From b3ae4feec5afe623183d92f8f3f9f0347f6abaea Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 7 Dec 2021 23:23:40 +0800 Subject: add linux driver example --- .gitignore | 7 + tests/projects/bpf/minimal/src/minimal.bpf.c | 21 - tests/projects/bpf/minimal/src/minimal.c | 73 - tests/projects/bpf/minimal/test.lua | 6 - tests/projects/bpf/minimal/xmake.lua | 19 - tests/projects/embed/mdk/hello/src/foo/foo.c | 4 + .../embed/mdk/hello/src/lib/cmsis/ARMCM3.h | 126 + .../embed/mdk/hello/src/lib/cmsis/cmsis_armcc.h | 888 ++ .../embed/mdk/hello/src/lib/cmsis/cmsis_armclang.h | 1503 +++ .../embed/mdk/hello/src/lib/cmsis/cmsis_compiler.h | 283 + .../embed/mdk/hello/src/lib/cmsis/cmsis_version.h | 39 + .../embed/mdk/hello/src/lib/cmsis/core_cm3.h | 1943 ++++ .../embed/mdk/hello/src/lib/cmsis/mpu_armv7.h | 275 + .../embed/mdk/hello/src/lib/cmsis/system_ARMCM3.h | 62 + tests/projects/embed/mdk/hello/src/main.c | 6 + .../projects/embed/mdk/hello/src/startup_ARMCM3.s | 172 + tests/projects/embed/mdk/hello/src/system_ARMCM3.c | 65 + tests/projects/embed/mdk/hello/xmake.lua | 13 + tests/projects/linux/bpf/minimal/src/minimal.bpf.c | 21 + tests/projects/linux/bpf/minimal/src/minimal.c | 73 + tests/projects/linux/bpf/minimal/test.lua | 6 + tests/projects/linux/bpf/minimal/xmake.lua | 19 + tests/projects/linux/driver/hello/Makefile | 13 + tests/projects/linux/driver/hello/hello.c | 21 + tests/projects/mdk/hello/src/foo/foo.c | 4 - tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h | 126 - .../projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h | 888 -- .../mdk/hello/src/lib/cmsis/cmsis_armclang.h | 1503 --- .../mdk/hello/src/lib/cmsis/cmsis_compiler.h | 283 - .../mdk/hello/src/lib/cmsis/cmsis_version.h | 39 - tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h | 1943 ---- tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h | 275 - .../mdk/hello/src/lib/cmsis/system_ARMCM3.h | 62 - tests/projects/mdk/hello/src/main.c | 6 - tests/projects/mdk/hello/src/startup_ARMCM3.s | 172 - tests/projects/mdk/hello/src/system_ARMCM3.c | 65 - tests/projects/mdk/hello/xmake.lua | 13 - tests/projects/wdk/kmdf/ioctl/driver/nonpnp.c | 1309 --- tests/projects/wdk/kmdf/ioctl/driver/nonpnp.h | 90 - tests/projects/wdk/kmdf/ioctl/driver/nonpnp.rc | 10 - tests/projects/wdk/kmdf/ioctl/driver/trace.h | 68 - tests/projects/wdk/kmdf/ioctl/exe/install.c | 812 -- tests/projects/wdk/kmdf/ioctl/exe/nonpnp.inf | 8 - tests/projects/wdk/kmdf/ioctl/exe/testapp.c | 643 -- tests/projects/wdk/kmdf/ioctl/localwpp.ini | 17 - tests/projects/wdk/kmdf/ioctl/public.h | 53 - tests/projects/wdk/kmdf/ioctl/xmake.lua | 15 - tests/projects/wdk/kmdf/serial/error.c | 67 - tests/projects/wdk/kmdf/serial/flush.c | 86 - tests/projects/wdk/kmdf/serial/immediat.c | 458 - tests/projects/wdk/kmdf/serial/initunlo.c | 197 - tests/projects/wdk/kmdf/serial/ioctl.c | 2187 ---- tests/projects/wdk/kmdf/serial/isr.c | 1517 --- tests/projects/wdk/kmdf/serial/log.c | 97 - tests/projects/wdk/kmdf/serial/log.h | 37 - tests/projects/wdk/kmdf/serial/modmflow.c | 1714 --- tests/projects/wdk/kmdf/serial/openclos.c | 850 -- tests/projects/wdk/kmdf/serial/pnp.c | 2804 ----- tests/projects/wdk/kmdf/serial/power.c | 331 - tests/projects/wdk/kmdf/serial/precomp.h | 18 - tests/projects/wdk/kmdf/serial/precompsrc.c | 1 - tests/projects/wdk/kmdf/serial/purge.c | 175 - tests/projects/wdk/kmdf/serial/qsfile.c | 180 - tests/projects/wdk/kmdf/serial/read.c | 1748 --- tests/projects/wdk/kmdf/serial/registry.c | 443 - tests/projects/wdk/kmdf/serial/serial.h | 1757 --- tests/projects/wdk/kmdf/serial/serial.inx | Bin 6212 -> 0 bytes tests/projects/wdk/kmdf/serial/serial.rc | 14 - tests/projects/wdk/kmdf/serial/serialp.h | 596 - tests/projects/wdk/kmdf/serial/serlog.mc | 290 - tests/projects/wdk/kmdf/serial/trace.h | 118 - tests/projects/wdk/kmdf/serial/utils.c | 1946 ---- tests/projects/wdk/kmdf/serial/waitmask.c | 574 - tests/projects/wdk/kmdf/serial/wmi.c | 295 - tests/projects/wdk/kmdf/serial/write.c | 1195 -- tests/projects/wdk/kmdf/serial/xmake.lua | 9 - tests/projects/wdk/umdf/echo/driver/device.c | 202 - tests/projects/wdk/umdf/echo/driver/device.h | 48 - tests/projects/wdk/umdf/echo/driver/driver.c | 192 - tests/projects/wdk/umdf/echo/driver/driver.h | 46 - tests/projects/wdk/umdf/echo/driver/echoum.inx | Bin 3924 -> 0 bytes tests/projects/wdk/umdf/echo/driver/queue.c | 538 - tests/projects/wdk/umdf/echo/driver/queue.h | 62 - tests/projects/wdk/umdf/echo/exe/echoapp.cpp | 652 -- tests/projects/wdk/umdf/echo/exe/public.h | 30 - tests/projects/wdk/umdf/echo/xmake.lua | 22 - tests/projects/wdk/umdf/skeleton/Skeleton.rc | 21 - .../wdk/umdf/skeleton/UMDFSkeleton_OSR.inx | Bin 5646 -> 0 bytes .../wdk/umdf/skeleton/UMDFSkeleton_Root.inx | Bin 3798 -> 0 bytes tests/projects/wdk/umdf/skeleton/comsup.cpp | 344 - tests/projects/wdk/umdf/skeleton/comsup.h | 215 - tests/projects/wdk/umdf/skeleton/device.cpp | 238 - tests/projects/wdk/umdf/skeleton/device.h | 115 - tests/projects/wdk/umdf/skeleton/dllsup.cpp | 177 - tests/projects/wdk/umdf/skeleton/driver.cpp | 220 - tests/projects/wdk/umdf/skeleton/driver.h | 149 - tests/projects/wdk/umdf/skeleton/exports.def | 10 - tests/projects/wdk/umdf/skeleton/internal.h | 90 - tests/projects/wdk/umdf/skeleton/xmake.lua | 13 - tests/projects/wdk/wdm/msdsm/SampleDSM.inf | Bin 5354 -> 0 bytes tests/projects/wdk/wdm/msdsm/dsmmain.c | 9752 ---------------- tests/projects/wdk/wdm/msdsm/dsmtrace.mof | 111 - tests/projects/wdk/wdm/msdsm/intrface.c | 5198 --------- tests/projects/wdk/wdm/msdsm/msdsm.h | 1403 --- tests/projects/wdk/wdm/msdsm/msdsm.mof | 82 - tests/projects/wdk/wdm/msdsm/msdsm.rc | 24 - tests/projects/wdk/wdm/msdsm/msdsmdsm.mof | 141 - tests/projects/wdk/wdm/msdsm/precomp.h | 34 - tests/projects/wdk/wdm/msdsm/precompsrc.c | 1 - tests/projects/wdk/wdm/msdsm/prototypes.h | 1436 --- tests/projects/wdk/wdm/msdsm/trace.h | 35 - tests/projects/wdk/wdm/msdsm/utils.c | 7946 ------------- tests/projects/wdk/wdm/msdsm/wmi.c | 3822 ------- tests/projects/wdk/wdm/msdsm/xmake.lua | 15 - tests/projects/wdk/wdm/perfcounters/kcs.c | 407 - tests/projects/wdk/wdm/perfcounters/kcs.h | 34 - tests/projects/wdk/wdm/perfcounters/kcs.man | 101 - tests/projects/wdk/wdm/perfcounters/kcs.rc | 1 - tests/projects/wdk/wdm/perfcounters/xmake.lua | 10 - .../windows/driver/kmdf/ioctl/driver/nonpnp.c | 1309 +++ .../windows/driver/kmdf/ioctl/driver/nonpnp.h | 90 + .../windows/driver/kmdf/ioctl/driver/nonpnp.rc | 10 + .../windows/driver/kmdf/ioctl/driver/trace.h | 68 + .../windows/driver/kmdf/ioctl/exe/install.c | 812 ++ .../windows/driver/kmdf/ioctl/exe/nonpnp.inf | 8 + .../windows/driver/kmdf/ioctl/exe/testapp.c | 643 ++ .../windows/driver/kmdf/ioctl/localwpp.ini | 17 + tests/projects/windows/driver/kmdf/ioctl/public.h | 53 + tests/projects/windows/driver/kmdf/ioctl/xmake.lua | 15 + tests/projects/windows/driver/kmdf/serial/error.c | 67 + tests/projects/windows/driver/kmdf/serial/flush.c | 86 + .../projects/windows/driver/kmdf/serial/immediat.c | 458 + .../projects/windows/driver/kmdf/serial/initunlo.c | 197 + tests/projects/windows/driver/kmdf/serial/ioctl.c | 2187 ++++ tests/projects/windows/driver/kmdf/serial/isr.c | 1517 +++ tests/projects/windows/driver/kmdf/serial/log.c | 97 + tests/projects/windows/driver/kmdf/serial/log.h | 37 + .../projects/windows/driver/kmdf/serial/modmflow.c | 1714 +++ .../projects/windows/driver/kmdf/serial/openclos.c | 850 ++ tests/projects/windows/driver/kmdf/serial/pnp.c | 2804 +++++ tests/projects/windows/driver/kmdf/serial/power.c | 331 + .../projects/windows/driver/kmdf/serial/precomp.h | 18 + .../windows/driver/kmdf/serial/precompsrc.c | 1 + tests/projects/windows/driver/kmdf/serial/purge.c | 175 + tests/projects/windows/driver/kmdf/serial/qsfile.c | 180 + tests/projects/windows/driver/kmdf/serial/read.c | 1748 +++ .../projects/windows/driver/kmdf/serial/registry.c | 443 + tests/projects/windows/driver/kmdf/serial/serial.h | 1757 +++ .../projects/windows/driver/kmdf/serial/serial.inx | Bin 0 -> 6212 bytes .../projects/windows/driver/kmdf/serial/serial.rc | 14 + .../projects/windows/driver/kmdf/serial/serialp.h | 596 + .../projects/windows/driver/kmdf/serial/serlog.mc | 290 + tests/projects/windows/driver/kmdf/serial/trace.h | 118 + tests/projects/windows/driver/kmdf/serial/utils.c | 1946 ++++ .../projects/windows/driver/kmdf/serial/waitmask.c | 574 + tests/projects/windows/driver/kmdf/serial/wmi.c | 295 + tests/projects/windows/driver/kmdf/serial/write.c | 1195 ++ .../projects/windows/driver/kmdf/serial/xmake.lua | 9 + .../windows/driver/umdf/echo/driver/device.c | 202 + .../windows/driver/umdf/echo/driver/device.h | 48 + .../windows/driver/umdf/echo/driver/driver.c | 192 + .../windows/driver/umdf/echo/driver/driver.h | 46 + .../windows/driver/umdf/echo/driver/echoum.inx | Bin 0 -> 3924 bytes .../windows/driver/umdf/echo/driver/queue.c | 538 + .../windows/driver/umdf/echo/driver/queue.h | 62 + .../windows/driver/umdf/echo/exe/echoapp.cpp | 652 ++ .../projects/windows/driver/umdf/echo/exe/public.h | 30 + tests/projects/windows/driver/umdf/echo/xmake.lua | 22 + .../windows/driver/umdf/skeleton/Skeleton.rc | 21 + .../driver/umdf/skeleton/UMDFSkeleton_OSR.inx | Bin 0 -> 5646 bytes .../driver/umdf/skeleton/UMDFSkeleton_Root.inx | Bin 0 -> 3798 bytes .../windows/driver/umdf/skeleton/comsup.cpp | 344 + .../projects/windows/driver/umdf/skeleton/comsup.h | 215 + .../windows/driver/umdf/skeleton/device.cpp | 238 + .../projects/windows/driver/umdf/skeleton/device.h | 115 + .../windows/driver/umdf/skeleton/dllsup.cpp | 177 + .../windows/driver/umdf/skeleton/driver.cpp | 220 + .../projects/windows/driver/umdf/skeleton/driver.h | 149 + .../windows/driver/umdf/skeleton/exports.def | 10 + .../windows/driver/umdf/skeleton/internal.h | 90 + .../windows/driver/umdf/skeleton/xmake.lua | 13 + .../windows/driver/wdm/msdsm/SampleDSM.inf | Bin 0 -> 5354 bytes tests/projects/windows/driver/wdm/msdsm/dsmmain.c | 9752 ++++++++++++++++ .../projects/windows/driver/wdm/msdsm/dsmtrace.mof | 111 + tests/projects/windows/driver/wdm/msdsm/intrface.c | 5198 +++++++++ tests/projects/windows/driver/wdm/msdsm/msdsm.h | 1403 +++ tests/projects/windows/driver/wdm/msdsm/msdsm.mof | 82 + tests/projects/windows/driver/wdm/msdsm/msdsm.rc | 24 + .../projects/windows/driver/wdm/msdsm/msdsmdsm.mof | 141 + tests/projects/windows/driver/wdm/msdsm/precomp.h | 34 + .../projects/windows/driver/wdm/msdsm/precompsrc.c | 1 + .../projects/windows/driver/wdm/msdsm/prototypes.h | 1436 +++ tests/projects/windows/driver/wdm/msdsm/trace.h | 35 + tests/projects/windows/driver/wdm/msdsm/utils.c | 7946 +++++++++++++ tests/projects/windows/driver/wdm/msdsm/wmi.c | 3822 +++++++ tests/projects/windows/driver/wdm/msdsm/xmake.lua | 15 + .../projects/windows/driver/wdm/perfcounters/kcs.c | 407 + .../projects/windows/driver/wdm/perfcounters/kcs.h | 34 + .../windows/driver/wdm/perfcounters/kcs.man | 101 + .../windows/driver/wdm/perfcounters/kcs.rc | 1 + .../windows/driver/wdm/perfcounters/xmake.lua | 10 + tests/projects/windows/winsdk/usbview/app.config | 12 + tests/projects/windows/winsdk/usbview/bang.ico | Bin 0 -> 1846 bytes .../projects/windows/winsdk/usbview/codeanalysis.h | 133 + tests/projects/windows/winsdk/usbview/debug.c | 210 + tests/projects/windows/winsdk/usbview/devnode.c | 336 + tests/projects/windows/winsdk/usbview/dispaud.c | 1164 ++ tests/projects/windows/winsdk/usbview/display.c | 5242 +++++++++ tests/projects/windows/winsdk/usbview/dispvid.c | 5649 ++++++++++ tests/projects/windows/winsdk/usbview/enum.c | 3366 ++++++ tests/projects/windows/winsdk/usbview/h264.c | 750 ++ tests/projects/windows/winsdk/usbview/h264.h | 164 + tests/projects/windows/winsdk/usbview/hub.ico | Bin 0 -> 766 bytes tests/projects/windows/winsdk/usbview/langidlist.h | 206 + tests/projects/windows/winsdk/usbview/monitor.ico | Bin 0 -> 10134 bytes tests/projects/windows/winsdk/usbview/port.ico | Bin 0 -> 766 bytes tests/projects/windows/winsdk/usbview/resource.h | 51 + tests/projects/windows/winsdk/usbview/split.cur | Bin 0 -> 326 bytes tests/projects/windows/winsdk/usbview/ssport.ico | Bin 0 -> 766 bytes tests/projects/windows/winsdk/usbview/ssusb.ico | Bin 0 -> 766 bytes tests/projects/windows/winsdk/usbview/usb.ico | Bin 0 -> 766 bytes tests/projects/windows/winsdk/usbview/usbdesc.h | 394 + .../projects/windows/winsdk/usbview/usbschema.hpp | 6119 ++++++++++ tests/projects/windows/winsdk/usbview/usbviddesc.h | 743 ++ tests/projects/windows/winsdk/usbview/uvcdesc.h | 1106 ++ tests/projects/windows/winsdk/usbview/uvcview.c | 2153 ++++ tests/projects/windows/winsdk/usbview/uvcview.h | 675 ++ tests/projects/windows/winsdk/usbview/uvcview.rc | 152 + tests/projects/windows/winsdk/usbview/vndrlist.h | 11036 +++++++++++++++++++ tests/projects/windows/winsdk/usbview/xmake.lua | 13 + .../projects/windows/winsdk/usbview/xmlhelper.cpp | 3235 ++++++ tests/projects/windows/winsdk/usbview/xmlhelper.h | 41 + tests/projects/windows/winsdk/windemo/main.cpp | 190 + tests/projects/windows/winsdk/windemo/resource.h | 31 + tests/projects/windows/winsdk/windemo/small.ico | Bin 0 -> 23558 bytes tests/projects/windows/winsdk/windemo/stdafx.cpp | 8 + tests/projects/windows/winsdk/windemo/stdafx.h | 21 + tests/projects/windows/winsdk/windemo/targetver.h | 24 + tests/projects/windows/winsdk/windemo/test | 150 + tests/projects/windows/winsdk/windemo/test.h | 3 + tests/projects/windows/winsdk/windemo/test.ico | Bin 0 -> 23558 bytes tests/projects/windows/winsdk/windemo/test.rc | 150 + tests/projects/windows/winsdk/windemo/xmake.lua | 12 + tests/projects/winsdk/usbview/app.config | 12 - tests/projects/winsdk/usbview/bang.ico | Bin 1846 -> 0 bytes tests/projects/winsdk/usbview/codeanalysis.h | 133 - tests/projects/winsdk/usbview/debug.c | 210 - tests/projects/winsdk/usbview/devnode.c | 336 - tests/projects/winsdk/usbview/dispaud.c | 1164 -- tests/projects/winsdk/usbview/display.c | 5242 --------- tests/projects/winsdk/usbview/dispvid.c | 5649 ---------- tests/projects/winsdk/usbview/enum.c | 3366 ------ tests/projects/winsdk/usbview/h264.c | 750 -- tests/projects/winsdk/usbview/h264.h | 164 - tests/projects/winsdk/usbview/hub.ico | Bin 766 -> 0 bytes tests/projects/winsdk/usbview/langidlist.h | 206 - tests/projects/winsdk/usbview/monitor.ico | Bin 10134 -> 0 bytes tests/projects/winsdk/usbview/port.ico | Bin 766 -> 0 bytes tests/projects/winsdk/usbview/resource.h | 51 - tests/projects/winsdk/usbview/split.cur | Bin 326 -> 0 bytes tests/projects/winsdk/usbview/ssport.ico | Bin 766 -> 0 bytes tests/projects/winsdk/usbview/ssusb.ico | Bin 766 -> 0 bytes tests/projects/winsdk/usbview/usb.ico | Bin 766 -> 0 bytes tests/projects/winsdk/usbview/usbdesc.h | 394 - tests/projects/winsdk/usbview/usbschema.hpp | 6119 ---------- tests/projects/winsdk/usbview/usbviddesc.h | 743 -- tests/projects/winsdk/usbview/uvcdesc.h | 1106 -- tests/projects/winsdk/usbview/uvcview.c | 2153 ---- tests/projects/winsdk/usbview/uvcview.h | 675 -- tests/projects/winsdk/usbview/uvcview.rc | 152 - tests/projects/winsdk/usbview/vndrlist.h | 11036 ------------------- tests/projects/winsdk/usbview/xmake.lua | 13 - tests/projects/winsdk/usbview/xmlhelper.cpp | 3235 ------ tests/projects/winsdk/usbview/xmlhelper.h | 41 - tests/projects/winsdk/windemo/main.cpp | 190 - tests/projects/winsdk/windemo/resource.h | 31 - tests/projects/winsdk/windemo/small.ico | Bin 23558 -> 0 bytes tests/projects/winsdk/windemo/stdafx.cpp | 8 - tests/projects/winsdk/windemo/stdafx.h | 21 - tests/projects/winsdk/windemo/targetver.h | 24 - tests/projects/winsdk/windemo/test | 150 - tests/projects/winsdk/windemo/test.h | 3 - tests/projects/winsdk/windemo/test.ico | Bin 23558 -> 0 bytes tests/projects/winsdk/windemo/test.rc | 150 - tests/projects/winsdk/windemo/xmake.lua | 12 - 285 files changed, 105744 insertions(+), 105703 deletions(-) delete mode 100644 tests/projects/bpf/minimal/src/minimal.bpf.c delete mode 100644 tests/projects/bpf/minimal/src/minimal.c delete mode 100644 tests/projects/bpf/minimal/test.lua delete mode 100644 tests/projects/bpf/minimal/xmake.lua create mode 100644 tests/projects/embed/mdk/hello/src/foo/foo.c create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/ARMCM3.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armcc.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armclang.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_compiler.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_version.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/core_cm3.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/mpu_armv7.h create mode 100644 tests/projects/embed/mdk/hello/src/lib/cmsis/system_ARMCM3.h create mode 100644 tests/projects/embed/mdk/hello/src/main.c create mode 100644 tests/projects/embed/mdk/hello/src/startup_ARMCM3.s create mode 100644 tests/projects/embed/mdk/hello/src/system_ARMCM3.c create mode 100644 tests/projects/embed/mdk/hello/xmake.lua create mode 100644 tests/projects/linux/bpf/minimal/src/minimal.bpf.c create mode 100644 tests/projects/linux/bpf/minimal/src/minimal.c create mode 100644 tests/projects/linux/bpf/minimal/test.lua create mode 100644 tests/projects/linux/bpf/minimal/xmake.lua create mode 100644 tests/projects/linux/driver/hello/Makefile create mode 100644 tests/projects/linux/driver/hello/hello.c delete mode 100644 tests/projects/mdk/hello/src/foo/foo.c delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_armclang.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_compiler.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/cmsis_version.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h delete mode 100644 tests/projects/mdk/hello/src/lib/cmsis/system_ARMCM3.h delete mode 100644 tests/projects/mdk/hello/src/main.c delete mode 100644 tests/projects/mdk/hello/src/startup_ARMCM3.s delete mode 100644 tests/projects/mdk/hello/src/system_ARMCM3.c delete mode 100644 tests/projects/mdk/hello/xmake.lua delete mode 100644 tests/projects/wdk/kmdf/ioctl/driver/nonpnp.c delete mode 100644 tests/projects/wdk/kmdf/ioctl/driver/nonpnp.h delete mode 100644 tests/projects/wdk/kmdf/ioctl/driver/nonpnp.rc delete mode 100644 tests/projects/wdk/kmdf/ioctl/driver/trace.h delete mode 100644 tests/projects/wdk/kmdf/ioctl/exe/install.c delete mode 100644 tests/projects/wdk/kmdf/ioctl/exe/nonpnp.inf delete mode 100644 tests/projects/wdk/kmdf/ioctl/exe/testapp.c delete mode 100644 tests/projects/wdk/kmdf/ioctl/localwpp.ini delete mode 100644 tests/projects/wdk/kmdf/ioctl/public.h delete mode 100644 tests/projects/wdk/kmdf/ioctl/xmake.lua delete mode 100644 tests/projects/wdk/kmdf/serial/error.c delete mode 100644 tests/projects/wdk/kmdf/serial/flush.c delete mode 100644 tests/projects/wdk/kmdf/serial/immediat.c delete mode 100644 tests/projects/wdk/kmdf/serial/initunlo.c delete mode 100644 tests/projects/wdk/kmdf/serial/ioctl.c delete mode 100644 tests/projects/wdk/kmdf/serial/isr.c delete mode 100644 tests/projects/wdk/kmdf/serial/log.c delete mode 100644 tests/projects/wdk/kmdf/serial/log.h delete mode 100644 tests/projects/wdk/kmdf/serial/modmflow.c delete mode 100644 tests/projects/wdk/kmdf/serial/openclos.c delete mode 100644 tests/projects/wdk/kmdf/serial/pnp.c delete mode 100644 tests/projects/wdk/kmdf/serial/power.c delete mode 100644 tests/projects/wdk/kmdf/serial/precomp.h delete mode 100644 tests/projects/wdk/kmdf/serial/precompsrc.c delete mode 100644 tests/projects/wdk/kmdf/serial/purge.c delete mode 100644 tests/projects/wdk/kmdf/serial/qsfile.c delete mode 100644 tests/projects/wdk/kmdf/serial/read.c delete mode 100644 tests/projects/wdk/kmdf/serial/registry.c delete mode 100644 tests/projects/wdk/kmdf/serial/serial.h delete mode 100644 tests/projects/wdk/kmdf/serial/serial.inx delete mode 100644 tests/projects/wdk/kmdf/serial/serial.rc delete mode 100644 tests/projects/wdk/kmdf/serial/serialp.h delete mode 100644 tests/projects/wdk/kmdf/serial/serlog.mc delete mode 100644 tests/projects/wdk/kmdf/serial/trace.h delete mode 100644 tests/projects/wdk/kmdf/serial/utils.c delete mode 100644 tests/projects/wdk/kmdf/serial/waitmask.c delete mode 100644 tests/projects/wdk/kmdf/serial/wmi.c delete mode 100644 tests/projects/wdk/kmdf/serial/write.c delete mode 100644 tests/projects/wdk/kmdf/serial/xmake.lua delete mode 100644 tests/projects/wdk/umdf/echo/driver/device.c delete mode 100644 tests/projects/wdk/umdf/echo/driver/device.h delete mode 100644 tests/projects/wdk/umdf/echo/driver/driver.c delete mode 100644 tests/projects/wdk/umdf/echo/driver/driver.h delete mode 100644 tests/projects/wdk/umdf/echo/driver/echoum.inx delete mode 100644 tests/projects/wdk/umdf/echo/driver/queue.c delete mode 100644 tests/projects/wdk/umdf/echo/driver/queue.h delete mode 100644 tests/projects/wdk/umdf/echo/exe/echoapp.cpp delete mode 100644 tests/projects/wdk/umdf/echo/exe/public.h delete mode 100644 tests/projects/wdk/umdf/echo/xmake.lua delete mode 100644 tests/projects/wdk/umdf/skeleton/Skeleton.rc delete mode 100644 tests/projects/wdk/umdf/skeleton/UMDFSkeleton_OSR.inx delete mode 100644 tests/projects/wdk/umdf/skeleton/UMDFSkeleton_Root.inx delete mode 100644 tests/projects/wdk/umdf/skeleton/comsup.cpp delete mode 100644 tests/projects/wdk/umdf/skeleton/comsup.h delete mode 100644 tests/projects/wdk/umdf/skeleton/device.cpp delete mode 100644 tests/projects/wdk/umdf/skeleton/device.h delete mode 100644 tests/projects/wdk/umdf/skeleton/dllsup.cpp delete mode 100644 tests/projects/wdk/umdf/skeleton/driver.cpp delete mode 100644 tests/projects/wdk/umdf/skeleton/driver.h delete mode 100644 tests/projects/wdk/umdf/skeleton/exports.def delete mode 100644 tests/projects/wdk/umdf/skeleton/internal.h delete mode 100644 tests/projects/wdk/umdf/skeleton/xmake.lua delete mode 100644 tests/projects/wdk/wdm/msdsm/SampleDSM.inf delete mode 100644 tests/projects/wdk/wdm/msdsm/dsmmain.c delete mode 100644 tests/projects/wdk/wdm/msdsm/dsmtrace.mof delete mode 100644 tests/projects/wdk/wdm/msdsm/intrface.c delete mode 100644 tests/projects/wdk/wdm/msdsm/msdsm.h delete mode 100644 tests/projects/wdk/wdm/msdsm/msdsm.mof delete mode 100644 tests/projects/wdk/wdm/msdsm/msdsm.rc delete mode 100644 tests/projects/wdk/wdm/msdsm/msdsmdsm.mof delete mode 100644 tests/projects/wdk/wdm/msdsm/precomp.h delete mode 100644 tests/projects/wdk/wdm/msdsm/precompsrc.c delete mode 100644 tests/projects/wdk/wdm/msdsm/prototypes.h delete mode 100644 tests/projects/wdk/wdm/msdsm/trace.h delete mode 100644 tests/projects/wdk/wdm/msdsm/utils.c delete mode 100644 tests/projects/wdk/wdm/msdsm/wmi.c delete mode 100644 tests/projects/wdk/wdm/msdsm/xmake.lua delete mode 100644 tests/projects/wdk/wdm/perfcounters/kcs.c delete mode 100644 tests/projects/wdk/wdm/perfcounters/kcs.h delete mode 100644 tests/projects/wdk/wdm/perfcounters/kcs.man delete mode 100644 tests/projects/wdk/wdm/perfcounters/kcs.rc delete mode 100644 tests/projects/wdk/wdm/perfcounters/xmake.lua create mode 100644 tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.c create mode 100644 tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.h create mode 100644 tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.rc create mode 100644 tests/projects/windows/driver/kmdf/ioctl/driver/trace.h create mode 100644 tests/projects/windows/driver/kmdf/ioctl/exe/install.c create mode 100644 tests/projects/windows/driver/kmdf/ioctl/exe/nonpnp.inf create mode 100644 tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c create mode 100644 tests/projects/windows/driver/kmdf/ioctl/localwpp.ini create mode 100644 tests/projects/windows/driver/kmdf/ioctl/public.h create mode 100644 tests/projects/windows/driver/kmdf/ioctl/xmake.lua create mode 100644 tests/projects/windows/driver/kmdf/serial/error.c create mode 100644 tests/projects/windows/driver/kmdf/serial/flush.c create mode 100644 tests/projects/windows/driver/kmdf/serial/immediat.c create mode 100644 tests/projects/windows/driver/kmdf/serial/initunlo.c create mode 100644 tests/projects/windows/driver/kmdf/serial/ioctl.c create mode 100644 tests/projects/windows/driver/kmdf/serial/isr.c create mode 100644 tests/projects/windows/driver/kmdf/serial/log.c create mode 100644 tests/projects/windows/driver/kmdf/serial/log.h create mode 100644 tests/projects/windows/driver/kmdf/serial/modmflow.c create mode 100644 tests/projects/windows/driver/kmdf/serial/openclos.c create mode 100644 tests/projects/windows/driver/kmdf/serial/pnp.c create mode 100644 tests/projects/windows/driver/kmdf/serial/power.c create mode 100644 tests/projects/windows/driver/kmdf/serial/precomp.h create mode 100644 tests/projects/windows/driver/kmdf/serial/precompsrc.c create mode 100644 tests/projects/windows/driver/kmdf/serial/purge.c create mode 100644 tests/projects/windows/driver/kmdf/serial/qsfile.c create mode 100644 tests/projects/windows/driver/kmdf/serial/read.c create mode 100644 tests/projects/windows/driver/kmdf/serial/registry.c create mode 100644 tests/projects/windows/driver/kmdf/serial/serial.h create mode 100644 tests/projects/windows/driver/kmdf/serial/serial.inx create mode 100644 tests/projects/windows/driver/kmdf/serial/serial.rc create mode 100644 tests/projects/windows/driver/kmdf/serial/serialp.h create mode 100644 tests/projects/windows/driver/kmdf/serial/serlog.mc create mode 100644 tests/projects/windows/driver/kmdf/serial/trace.h create mode 100644 tests/projects/windows/driver/kmdf/serial/utils.c create mode 100644 tests/projects/windows/driver/kmdf/serial/waitmask.c create mode 100644 tests/projects/windows/driver/kmdf/serial/wmi.c create mode 100644 tests/projects/windows/driver/kmdf/serial/write.c create mode 100644 tests/projects/windows/driver/kmdf/serial/xmake.lua create mode 100644 tests/projects/windows/driver/umdf/echo/driver/device.c create mode 100644 tests/projects/windows/driver/umdf/echo/driver/device.h create mode 100644 tests/projects/windows/driver/umdf/echo/driver/driver.c create mode 100644 tests/projects/windows/driver/umdf/echo/driver/driver.h create mode 100644 tests/projects/windows/driver/umdf/echo/driver/echoum.inx create mode 100644 tests/projects/windows/driver/umdf/echo/driver/queue.c create mode 100644 tests/projects/windows/driver/umdf/echo/driver/queue.h create mode 100644 tests/projects/windows/driver/umdf/echo/exe/echoapp.cpp create mode 100644 tests/projects/windows/driver/umdf/echo/exe/public.h create mode 100644 tests/projects/windows/driver/umdf/echo/xmake.lua create mode 100644 tests/projects/windows/driver/umdf/skeleton/Skeleton.rc create mode 100644 tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_OSR.inx create mode 100644 tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_Root.inx create mode 100644 tests/projects/windows/driver/umdf/skeleton/comsup.cpp create mode 100644 tests/projects/windows/driver/umdf/skeleton/comsup.h create mode 100644 tests/projects/windows/driver/umdf/skeleton/device.cpp create mode 100644 tests/projects/windows/driver/umdf/skeleton/device.h create mode 100644 tests/projects/windows/driver/umdf/skeleton/dllsup.cpp create mode 100644 tests/projects/windows/driver/umdf/skeleton/driver.cpp create mode 100644 tests/projects/windows/driver/umdf/skeleton/driver.h create mode 100644 tests/projects/windows/driver/umdf/skeleton/exports.def create mode 100644 tests/projects/windows/driver/umdf/skeleton/internal.h create mode 100644 tests/projects/windows/driver/umdf/skeleton/xmake.lua create mode 100644 tests/projects/windows/driver/wdm/msdsm/SampleDSM.inf create mode 100644 tests/projects/windows/driver/wdm/msdsm/dsmmain.c create mode 100644 tests/projects/windows/driver/wdm/msdsm/dsmtrace.mof create mode 100644 tests/projects/windows/driver/wdm/msdsm/intrface.c create mode 100644 tests/projects/windows/driver/wdm/msdsm/msdsm.h create mode 100644 tests/projects/windows/driver/wdm/msdsm/msdsm.mof create mode 100644 tests/projects/windows/driver/wdm/msdsm/msdsm.rc create mode 100644 tests/projects/windows/driver/wdm/msdsm/msdsmdsm.mof create mode 100644 tests/projects/windows/driver/wdm/msdsm/precomp.h create mode 100644 tests/projects/windows/driver/wdm/msdsm/precompsrc.c create mode 100644 tests/projects/windows/driver/wdm/msdsm/prototypes.h create mode 100644 tests/projects/windows/driver/wdm/msdsm/trace.h create mode 100644 tests/projects/windows/driver/wdm/msdsm/utils.c create mode 100644 tests/projects/windows/driver/wdm/msdsm/wmi.c create mode 100644 tests/projects/windows/driver/wdm/msdsm/xmake.lua create mode 100644 tests/projects/windows/driver/wdm/perfcounters/kcs.c create mode 100644 tests/projects/windows/driver/wdm/perfcounters/kcs.h create mode 100644 tests/projects/windows/driver/wdm/perfcounters/kcs.man create mode 100644 tests/projects/windows/driver/wdm/perfcounters/kcs.rc create mode 100644 tests/projects/windows/driver/wdm/perfcounters/xmake.lua create mode 100644 tests/projects/windows/winsdk/usbview/app.config create mode 100644 tests/projects/windows/winsdk/usbview/bang.ico create mode 100644 tests/projects/windows/winsdk/usbview/codeanalysis.h create mode 100644 tests/projects/windows/winsdk/usbview/debug.c create mode 100644 tests/projects/windows/winsdk/usbview/devnode.c create mode 100644 tests/projects/windows/winsdk/usbview/dispaud.c create mode 100644 tests/projects/windows/winsdk/usbview/display.c create mode 100644 tests/projects/windows/winsdk/usbview/dispvid.c create mode 100644 tests/projects/windows/winsdk/usbview/enum.c create mode 100644 tests/projects/windows/winsdk/usbview/h264.c create mode 100644 tests/projects/windows/winsdk/usbview/h264.h create mode 100644 tests/projects/windows/winsdk/usbview/hub.ico create mode 100644 tests/projects/windows/winsdk/usbview/langidlist.h create mode 100644 tests/projects/windows/winsdk/usbview/monitor.ico create mode 100644 tests/projects/windows/winsdk/usbview/port.ico create mode 100644 tests/projects/windows/winsdk/usbview/resource.h create mode 100644 tests/projects/windows/winsdk/usbview/split.cur create mode 100644 tests/projects/windows/winsdk/usbview/ssport.ico create mode 100644 tests/projects/windows/winsdk/usbview/ssusb.ico create mode 100644 tests/projects/windows/winsdk/usbview/usb.ico create mode 100644 tests/projects/windows/winsdk/usbview/usbdesc.h create mode 100644 tests/projects/windows/winsdk/usbview/usbschema.hpp create mode 100644 tests/projects/windows/winsdk/usbview/usbviddesc.h create mode 100644 tests/projects/windows/winsdk/usbview/uvcdesc.h create mode 100644 tests/projects/windows/winsdk/usbview/uvcview.c create mode 100644 tests/projects/windows/winsdk/usbview/uvcview.h create mode 100644 tests/projects/windows/winsdk/usbview/uvcview.rc create mode 100644 tests/projects/windows/winsdk/usbview/vndrlist.h create mode 100644 tests/projects/windows/winsdk/usbview/xmake.lua create mode 100644 tests/projects/windows/winsdk/usbview/xmlhelper.cpp create mode 100644 tests/projects/windows/winsdk/usbview/xmlhelper.h create mode 100644 tests/projects/windows/winsdk/windemo/main.cpp create mode 100644 tests/projects/windows/winsdk/windemo/resource.h create mode 100644 tests/projects/windows/winsdk/windemo/small.ico create mode 100644 tests/projects/windows/winsdk/windemo/stdafx.cpp create mode 100644 tests/projects/windows/winsdk/windemo/stdafx.h create mode 100644 tests/projects/windows/winsdk/windemo/targetver.h create mode 100644 tests/projects/windows/winsdk/windemo/test create mode 100644 tests/projects/windows/winsdk/windemo/test.h create mode 100644 tests/projects/windows/winsdk/windemo/test.ico create mode 100644 tests/projects/windows/winsdk/windemo/test.rc create mode 100644 tests/projects/windows/winsdk/windemo/xmake.lua delete mode 100644 tests/projects/winsdk/usbview/app.config delete mode 100644 tests/projects/winsdk/usbview/bang.ico delete mode 100644 tests/projects/winsdk/usbview/codeanalysis.h delete mode 100644 tests/projects/winsdk/usbview/debug.c delete mode 100644 tests/projects/winsdk/usbview/devnode.c delete mode 100644 tests/projects/winsdk/usbview/dispaud.c delete mode 100644 tests/projects/winsdk/usbview/display.c delete mode 100644 tests/projects/winsdk/usbview/dispvid.c delete mode 100644 tests/projects/winsdk/usbview/enum.c delete mode 100644 tests/projects/winsdk/usbview/h264.c delete mode 100644 tests/projects/winsdk/usbview/h264.h delete mode 100644 tests/projects/winsdk/usbview/hub.ico delete mode 100644 tests/projects/winsdk/usbview/langidlist.h delete mode 100644 tests/projects/winsdk/usbview/monitor.ico delete mode 100644 tests/projects/winsdk/usbview/port.ico delete mode 100644 tests/projects/winsdk/usbview/resource.h delete mode 100644 tests/projects/winsdk/usbview/split.cur delete mode 100644 tests/projects/winsdk/usbview/ssport.ico delete mode 100644 tests/projects/winsdk/usbview/ssusb.ico delete mode 100644 tests/projects/winsdk/usbview/usb.ico delete mode 100644 tests/projects/winsdk/usbview/usbdesc.h delete mode 100644 tests/projects/winsdk/usbview/usbschema.hpp delete mode 100644 tests/projects/winsdk/usbview/usbviddesc.h delete mode 100644 tests/projects/winsdk/usbview/uvcdesc.h delete mode 100644 tests/projects/winsdk/usbview/uvcview.c delete mode 100644 tests/projects/winsdk/usbview/uvcview.h delete mode 100644 tests/projects/winsdk/usbview/uvcview.rc delete mode 100644 tests/projects/winsdk/usbview/vndrlist.h delete mode 100644 tests/projects/winsdk/usbview/xmake.lua delete mode 100644 tests/projects/winsdk/usbview/xmlhelper.cpp delete mode 100644 tests/projects/winsdk/usbview/xmlhelper.h delete mode 100644 tests/projects/winsdk/windemo/main.cpp delete mode 100644 tests/projects/winsdk/windemo/resource.h delete mode 100644 tests/projects/winsdk/windemo/small.ico delete mode 100644 tests/projects/winsdk/windemo/stdafx.cpp delete mode 100644 tests/projects/winsdk/windemo/stdafx.h delete mode 100644 tests/projects/winsdk/windemo/targetver.h delete mode 100644 tests/projects/winsdk/windemo/test delete mode 100644 tests/projects/winsdk/windemo/test.h delete mode 100644 tests/projects/winsdk/windemo/test.ico delete mode 100644 tests/projects/winsdk/windemo/test.rc delete mode 100644 tests/projects/winsdk/windemo/xmake.lua diff --git a/.gitignore b/.gitignore index 7107445a1..a8573ebd9 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,10 @@ compile_commands.json /scripts/rpmbuild/SRPMS/* !/xmake/actions/build/ + +# for linux driver +*.ko +*.mod +.*.cmd +Module.symvers +modules.order diff --git a/tests/projects/bpf/minimal/src/minimal.bpf.c b/tests/projects/bpf/minimal/src/minimal.bpf.c deleted file mode 100644 index ea1eeefbb..000000000 --- a/tests/projects/bpf/minimal/src/minimal.bpf.c +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2020 Facebook */ -#include -#include - -char LICENSE[] SEC("license") = "Dual BSD/GPL"; - -int my_pid = 0; - -SEC("tp/syscalls/sys_enter_write") -int handle_tp(void *ctx) -{ - int pid = bpf_get_current_pid_tgid() >> 32; - - if (pid != my_pid) - return 0; - - bpf_printk("BPF triggered from PID %d.\n", pid); - - return 0; -} diff --git a/tests/projects/bpf/minimal/src/minimal.c b/tests/projects/bpf/minimal/src/minimal.c deleted file mode 100644 index 4b6ec3181..000000000 --- a/tests/projects/bpf/minimal/src/minimal.c +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) -/* Copyright (c) 2020 Facebook */ -#include -#include -#include -#include -#include "minimal.skel.h" - -static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) -{ - return vfprintf(stderr, format, args); -} - -static void bump_memlock_rlimit(void) -{ - struct rlimit rlim_new = { - .rlim_cur = RLIM_INFINITY, - .rlim_max = RLIM_INFINITY, - }; - - if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { - fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); - exit(1); - } -} - -int main(int argc, char **argv) -{ - struct minimal_bpf *skel; - int err; - - /* Set up libbpf errors and debug info callback */ - libbpf_set_print(libbpf_print_fn); - - /* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */ - bump_memlock_rlimit(); - - /* Open BPF application */ - skel = minimal_bpf__open(); - if (!skel) { - fprintf(stderr, "Failed to open BPF skeleton\n"); - return 1; - } - - /* ensure BPF program only handles write() syscalls from our process */ - skel->bss->my_pid = getpid(); - - /* Load & verify BPF programs */ - err = minimal_bpf__load(skel); - if (err) { - fprintf(stderr, "Failed to load and verify BPF skeleton\n"); - goto cleanup; - } - - /* Attach tracepoint handler */ - err = minimal_bpf__attach(skel); - if (err) { - fprintf(stderr, "Failed to attach BPF skeleton\n"); - goto cleanup; - } - - printf("Successfully started!\n"); - - for (;;) { - /* trigger our BPF program */ - fprintf(stderr, "."); - sleep(1); - } - -cleanup: - minimal_bpf__destroy(skel); - return -err; -} diff --git a/tests/projects/bpf/minimal/test.lua b/tests/projects/bpf/minimal/test.lua deleted file mode 100644 index 2856a3831..000000000 --- a/tests/projects/bpf/minimal/test.lua +++ /dev/null @@ -1,6 +0,0 @@ -function main(t) - if is_host("linux") and os.arch() == "x86_64" then - os.vrun("xmake f -y -p android -vD") - os.vrun("xmake -y -vD") - end -end diff --git a/tests/projects/bpf/minimal/xmake.lua b/tests/projects/bpf/minimal/xmake.lua deleted file mode 100644 index 8507b8aa1..000000000 --- a/tests/projects/bpf/minimal/xmake.lua +++ /dev/null @@ -1,19 +0,0 @@ -add_rules("mode.release", "mode.debug") -add_rules("platform.linux.bpf") - -add_requires("linux-tools", {configs = {bpftool = true}}) -add_requires("libbpf") -if is_plat("android") then - add_requires("ndk >=22.x") - set_toolchains("@ndk", {sdkver = "23"}) -else - add_requires("llvm >=10.x") - set_toolchains("@llvm") - add_requires("linux-headers") -end - -target("minimal") - set_kind("binary") - add_files("src/*.c") - add_packages("linux-tools", "linux-headers", "libbpf") - set_license("GPL-2.0") diff --git a/tests/projects/embed/mdk/hello/src/foo/foo.c b/tests/projects/embed/mdk/hello/src/foo/foo.c new file mode 100644 index 000000000..e51afb553 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/foo/foo.c @@ -0,0 +1,4 @@ +int foo(int x) +{ + return x; +} diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/ARMCM3.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/ARMCM3.h new file mode 100644 index 000000000..44c0c23f4 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/ARMCM3.h @@ -0,0 +1,126 @@ +/**************************************************************************//** + * @file ARMCM3.h + * @brief CMSIS Core Peripheral Access Layer Header File for + * ARMCM3 Device + * @version V5.3.1 + * @date 09. July 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ARMCM3_H +#define ARMCM3_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ------------------------- Interrupt Number Definition ------------------------ */ + +typedef enum IRQn +{ +/* ------------------- Processor Exceptions Numbers ----------------------------- */ + NonMaskableInt_IRQn = -14, /* 2 Non Maskable Interrupt */ + HardFault_IRQn = -13, /* 3 HardFault Interrupt */ + MemoryManagement_IRQn = -12, /* 4 Memory Management Interrupt */ + BusFault_IRQn = -11, /* 5 Bus Fault Interrupt */ + UsageFault_IRQn = -10, /* 6 Usage Fault Interrupt */ + SVCall_IRQn = -5, /* 11 SV Call Interrupt */ + DebugMonitor_IRQn = -4, /* 12 Debug Monitor Interrupt */ + PendSV_IRQn = -2, /* 14 Pend SV Interrupt */ + SysTick_IRQn = -1, /* 15 System Tick Interrupt */ + +/* ------------------- Processor Interrupt Numbers ------------------------------ */ + Interrupt0_IRQn = 0, + Interrupt1_IRQn = 1, + Interrupt2_IRQn = 2, + Interrupt3_IRQn = 3, + Interrupt4_IRQn = 4, + Interrupt5_IRQn = 5, + Interrupt6_IRQn = 6, + Interrupt7_IRQn = 7, + Interrupt8_IRQn = 8, + Interrupt9_IRQn = 9 + /* Interrupts 10 .. 224 are left out */ +} IRQn_Type; + + +/* ================================================================================ */ +/* ================ Processor and Core Peripheral Section ================ */ +/* ================================================================================ */ + +/* ------- Start of section using anonymous unions and disabling warnings ------- */ +#if defined (__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined (__ICCARM__) + #pragma language=extended +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wc11-extensions" + #pragma clang diagnostic ignored "-Wreserved-id-macro" +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning 586 +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +/* -------- Configuration of Core Peripherals ----------------------------------- */ +#define __CM3_REV 0x0201U /* Core revision r2p1 */ +#define __MPU_PRESENT 1U /* MPU present */ +#define __VTOR_PRESENT 1U /* VTOR present */ +#define __NVIC_PRIO_BITS 3U /* Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick Config is used */ + +#include "core_cm3.h" /* Processor and core peripherals */ +#include "system_ARMCM3.h" /* System Header */ + + +/* -------- End of section using anonymous unions and disabling warnings -------- */ +#if defined (__CC_ARM) + #pragma pop +#elif defined (__ICCARM__) + /* leave anonymous unions enabled */ +#elif (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) + #pragma clang diagnostic pop +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning restore +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* ARMCM3_H */ diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armcc.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armcc.h new file mode 100644 index 000000000..a955d4713 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armcc.h @@ -0,0 +1,888 @@ +/**************************************************************************//** + * @file cmsis_armcc.h + * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file + * @version V5.3.2 + * @date 27. May 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_ARMCC_H +#define __CMSIS_ARMCC_H + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) + #error "Please use Arm Compiler Toolchain V4.0.677 or later!" +#endif + +/* CMSIS compiler control architecture macros */ +#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ + (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) + #define __ARM_ARCH_6M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) + #define __ARM_ARCH_7M__ 1 +#endif + +#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) + #define __ARM_ARCH_7EM__ 1 +#endif + + /* __ARM_ARCH_8M_BASE__ not applicable */ + /* __ARM_ARCH_8M_MAIN__ not applicable */ + /* __ARM_ARCH_8_1M_MAIN__ not applicable */ + +/* CMSIS compiler control DSP macros */ +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __ARM_FEATURE_DSP 1 +#endif + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static __forceinline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __declspec(noreturn) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed)) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT __packed struct +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION __packed union +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __memory_changed() +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __nop + + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __dsb(0xF) + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV __rev + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) +{ + rev16 r0, r0 + bx lr +} +#endif + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) +{ + revsh r0, r0 + bx lr +} +#endif + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +#define __ROR __ror + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __breakpoint(value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + #define __RBIT __rbit +#else +__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) +{ + uint32_t result; + uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ + + result = value; /* r will be reversed bits of v; first get LSB of v */ + for (value >>= 1U; value != 0U; value >>= 1U) + { + result <<= 1U; + result |= value & 1U; + s--; + } + result <<= s; /* shift when v's highest bits are zero */ + return result; +} +#endif + + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +#define __CLZ __clz + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) +#else + #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) +#else + #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) +#else + #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXB(value, ptr) __strex(value, ptr) +#else + #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXH(value, ptr) __strex(value, ptr) +#else + #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) + #define __STREXW(value, ptr) __strex(value, ptr) +#else + #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") +#endif + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __clrex + + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +#ifndef __NO_EMBEDDED_ASM +__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) +{ + rrx r0, r0 + bx lr +} +#endif + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRBT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRHT(value, ptr) __strt(value, ptr) + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +#define __STRT(value, ptr) __strt(value, ptr) + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __enable_irq(); */ + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +/* intrinsic void __disable_irq(); */ + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_INLINE uint32_t __get_CONTROL(void) +{ + register uint32_t __regControl __ASM("control"); + return(__regControl); +} + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_INLINE void __set_CONTROL(uint32_t control) +{ + register uint32_t __regControl __ASM("control"); + __regControl = control; + __ISB(); +} + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_INLINE uint32_t __get_IPSR(void) +{ + register uint32_t __regIPSR __ASM("ipsr"); + return(__regIPSR); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_INLINE uint32_t __get_APSR(void) +{ + register uint32_t __regAPSR __ASM("apsr"); + return(__regAPSR); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_INLINE uint32_t __get_xPSR(void) +{ + register uint32_t __regXPSR __ASM("xpsr"); + return(__regXPSR); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_INLINE uint32_t __get_PSP(void) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + return(__regProcessStackPointer); +} + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) +{ + register uint32_t __regProcessStackPointer __ASM("psp"); + __regProcessStackPointer = topOfProcStack; +} + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_INLINE uint32_t __get_MSP(void) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + return(__regMainStackPointer); +} + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) +{ + register uint32_t __regMainStackPointer __ASM("msp"); + __regMainStackPointer = topOfMainStack; +} + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_INLINE uint32_t __get_PRIMASK(void) +{ + register uint32_t __regPriMask __ASM("primask"); + return(__regPriMask); +} + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) +{ + register uint32_t __regPriMask __ASM("primask"); + __regPriMask = (priMask); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +#define __enable_fault_irq __enable_fiq + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +#define __disable_fault_irq __disable_fiq + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_INLINE uint32_t __get_BASEPRI(void) +{ + register uint32_t __regBasePri __ASM("basepri"); + return(__regBasePri); +} + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) +{ + register uint32_t __regBasePri __ASM("basepri"); + __regBasePri = (basePri & 0xFFU); +} + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + register uint32_t __regBasePriMax __ASM("basepri_max"); + __regBasePriMax = (basePri & 0xFFU); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_INLINE uint32_t __get_FAULTMASK(void) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + return(__regFaultMask); +} + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) +{ + register uint32_t __regFaultMask __ASM("faultmask"); + __regFaultMask = (faultMask & (uint32_t)1U); +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ + + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +__STATIC_INLINE uint32_t __get_FPSCR(void) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + return(__regfpscr); +#else + return(0U); +#endif +} + + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) +{ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) + register uint32_t __regfpscr __ASM("fpscr"); + __regfpscr = (fpscr); +#else + (void)fpscr; +#endif +} + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) + +#define __SADD8 __sadd8 +#define __QADD8 __qadd8 +#define __SHADD8 __shadd8 +#define __UADD8 __uadd8 +#define __UQADD8 __uqadd8 +#define __UHADD8 __uhadd8 +#define __SSUB8 __ssub8 +#define __QSUB8 __qsub8 +#define __SHSUB8 __shsub8 +#define __USUB8 __usub8 +#define __UQSUB8 __uqsub8 +#define __UHSUB8 __uhsub8 +#define __SADD16 __sadd16 +#define __QADD16 __qadd16 +#define __SHADD16 __shadd16 +#define __UADD16 __uadd16 +#define __UQADD16 __uqadd16 +#define __UHADD16 __uhadd16 +#define __SSUB16 __ssub16 +#define __QSUB16 __qsub16 +#define __SHSUB16 __shsub16 +#define __USUB16 __usub16 +#define __UQSUB16 __uqsub16 +#define __UHSUB16 __uhsub16 +#define __SASX __sasx +#define __QASX __qasx +#define __SHASX __shasx +#define __UASX __uasx +#define __UQASX __uqasx +#define __UHASX __uhasx +#define __SSAX __ssax +#define __QSAX __qsax +#define __SHSAX __shsax +#define __USAX __usax +#define __UQSAX __uqsax +#define __UHSAX __uhsax +#define __USAD8 __usad8 +#define __USADA8 __usada8 +#define __SSAT16 __ssat16 +#define __USAT16 __usat16 +#define __UXTB16 __uxtb16 +#define __UXTAB16 __uxtab16 +#define __SXTB16 __sxtb16 +#define __SXTAB16 __sxtab16 +#define __SMUAD __smuad +#define __SMUADX __smuadx +#define __SMLAD __smlad +#define __SMLADX __smladx +#define __SMLALD __smlald +#define __SMLALDX __smlaldx +#define __SMUSD __smusd +#define __SMUSDX __smusdx +#define __SMLSD __smlsd +#define __SMLSDX __smlsdx +#define __SMLSLD __smlsld +#define __SMLSLDX __smlsldx +#define __SEL __sel +#define __QADD __qadd +#define __QSUB __qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ + ((int64_t)(ARG3) << 32U) ) >> 32U)) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCC_H */ diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armclang.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armclang.h new file mode 100644 index 000000000..691141774 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_armclang.h @@ -0,0 +1,1503 @@ +/**************************************************************************//** + * @file cmsis_armclang.h + * @brief CMSIS compiler armclang (Arm Compiler 6) header file + * @version V5.4.3 + * @date 27. May 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ + +#ifndef __CMSIS_ARMCLANG_H +#define __CMSIS_ARMCLANG_H + +#pragma clang system_header /* treat file as system include file */ + +/* CMSIS compiler specific defines */ +#ifndef __ASM + #define __ASM __asm +#endif +#ifndef __INLINE + #define __INLINE __inline +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static __inline +#endif +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline +#endif +#ifndef __NO_RETURN + #define __NO_RETURN __attribute__((__noreturn__)) +#endif +#ifndef __USED + #define __USED __attribute__((used)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED + #define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __UNALIGNED_UINT32 /* deprecated */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) +#endif +#ifndef __UNALIGNED_UINT16_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT16_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) +#endif +#ifndef __UNALIGNED_UINT32_WRITE + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) +#endif +#ifndef __UNALIGNED_UINT32_READ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wpacked" +/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #pragma clang diagnostic pop + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) +#endif +#ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#ifndef __RESTRICT + #define __RESTRICT __restrict +#endif +#ifndef __COMPILER_BARRIER + #define __COMPILER_BARRIER() __ASM volatile("":::"memory") +#endif + +/* ######################### Startup and Lowlevel Init ######################## */ + +#ifndef __PROGRAM_START +#define __PROGRAM_START __main +#endif + +#ifndef __INITIAL_SP +#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit +#endif + +#ifndef __STACK_LIMIT +#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base +#endif + +#ifndef __VECTOR_TABLE +#define __VECTOR_TABLE __Vectors +#endif + +#ifndef __VECTOR_TABLE_ATTRIBUTE +#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) +#endif + +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#ifndef __STACK_SEAL +#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base +#endif + +#ifndef __TZ_STACK_SEAL_SIZE +#define __TZ_STACK_SEAL_SIZE 8U +#endif + +#ifndef __TZ_STACK_SEAL_VALUE +#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL +#endif + + +__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { + *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; +} +#endif + + +/* ########################## Core Instruction Access ######################### */ +/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface + Access to dedicated instructions + @{ +*/ + +/* Define macros for porting to both thumb1 and thumb2. + * For thumb1, use low register (r0-r7), specified by constraint "l" + * Otherwise, use general registers, specified by constraint "r" */ +#if defined (__thumb__) && !defined (__thumb2__) +#define __CMSIS_GCC_OUT_REG(r) "=l" (r) +#define __CMSIS_GCC_RW_REG(r) "+l" (r) +#define __CMSIS_GCC_USE_REG(r) "l" (r) +#else +#define __CMSIS_GCC_OUT_REG(r) "=r" (r) +#define __CMSIS_GCC_RW_REG(r) "+r" (r) +#define __CMSIS_GCC_USE_REG(r) "r" (r) +#endif + +/** + \brief No Operation + \details No Operation does nothing. This instruction can be used for code alignment purposes. + */ +#define __NOP __builtin_arm_nop + +/** + \brief Wait For Interrupt + \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. + */ +#define __WFI __builtin_arm_wfi + + +/** + \brief Wait For Event + \details Wait For Event is a hint instruction that permits the processor to enter + a low-power state until one of a number of events occurs. + */ +#define __WFE __builtin_arm_wfe + + +/** + \brief Send Event + \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. + */ +#define __SEV __builtin_arm_sev + + +/** + \brief Instruction Synchronization Barrier + \details Instruction Synchronization Barrier flushes the pipeline in the processor, + so that all instructions following the ISB are fetched from cache or memory, + after the instruction has been completed. + */ +#define __ISB() __builtin_arm_isb(0xF) + +/** + \brief Data Synchronization Barrier + \details Acts as a special kind of Data Memory Barrier. + It completes when all explicit memory accesses before this instruction complete. + */ +#define __DSB() __builtin_arm_dsb(0xF) + + +/** + \brief Data Memory Barrier + \details Ensures the apparent order of the explicit memory operations before + and after the instruction, without ensuring their completion. + */ +#define __DMB() __builtin_arm_dmb(0xF) + + +/** + \brief Reverse byte order (32 bit) + \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV(value) __builtin_bswap32(value) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REV16(value) __ROR(__REV(value), 16) + + +/** + \brief Reverse byte order (16 bit) + \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. + \param [in] value Value to reverse + \return Reversed value + */ +#define __REVSH(value) (int16_t)__builtin_bswap16(value) + + +/** + \brief Rotate Right in unsigned value (32 bit) + \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. + \param [in] op1 Value to rotate + \param [in] op2 Number of Bits to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) +{ + op2 %= 32U; + if (op2 == 0U) + { + return op1; + } + return (op1 >> op2) | (op1 << (32U - op2)); +} + + +/** + \brief Breakpoint + \details Causes the processor to enter Debug state. + Debug tools can use this to investigate system state when the instruction at a particular address is reached. + \param [in] value is ignored by the processor. + If required, a debugger can use it to store additional information about the breakpoint. + */ +#define __BKPT(value) __ASM volatile ("bkpt "#value) + + +/** + \brief Reverse bit order of value + \details Reverses the bit order of the given value. + \param [in] value Value to reverse + \return Reversed value + */ +#define __RBIT __builtin_arm_rbit + +/** + \brief Count leading zeros + \details Counts the number of leading zeros of a data value. + \param [in] value Value to count the leading zeros + \return number of leading zeros in value + */ +__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) +{ + /* Even though __builtin_clz produces a CLZ instruction on ARM, formally + __builtin_clz(0) is undefined behaviour, so handle this case specially. + This guarantees ARM-compatible results if happening to compile on a non-ARM + target, and ensures the compiler doesn't decide to activate any + optimisations using the logic "value was passed to __builtin_clz, so it + is non-zero". + ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a + single CLZ instruction. + */ + if (value == 0U) + { + return 32U; + } + return __builtin_clz(value); +} + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief LDR Exclusive (8 bit) + \details Executes a exclusive LDR instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDREXB (uint8_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (16 bit) + \details Executes a exclusive LDR instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDREXH (uint16_t)__builtin_arm_ldrex + + +/** + \brief LDR Exclusive (32 bit) + \details Executes a exclusive LDR instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDREXW (uint32_t)__builtin_arm_ldrex + + +/** + \brief STR Exclusive (8 bit) + \details Executes a exclusive STR instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXB (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (16 bit) + \details Executes a exclusive STR instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXH (uint32_t)__builtin_arm_strex + + +/** + \brief STR Exclusive (32 bit) + \details Executes a exclusive STR instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STREXW (uint32_t)__builtin_arm_strex + + +/** + \brief Remove the exclusive lock + \details Removes the exclusive lock which is created by LDREX. + */ +#define __CLREX __builtin_arm_clrex + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +#define __SSAT __builtin_arm_ssat + + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +#define __USAT __builtin_arm_usat + + +/** + \brief Rotate Right with Extend (32 bit) + \details Moves each bit of a bitstring right by one bit. + The carry input is shifted in at the left end of the bitstring. + \param [in] value Value to rotate + \return Rotated value + */ +__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) +{ + uint32_t result; + + __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); + return(result); +} + + +/** + \brief LDRT Unprivileged (8 bit) + \details Executes a Unprivileged LDRT instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint8_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (16 bit) + \details Executes a Unprivileged LDRT instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); + return ((uint16_t) result); /* Add explicit type cast here */ +} + + +/** + \brief LDRT Unprivileged (32 bit) + \details Executes a Unprivileged LDRT instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); + return(result); +} + + +/** + \brief STRT Unprivileged (8 bit) + \details Executes a Unprivileged STRT instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (16 bit) + \details Executes a Unprivileged STRT instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); +} + + +/** + \brief STRT Unprivileged (32 bit) + \details Executes a Unprivileged STRT instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); +} + +#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Signed Saturate + \details Saturates a signed value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (1..32) + \return Saturated value + */ +__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) +{ + if ((sat >= 1U) && (sat <= 32U)) + { + const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); + const int32_t min = -1 - max ; + if (val > max) + { + return max; + } + else if (val < min) + { + return min; + } + } + return val; +} + +/** + \brief Unsigned Saturate + \details Saturates an unsigned value. + \param [in] value Value to be saturated + \param [in] sat Bit position to saturate to (0..31) + \return Saturated value + */ +__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) +{ + if (sat <= 31U) + { + const uint32_t max = ((1U << sat) - 1U); + if (val > (int32_t)max) + { + return max; + } + else if (val < 0) + { + return 0U; + } + } + return (uint32_t)val; +} + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Load-Acquire (8 bit) + \details Executes a LDAB instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint8_t) result); +} + + +/** + \brief Load-Acquire (16 bit) + \details Executes a LDAH instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) +{ + uint32_t result; + + __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return ((uint16_t) result); +} + + +/** + \brief Load-Acquire (32 bit) + \details Executes a LDA instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) +{ + uint32_t result; + + __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); + return(result); +} + + +/** + \brief Store-Release (8 bit) + \details Executes a STLB instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) +{ + __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (16 bit) + \details Executes a STLH instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) +{ + __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Store-Release (32 bit) + \details Executes a STL instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + */ +__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) +{ + __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); +} + + +/** + \brief Load-Acquire Exclusive (8 bit) + \details Executes a LDAB exclusive instruction for 8 bit value. + \param [in] ptr Pointer to data + \return value of type uint8_t at (*ptr) + */ +#define __LDAEXB (uint8_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (16 bit) + \details Executes a LDAH exclusive instruction for 16 bit values. + \param [in] ptr Pointer to data + \return value of type uint16_t at (*ptr) + */ +#define __LDAEXH (uint16_t)__builtin_arm_ldaex + + +/** + \brief Load-Acquire Exclusive (32 bit) + \details Executes a LDA exclusive instruction for 32 bit values. + \param [in] ptr Pointer to data + \return value of type uint32_t at (*ptr) + */ +#define __LDAEX (uint32_t)__builtin_arm_ldaex + + +/** + \brief Store-Release Exclusive (8 bit) + \details Executes a STLB exclusive instruction for 8 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXB (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (16 bit) + \details Executes a STLH exclusive instruction for 16 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEXH (uint32_t)__builtin_arm_stlex + + +/** + \brief Store-Release Exclusive (32 bit) + \details Executes a STL exclusive instruction for 32 bit values. + \param [in] value Value to store + \param [in] ptr Pointer to location + \return 0 Function succeeded + \return 1 Function failed + */ +#define __STLEX (uint32_t)__builtin_arm_stlex + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ + + +/* ########################### Core Function Access ########################### */ +/** \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions + @{ + */ + +/** + \brief Enable IRQ Interrupts + \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __enable_irq(void) +{ + __ASM volatile ("cpsie i" : : : "memory"); +} +#endif + + +/** + \brief Disable IRQ Interrupts + \details Disables IRQ interrupts by setting special-purpose register PRIMASK. + Can only be executed in Privileged modes. + */ +#ifndef __ARM_COMPAT_H +__STATIC_FORCEINLINE void __disable_irq(void) +{ + __ASM volatile ("cpsid i" : : : "memory"); +} +#endif + + +/** + \brief Get Control Register + \details Returns the content of the Control Register. + \return Control Register value + */ +__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Control Register (non-secure) + \details Returns the content of the non-secure Control Register when in secure mode. + \return non-secure Control Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Control Register + \details Writes the given value to the Control Register. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) +{ + __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); + __ISB(); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Control Register (non-secure) + \details Writes the given value to the non-secure Control Register when in secure state. + \param [in] control Control Register value to set + */ +__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) +{ + __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); + __ISB(); +} +#endif + + +/** + \brief Get IPSR Register + \details Returns the content of the IPSR Register. + \return IPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_IPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get APSR Register + \details Returns the content of the APSR Register. + \return APSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_APSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, apsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get xPSR Register + \details Returns the content of the xPSR Register. + \return xPSR Register value + */ +__STATIC_FORCEINLINE uint32_t __get_xPSR(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); + return(result); +} + + +/** + \brief Get Process Stack Pointer + \details Returns the current value of the Process Stack Pointer (PSP). + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer (non-secure) + \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. + \return PSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Process Stack Pointer + \details Assigns the given value to the Process Stack Pointer (PSP). + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. + \param [in] topOfProcStack Process Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) +{ + __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); +} +#endif + + +/** + \brief Get Main Stack Pointer + \details Returns the current value of the Main Stack Pointer (MSP). + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSP(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer (non-secure) + \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. + \return MSP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Main Stack Pointer + \details Assigns the given value to the Main Stack Pointer (MSP). + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. + \param [in] topOfMainStack Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) +{ + __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); +} +#endif + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Stack Pointer (non-secure) + \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. + \return SP Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); + return(result); +} + + +/** + \brief Set Stack Pointer (non-secure) + \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. + \param [in] topOfStack Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) +{ + __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); +} +#endif + + +/** + \brief Get Priority Mask + \details Returns the current state of the priority mask bit from the Priority Mask Register. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Priority Mask (non-secure) + \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. + \return Priority Mask value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Priority Mask + \details Assigns the given value to the Priority Mask Register. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) +{ + __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Priority Mask (non-secure) + \details Assigns the given value to the non-secure Priority Mask Register when in secure state. + \param [in] priMask Priority Mask + */ +__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) +{ + __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); +} +#endif + + +#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) +/** + \brief Enable FIQ + \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __enable_fault_irq(void) +{ + __ASM volatile ("cpsie f" : : : "memory"); +} + + +/** + \brief Disable FIQ + \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. + Can only be executed in Privileged modes. + */ +__STATIC_FORCEINLINE void __disable_fault_irq(void) +{ + __ASM volatile ("cpsid f" : : : "memory"); +} + + +/** + \brief Get Base Priority + \details Returns the current value of the Base Priority register. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Base Priority (non-secure) + \details Returns the current value of the non-secure Base Priority register when in secure state. + \return Base Priority register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Base Priority + \details Assigns the given value to the Base Priority register. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) +{ + __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Base Priority (non-secure) + \details Assigns the given value to the non-secure Base Priority register when in secure state. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); +} +#endif + + +/** + \brief Set Base Priority with condition + \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, + or the new value increases the BASEPRI priority level. + \param [in] basePri Base Priority value to set + */ +__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) +{ + __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); +} + + +/** + \brief Get Fault Mask + \details Returns the current value of the Fault Mask register. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); + return(result); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Fault Mask (non-secure) + \details Returns the current value of the non-secure Fault Mask register when in secure state. + \return Fault Mask register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) +{ + uint32_t result; + + __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); + return(result); +} +#endif + + +/** + \brief Set Fault Mask + \details Assigns the given value to the Fault Mask register. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Fault Mask (non-secure) + \details Assigns the given value to the non-secure Fault Mask register when in secure state. + \param [in] faultMask Fault Mask value to set + */ +__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) +{ + __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); +} +#endif + +#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ + (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ + (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + + +#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) + +/** + \brief Get Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim" : "=r" (result) ); + return result; +#endif +} + +#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Process Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always in non-secure + mode. + + \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \return PSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Process Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Process Stack Pointer (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored in non-secure + mode. + + \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. + \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure PSPLIM is RAZ/WI + (void)ProcStackPtrLimit; +#else + __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); +#endif +} +#endif + + +/** + \brief Get Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim" : "=r" (result) ); + return result; +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Get Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence zero is returned always. + + \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. + \return MSPLIM Register value + */ +__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + return 0U; +#else + uint32_t result; + __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); + return result; +#endif +} +#endif + + +/** + \brief Set Main Stack Pointer Limit + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). + \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set + */ +__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ + (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); +#endif +} + + +#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) +/** + \brief Set Main Stack Pointer Limit (non-secure) + Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure + Stack Pointer Limit register hence the write is silently ignored. + + \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. + \param [in] MainStackPtrLimit Main Stack Pointer value to set + */ +__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) +{ +#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) + // without main extensions, the non-secure MSPLIM is RAZ/WI + (void)MainStackPtrLimit; +#else + __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); +#endif +} +#endif + +#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ + (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ + (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ + +/** + \brief Get FPSCR + \details Returns the current value of the Floating Point Status/Control register. + \return Floating Point Status/Control register value + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr +#else +#define __get_FPSCR() ((uint32_t)0U) +#endif + +/** + \brief Set FPSCR + \details Assigns the given value to the Floating Point Status/Control register. + \param [in] fpscr Floating Point Status/Control value to set + */ +#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ + (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) +#define __set_FPSCR __builtin_arm_set_fpscr +#else +#define __set_FPSCR(x) ((void)(x)) +#endif + + +/*@} end of CMSIS_Core_RegAccFunctions */ + + +/* ################### Compiler specific Intrinsics ########################### */ +/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics + Access to dedicated SIMD instructions + @{ +*/ + +#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + +#define __SADD8 __builtin_arm_sadd8 +#define __QADD8 __builtin_arm_qadd8 +#define __SHADD8 __builtin_arm_shadd8 +#define __UADD8 __builtin_arm_uadd8 +#define __UQADD8 __builtin_arm_uqadd8 +#define __UHADD8 __builtin_arm_uhadd8 +#define __SSUB8 __builtin_arm_ssub8 +#define __QSUB8 __builtin_arm_qsub8 +#define __SHSUB8 __builtin_arm_shsub8 +#define __USUB8 __builtin_arm_usub8 +#define __UQSUB8 __builtin_arm_uqsub8 +#define __UHSUB8 __builtin_arm_uhsub8 +#define __SADD16 __builtin_arm_sadd16 +#define __QADD16 __builtin_arm_qadd16 +#define __SHADD16 __builtin_arm_shadd16 +#define __UADD16 __builtin_arm_uadd16 +#define __UQADD16 __builtin_arm_uqadd16 +#define __UHADD16 __builtin_arm_uhadd16 +#define __SSUB16 __builtin_arm_ssub16 +#define __QSUB16 __builtin_arm_qsub16 +#define __SHSUB16 __builtin_arm_shsub16 +#define __USUB16 __builtin_arm_usub16 +#define __UQSUB16 __builtin_arm_uqsub16 +#define __UHSUB16 __builtin_arm_uhsub16 +#define __SASX __builtin_arm_sasx +#define __QASX __builtin_arm_qasx +#define __SHASX __builtin_arm_shasx +#define __UASX __builtin_arm_uasx +#define __UQASX __builtin_arm_uqasx +#define __UHASX __builtin_arm_uhasx +#define __SSAX __builtin_arm_ssax +#define __QSAX __builtin_arm_qsax +#define __SHSAX __builtin_arm_shsax +#define __USAX __builtin_arm_usax +#define __UQSAX __builtin_arm_uqsax +#define __UHSAX __builtin_arm_uhsax +#define __USAD8 __builtin_arm_usad8 +#define __USADA8 __builtin_arm_usada8 +#define __SSAT16 __builtin_arm_ssat16 +#define __USAT16 __builtin_arm_usat16 +#define __UXTB16 __builtin_arm_uxtb16 +#define __UXTAB16 __builtin_arm_uxtab16 +#define __SXTB16 __builtin_arm_sxtb16 +#define __SXTAB16 __builtin_arm_sxtab16 +#define __SMUAD __builtin_arm_smuad +#define __SMUADX __builtin_arm_smuadx +#define __SMLAD __builtin_arm_smlad +#define __SMLADX __builtin_arm_smladx +#define __SMLALD __builtin_arm_smlald +#define __SMLALDX __builtin_arm_smlaldx +#define __SMUSD __builtin_arm_smusd +#define __SMUSDX __builtin_arm_smusdx +#define __SMLSD __builtin_arm_smlsd +#define __SMLSDX __builtin_arm_smlsdx +#define __SMLSLD __builtin_arm_smlsld +#define __SMLSLDX __builtin_arm_smlsldx +#define __SEL __builtin_arm_sel +#define __QADD __builtin_arm_qadd +#define __QSUB __builtin_arm_qsub + +#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ + ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) + +#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ + ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) + +#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) + +#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) + +__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) +{ + int32_t result; + + __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); + return(result); +} + +#endif /* (__ARM_FEATURE_DSP == 1) */ +/*@} end of group CMSIS_SIMD_intrinsics */ + + +#endif /* __CMSIS_ARMCLANG_H */ diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_compiler.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_compiler.h new file mode 100644 index 000000000..adbf296f1 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_compiler.h @@ -0,0 +1,283 @@ +/**************************************************************************//** + * @file cmsis_compiler.h + * @brief CMSIS compiler generic header file + * @version V5.1.0 + * @date 09. October 2018 + ******************************************************************************/ +/* + * Copyright (c) 2009-2018 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CMSIS_COMPILER_H +#define __CMSIS_COMPILER_H + +#include + +/* + * Arm Compiler 4/5 + */ +#if defined ( __CC_ARM ) + #include "cmsis_armcc.h" + + +/* + * Arm Compiler 6.6 LTM (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) + #include "cmsis_armclang_ltm.h" + + /* + * Arm Compiler above 6.10.1 (armclang) + */ +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) + #include "cmsis_armclang.h" + + +/* + * GNU Compiler + */ +#elif defined ( __GNUC__ ) + #include "cmsis_gcc.h" + + +/* + * IAR Compiler + */ +#elif defined ( __ICCARM__ ) + #include + + +/* + * TI Arm Compiler + */ +#elif defined ( __TI_ARM__ ) + #include + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __attribute__((packed)) + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __attribute__((packed)) + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __attribute__((packed)) + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __attribute__((packed)) T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __attribute__((aligned(x))) + #endif + #ifndef __RESTRICT + #define __RESTRICT __restrict + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * TASKING Compiler + */ +#elif defined ( __TASKING__ ) + /* + * The CMSIS functions have been implemented as intrinsics in the compiler. + * Please use "carm -?i" to get an up to date list of all intrinsics, + * Including the CMSIS ones. + */ + + #ifndef __ASM + #define __ASM __asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + #define __NO_RETURN __attribute__((noreturn)) + #endif + #ifndef __USED + #define __USED __attribute__((used)) + #endif + #ifndef __WEAK + #define __WEAK __attribute__((weak)) + #endif + #ifndef __PACKED + #define __PACKED __packed__ + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT struct __packed__ + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION union __packed__ + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + struct __packed__ T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #define __ALIGNED(x) __align(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +/* + * COSMIC Compiler + */ +#elif defined ( __CSMC__ ) + #include + + #ifndef __ASM + #define __ASM _asm + #endif + #ifndef __INLINE + #define __INLINE inline + #endif + #ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline + #endif + #ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE __STATIC_INLINE + #endif + #ifndef __NO_RETURN + // NO RETURN is automatically detected hence no warning here + #define __NO_RETURN + #endif + #ifndef __USED + #warning No compiler specific solution for __USED. __USED is ignored. + #define __USED + #endif + #ifndef __WEAK + #define __WEAK __weak + #endif + #ifndef __PACKED + #define __PACKED @packed + #endif + #ifndef __PACKED_STRUCT + #define __PACKED_STRUCT @packed struct + #endif + #ifndef __PACKED_UNION + #define __PACKED_UNION @packed union + #endif + #ifndef __UNALIGNED_UINT32 /* deprecated */ + @packed struct T_UINT32 { uint32_t v; }; + #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) + #endif + #ifndef __UNALIGNED_UINT16_WRITE + __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; + #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT16_READ + __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; + #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) + #endif + #ifndef __UNALIGNED_UINT32_WRITE + __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; + #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) + #endif + #ifndef __UNALIGNED_UINT32_READ + __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; + #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) + #endif + #ifndef __ALIGNED + #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. + #define __ALIGNED(x) + #endif + #ifndef __RESTRICT + #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. + #define __RESTRICT + #endif + #ifndef __COMPILER_BARRIER + #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. + #define __COMPILER_BARRIER() (void)0 + #endif + + +#else + #error Unknown compiler. +#endif + + +#endif /* __CMSIS_COMPILER_H */ + diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_version.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_version.h new file mode 100644 index 000000000..2f048e455 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/cmsis_version.h @@ -0,0 +1,39 @@ +/**************************************************************************//** + * @file cmsis_version.h + * @brief CMSIS Core(M) Version definitions + * @version V5.0.4 + * @date 23. July 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CMSIS_VERSION_H +#define __CMSIS_VERSION_H + +/* CMSIS Version definitions */ +#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ +#define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */ +#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ + __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ +#endif diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/core_cm3.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/core_cm3.h new file mode 100644 index 000000000..74fb87e5c --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/core_cm3.h @@ -0,0 +1,1943 @@ +/**************************************************************************//** + * @file core_cm3.h + * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File + * @version V5.1.2 + * @date 04. June 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef __CORE_CM3_H_GENERIC +#define __CORE_CM3_H_GENERIC + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/** + \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions + CMSIS violates the following MISRA-C:2004 rules: + + \li Required Rule 8.5, object/function definition in header file.
+ Function definitions in header files are used to allow 'inlining'. + + \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
+ Unions are used for effective representation of core registers. + + \li Advisory Rule 19.7, Function-like macro defined.
+ Function-like macros are used to allow more efficient code. + */ + + +/******************************************************************************* + * CMSIS definitions + ******************************************************************************/ +/** + \ingroup Cortex_M3 + @{ + */ + +#include "cmsis_version.h" + +/* CMSIS CM3 definitions */ +#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ +#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ +#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ + __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ + +#define __CORTEX_M (3U) /*!< Cortex-M Core */ + +/** __FPU_USED indicates whether an FPU is used or not. + This core does not support an FPU at all +*/ +#define __FPU_USED 0U + +#if defined ( __CC_ARM ) + #if defined __TARGET_FPU_VFP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #if defined __ARM_FP + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __GNUC__ ) + #if defined (__VFP_FP__) && !defined(__SOFTFP__) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __ICCARM__ ) + #if defined __ARMVFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TI_ARM__ ) + #if defined __TI_VFP_SUPPORT__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __TASKING__ ) + #if defined __FPU_VFP__ + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#elif defined ( __CSMC__ ) + #if ( __CSMC__ & 0x400U) + #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" + #endif + +#endif + +#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_GENERIC */ + +#ifndef __CMSIS_GENERIC + +#ifndef __CORE_CM3_H_DEPENDANT +#define __CORE_CM3_H_DEPENDANT + +#ifdef __cplusplus + extern "C" { +#endif + +/* check device defines and use defaults */ +#if defined __CHECK_DEVICE_DEFINES + #ifndef __CM3_REV + #define __CM3_REV 0x0200U + #warning "__CM3_REV not defined in device header file; using default!" + #endif + + #ifndef __MPU_PRESENT + #define __MPU_PRESENT 0U + #warning "__MPU_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __VTOR_PRESENT + #define __VTOR_PRESENT 1U + #warning "__VTOR_PRESENT not defined in device header file; using default!" + #endif + + #ifndef __NVIC_PRIO_BITS + #define __NVIC_PRIO_BITS 3U + #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" + #endif + + #ifndef __Vendor_SysTickConfig + #define __Vendor_SysTickConfig 0U + #warning "__Vendor_SysTickConfig not defined in device header file; using default!" + #endif +#endif + +/* IO definitions (access restrictions to peripheral registers) */ +/** + \defgroup CMSIS_glob_defs CMSIS Global Defines + + IO Type Qualifiers are used + \li to specify the access to peripheral variables. + \li for automatic generation of peripheral register debug information. +*/ +#ifdef __cplusplus + #define __I volatile /*!< Defines 'read only' permissions */ +#else + #define __I volatile const /*!< Defines 'read only' permissions */ +#endif +#define __O volatile /*!< Defines 'write only' permissions */ +#define __IO volatile /*!< Defines 'read / write' permissions */ + +/* following defines should be used for structure members */ +#define __IM volatile const /*! Defines 'read only' structure member permissions */ +#define __OM volatile /*! Defines 'write only' structure member permissions */ +#define __IOM volatile /*! Defines 'read / write' structure member permissions */ + +/*@} end of group Cortex_M3 */ + + + +/******************************************************************************* + * Register Abstraction + Core Register contain: + - Core Register + - Core NVIC Register + - Core SCB Register + - Core SysTick Register + - Core Debug Register + - Core MPU Register + ******************************************************************************/ +/** + \defgroup CMSIS_core_register Defines and Type Definitions + \brief Type definitions and defines for Cortex-M processor based devices. +*/ + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CORE Status and Control Registers + \brief Core Register type definitions. + @{ + */ + +/** + \brief Union type to access the Application Program Status Register (APSR). + */ +typedef union +{ + struct + { + uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} APSR_Type; + +/* APSR Register Definitions */ +#define APSR_N_Pos 31U /*!< APSR: N Position */ +#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ + +#define APSR_Z_Pos 30U /*!< APSR: Z Position */ +#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ + +#define APSR_C_Pos 29U /*!< APSR: C Position */ +#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ + +#define APSR_V_Pos 28U /*!< APSR: V Position */ +#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ + +#define APSR_Q_Pos 27U /*!< APSR: Q Position */ +#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ + + +/** + \brief Union type to access the Interrupt Program Status Register (IPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} IPSR_Type; + +/* IPSR Register Definitions */ +#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ +#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ + + +/** + \brief Union type to access the Special-Purpose Program Status Registers (xPSR). + */ +typedef union +{ + struct + { + uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ + uint32_t _reserved0:1; /*!< bit: 9 Reserved */ + uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ + uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ + uint32_t T:1; /*!< bit: 24 Thumb bit */ + uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ + uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ + uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ + uint32_t C:1; /*!< bit: 29 Carry condition code flag */ + uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ + uint32_t N:1; /*!< bit: 31 Negative condition code flag */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} xPSR_Type; + +/* xPSR Register Definitions */ +#define xPSR_N_Pos 31U /*!< xPSR: N Position */ +#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ + +#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ +#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ + +#define xPSR_C_Pos 29U /*!< xPSR: C Position */ +#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ + +#define xPSR_V_Pos 28U /*!< xPSR: V Position */ +#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ + +#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ +#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ + +#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ +#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ + +#define xPSR_T_Pos 24U /*!< xPSR: T Position */ +#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ + +#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ +#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ + +#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ +#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ + + +/** + \brief Union type to access the Control Registers (CONTROL). + */ +typedef union +{ + struct + { + uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ + uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ + uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ + } b; /*!< Structure used for bit access */ + uint32_t w; /*!< Type used for word access */ +} CONTROL_Type; + +/* CONTROL Register Definitions */ +#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ +#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ + +#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ +#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ + +/*@} end of group CMSIS_CORE */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) + \brief Type definitions for the NVIC Registers + @{ + */ + +/** + \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). + */ +typedef struct +{ + __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ + uint32_t RESERVED0[24U]; + __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ + uint32_t RESERVED1[24U]; + __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ + uint32_t RESERVED2[24U]; + __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ + uint32_t RESERVED3[24U]; + __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ + uint32_t RESERVED4[56U]; + __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ + uint32_t RESERVED5[644U]; + __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ +} NVIC_Type; + +/* Software Triggered Interrupt Register Definitions */ +#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ +#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ + +/*@} end of group CMSIS_NVIC */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCB System Control Block (SCB) + \brief Type definitions for the System Control Block Registers + @{ + */ + +/** + \brief Structure type to access the System Control Block (SCB). + */ +typedef struct +{ + __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ + __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ + __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ + __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ + __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ + __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ + __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ + __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ + __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ + __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ + __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ + __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ + __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ + __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ + __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ + __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ + __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ + __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ + __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ +} SCB_Type; + +/* SCB CPUID Register Definitions */ +#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ +#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ + +#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ +#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ + +#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ +#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ + +#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ +#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ + +#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ +#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ + +/* SCB Interrupt Control State Register Definitions */ +#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ +#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ + +#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ +#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ + +#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ +#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ + +#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ +#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ + +#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ +#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ + +#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ +#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ + +#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ +#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ + +#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ +#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ + +#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ +#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ + +#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ +#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ + +/* SCB Vector Table Offset Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */ +#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ +#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ + +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#else +#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ +#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ +#endif + +/* SCB Application Interrupt and Reset Control Register Definitions */ +#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ +#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ + +#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ +#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ + +#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ +#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ + +#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ +#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ + +#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ +#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ + +#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ +#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ + +#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ +#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ + +/* SCB System Control Register Definitions */ +#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ +#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ + +#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ +#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ + +#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ +#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ + +/* SCB Configuration Control Register Definitions */ +#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ +#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ + +#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ +#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ + +#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ +#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ + +#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ +#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ + +#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ +#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ + +#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ +#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ + +/* SCB System Handler Control and State Register Definitions */ +#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ +#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ + +#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ +#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ + +#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ +#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ + +#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ +#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ + +#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ +#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ + +#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ +#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ + +#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ +#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ + +#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ +#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ + +#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ +#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ + +#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ +#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ + +#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ +#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ + +#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ +#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ + +#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ +#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ + +#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ +#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ + +/* SCB Configurable Fault Status Register Definitions */ +#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ +#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ + +#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ +#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ + +#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ +#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ + +/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ +#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ + +#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ +#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ + +#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ +#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ + +#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ +#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ + +#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ +#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ + +/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ +#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ + +#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ +#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ + +#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ +#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ + +#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ +#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ + +#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ +#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ + +#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ +#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ + +/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ +#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ +#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ + +#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ +#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ + +#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ +#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ + +#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ +#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ + +#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ +#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ + +#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ +#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ + +/* SCB Hard Fault Status Register Definitions */ +#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ +#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ + +#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ +#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ + +#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ +#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ + +/* SCB Debug Fault Status Register Definitions */ +#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ +#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ + +#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ +#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ + +#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ +#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ + +#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ +#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ + +#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ +#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ + +/*@} end of group CMSIS_SCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) + \brief Type definitions for the System Control and ID Register not in the SCB + @{ + */ + +/** + \brief Structure type to access the System Control and ID Register not in the SCB. + */ +typedef struct +{ + uint32_t RESERVED0[1U]; + __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) + __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ +#else + uint32_t RESERVED1[1U]; +#endif +} SCnSCB_Type; + +/* Interrupt Controller Type Register Definitions */ +#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ +#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ + +/* Auxiliary Control Register Definitions */ +#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) +#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ +#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ + +#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ +#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ + +#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ +#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ + +#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ +#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ + +#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ +#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ +#endif + +/*@} end of group CMSIS_SCnotSCB */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_SysTick System Tick Timer (SysTick) + \brief Type definitions for the System Timer Registers. + @{ + */ + +/** + \brief Structure type to access the System Timer (SysTick). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ + __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ + __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ + __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ +} SysTick_Type; + +/* SysTick Control / Status Register Definitions */ +#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ +#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ + +#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ +#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ + +#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ +#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ + +#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ +#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ + +/* SysTick Reload Register Definitions */ +#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ +#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ + +/* SysTick Current Register Definitions */ +#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ +#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ + +/* SysTick Calibration Register Definitions */ +#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ +#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ + +#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ +#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ + +#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ +#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ + +/*@} end of group CMSIS_SysTick */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) + \brief Type definitions for the Instrumentation Trace Macrocell (ITM) + @{ + */ + +/** + \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). + */ +typedef struct +{ + __OM union + { + __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ + __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ + __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ + } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ + uint32_t RESERVED0[864U]; + __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ + uint32_t RESERVED1[15U]; + __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ + uint32_t RESERVED2[15U]; + __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ + uint32_t RESERVED3[32U]; + uint32_t RESERVED4[43U]; + __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ + __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ + uint32_t RESERVED5[6U]; + __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ + __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ + __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ + __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ + __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ + __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ + __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ + __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ + __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ + __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ + __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ + __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ +} ITM_Type; + +/* ITM Trace Privilege Register Definitions */ +#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ +#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ + +/* ITM Trace Control Register Definitions */ +#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ +#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ + +#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ +#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ + +#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ +#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ + +#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ +#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ + +#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ +#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ + +#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ +#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ + +#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ +#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ + +#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ +#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ + +#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ +#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ + +/* ITM Lock Status Register Definitions */ +#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ +#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ + +#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ +#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ + +#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ +#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ + +/*@}*/ /* end of group CMSIS_ITM */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) + \brief Type definitions for the Data Watchpoint and Trace (DWT) + @{ + */ + +/** + \brief Structure type to access the Data Watchpoint and Trace Register (DWT). + */ +typedef struct +{ + __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ + __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ + __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ + __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ + __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ + __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ + __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ + __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ + __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ + __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ + __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ + uint32_t RESERVED0[1U]; + __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ + __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ + __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ + uint32_t RESERVED1[1U]; + __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ + __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ + __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ + uint32_t RESERVED2[1U]; + __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ + __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ + __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ +} DWT_Type; + +/* DWT Control Register Definitions */ +#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ +#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ + +#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ +#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ + +#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ +#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ + +#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ +#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ + +#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ +#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ + +#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ +#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ + +#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ +#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ + +#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ +#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ + +#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ +#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ + +#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ +#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ + +#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ +#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ + +#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ +#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ + +#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ +#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ + +#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ +#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ + +#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ +#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ + +#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ +#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ + +#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ +#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ + +#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ +#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ + +/* DWT CPI Count Register Definitions */ +#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ +#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ + +/* DWT Exception Overhead Count Register Definitions */ +#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ +#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ + +/* DWT Sleep Count Register Definitions */ +#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ +#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ + +/* DWT LSU Count Register Definitions */ +#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ +#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ + +/* DWT Folded-instruction Count Register Definitions */ +#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ +#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ + +/* DWT Comparator Mask Register Definitions */ +#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ +#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ + +/* DWT Comparator Function Register Definitions */ +#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ +#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ + +#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ +#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ + +#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ +#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ + +#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ +#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ + +#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ +#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ + +#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ +#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ + +#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ +#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ + +#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ +#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ + +#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ +#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ + +/*@}*/ /* end of group CMSIS_DWT */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_TPI Trace Port Interface (TPI) + \brief Type definitions for the Trace Port Interface (TPI) + @{ + */ + +/** + \brief Structure type to access the Trace Port Interface Register (TPI). + */ +typedef struct +{ + __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ + __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ + uint32_t RESERVED0[2U]; + __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ + uint32_t RESERVED1[55U]; + __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ + uint32_t RESERVED2[131U]; + __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ + __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ + __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ + uint32_t RESERVED3[759U]; + __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ + __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ + __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ + uint32_t RESERVED4[1U]; + __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ + __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ + __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ + uint32_t RESERVED5[39U]; + __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ + __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ + uint32_t RESERVED7[8U]; + __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ + __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ +} TPI_Type; + +/* TPI Asynchronous Clock Prescaler Register Definitions */ +#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ +#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ + +/* TPI Selected Pin Protocol Register Definitions */ +#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ +#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ + +/* TPI Formatter and Flush Status Register Definitions */ +#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ +#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ + +#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ +#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ + +#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ +#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ + +#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ +#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ + +/* TPI Formatter and Flush Control Register Definitions */ +#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ +#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ + +#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ +#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ + +/* TPI TRIGGER Register Definitions */ +#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ +#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ + +/* TPI Integration ETM Data Register Definitions (FIFO0) */ +#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ +#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ + +#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ +#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ + +#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ +#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ + +#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ +#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ + +#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ +#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ + +#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ +#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ + +#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ +#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ + +/* TPI ITATBCTR2 Register Definitions */ +#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ +#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ + +#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ +#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ + +/* TPI Integration ITM Data Register Definitions (FIFO1) */ +#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ +#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ + +#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ +#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ + +#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ +#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ + +#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ +#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ + +#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ +#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ + +#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ +#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ + +#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ +#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ + +/* TPI ITATBCTR0 Register Definitions */ +#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ +#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ + +#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ +#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ + +/* TPI Integration Mode Control Register Definitions */ +#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ +#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ + +/* TPI DEVID Register Definitions */ +#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ +#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ + +#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ +#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ + +#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ +#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ + +#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ +#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ + +#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ +#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ + +#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ +#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ + +/* TPI DEVTYPE Register Definitions */ +#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ +#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ + +#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ +#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ + +/*@}*/ /* end of group CMSIS_TPI */ + + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_MPU Memory Protection Unit (MPU) + \brief Type definitions for the Memory Protection Unit (MPU) + @{ + */ + +/** + \brief Structure type to access the Memory Protection Unit (MPU). + */ +typedef struct +{ + __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ + __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ + __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ + __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ + __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ + __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ + __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ + __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ + __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ + __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ +} MPU_Type; + +#define MPU_TYPE_RALIASES 4U + +/* MPU Type Register Definitions */ +#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ +#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ + +#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ +#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ + +#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ +#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ + +/* MPU Control Register Definitions */ +#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ +#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ + +#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ +#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ + +#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ +#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ + +/* MPU Region Number Register Definitions */ +#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ +#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ + +/* MPU Region Base Address Register Definitions */ +#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ +#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ + +#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ +#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ + +#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ +#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ + +/* MPU Region Attribute and Size Register Definitions */ +#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ +#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ + +#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ +#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ + +#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ +#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ + +#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ +#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ + +#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ +#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ + +#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ +#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ + +#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ +#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ + +#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ +#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ + +#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ +#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ + +#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ +#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ + +/*@} end of group CMSIS_MPU */ +#endif + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) + \brief Type definitions for the Core Debug Registers + @{ + */ + +/** + \brief Structure type to access the Core Debug Register (CoreDebug). + */ +typedef struct +{ + __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ + __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ + __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ + __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ +} CoreDebug_Type; + +/* Debug Halting Control and Status Register Definitions */ +#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ +#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ + +#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ +#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ + +#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ +#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ + +#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ +#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ + +#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ +#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ + +#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ +#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ + +#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ +#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ + +#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ +#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ + +#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ +#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ + +#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ +#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ + +#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ +#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ + +#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ +#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ + +/* Debug Core Register Selector Register Definitions */ +#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ +#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ + +#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ +#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ + +/* Debug Exception and Monitor Control Register Definitions */ +#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ +#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ + +#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ +#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ + +#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ +#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ + +#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ +#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ + +#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ +#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ + +#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ +#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ + +#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ +#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ + +#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ +#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ + +#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ +#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ + +#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ +#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ + +#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ +#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ + +#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ +#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ + +#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ +#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ + +/*@} end of group CMSIS_CoreDebug */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_bitfield Core register bit field macros + \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). + @{ + */ + +/** + \brief Mask and shift a bit field value for use in a register bit range. + \param[in] field Name of the register bit field. + \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. + \return Masked and shifted value. +*/ +#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) + +/** + \brief Mask and shift a register value to extract a bit filed value. + \param[in] field Name of the register bit field. + \param[in] value Value of register. This parameter is interpreted as an uint32_t type. + \return Masked and shifted bit field value. +*/ +#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) + +/*@} end of group CMSIS_core_bitfield */ + + +/** + \ingroup CMSIS_core_register + \defgroup CMSIS_core_base Core Definitions + \brief Definitions for base addresses, unions, and structures. + @{ + */ + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ +#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ +#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ +#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ +#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ +#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ +#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ + +#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ +#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ +#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ +#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ +#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ +#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ +#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ +#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ + #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ +#endif + +/*@} */ + + + +/******************************************************************************* + * Hardware Abstraction Layer + Core Function Interface contains: + - Core NVIC Functions + - Core SysTick Functions + - Core Debug Functions + - Core Register Access Functions + ******************************************************************************/ +/** + \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference +*/ + + + +/* ########################## NVIC functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_NVICFunctions NVIC Functions + \brief Functions that manage interrupts and exceptions via the NVIC. + @{ + */ + +#ifdef CMSIS_NVIC_VIRTUAL + #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE + #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" + #endif + #include CMSIS_NVIC_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping + #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping + #define NVIC_EnableIRQ __NVIC_EnableIRQ + #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ + #define NVIC_DisableIRQ __NVIC_DisableIRQ + #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ + #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ + #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ + #define NVIC_GetActive __NVIC_GetActive + #define NVIC_SetPriority __NVIC_SetPriority + #define NVIC_GetPriority __NVIC_GetPriority + #define NVIC_SystemReset __NVIC_SystemReset +#endif /* CMSIS_NVIC_VIRTUAL */ + +#ifdef CMSIS_VECTAB_VIRTUAL + #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE + #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" + #endif + #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE +#else + #define NVIC_SetVector __NVIC_SetVector + #define NVIC_GetVector __NVIC_GetVector +#endif /* (CMSIS_VECTAB_VIRTUAL) */ + +#define NVIC_USER_IRQ_OFFSET 16 + + +/* The following EXC_RETURN values are saved the LR on exception entry */ +#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ +#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ +#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ + + +/** + \brief Set Priority Grouping + \details Sets the priority grouping field using the required unlock sequence. + The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. + Only values from 0..7 are used. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Priority grouping field. + */ +__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) +{ + uint32_t reg_value; + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + + reg_value = SCB->AIRCR; /* read old register configuration */ + reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ + reg_value = (reg_value | + ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ + SCB->AIRCR = reg_value; +} + + +/** + \brief Get Priority Grouping + \details Reads the priority grouping field from the NVIC Interrupt Controller. + \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). + */ +__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) +{ + return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); +} + + +/** + \brief Enable Interrupt + \details Enables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + __COMPILER_BARRIER(); + NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __COMPILER_BARRIER(); + } +} + + +/** + \brief Get Interrupt Enable status + \details Returns a device specific interrupt enable status from the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt is not enabled. + \return 1 Interrupt is enabled. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Disable Interrupt + \details Disables a device specific interrupt in the NVIC interrupt controller. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + __DSB(); + __ISB(); + } +} + + +/** + \brief Get Pending Interrupt + \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not pending. + \return 1 Interrupt status is pending. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Pending Interrupt + \details Sets the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Clear Pending Interrupt + \details Clears the pending bit of a device specific interrupt in the NVIC pending register. + \param [in] IRQn Device specific interrupt number. + \note IRQn must not be negative. + */ +__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); + } +} + + +/** + \brief Get Active Interrupt + \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. + \param [in] IRQn Device specific interrupt number. + \return 0 Interrupt status is not active. + \return 1 Interrupt status is active. + \note IRQn must not be negative. + */ +__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) +{ + if ((int32_t)(IRQn) >= 0) + { + return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); + } + else + { + return(0U); + } +} + + +/** + \brief Set Interrupt Priority + \details Sets the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \param [in] priority Priority to set. + \note The priority cannot be set for every processor exception. + */ +__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) +{ + if ((int32_t)(IRQn) >= 0) + { + NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } + else + { + SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); + } +} + + +/** + \brief Get Interrupt Priority + \details Reads the priority of a device specific interrupt or a processor exception. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Interrupt Priority. + Value is aligned automatically to the implemented priority bits of the microcontroller. + */ +__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) +{ + + if ((int32_t)(IRQn) >= 0) + { + return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); + } + else + { + return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); + } +} + + +/** + \brief Encode Priority + \details Encodes the priority for an interrupt with the given priority group, + preemptive priority value, and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. + \param [in] PriorityGroup Used priority group. + \param [in] PreemptPriority Preemptive priority value (starting from 0). + \param [in] SubPriority Subpriority value (starting from 0). + \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). + */ +__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + return ( + ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | + ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) + ); +} + + +/** + \brief Decode Priority + \details Decodes an interrupt priority value with a given priority group to + preemptive priority value and subpriority value. + In case of a conflict between priority grouping and available + priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. + \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). + \param [in] PriorityGroup Used priority group. + \param [out] pPreemptPriority Preemptive priority value (starting from 0). + \param [out] pSubPriority Subpriority value (starting from 0). + */ +__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) +{ + uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ + uint32_t PreemptPriorityBits; + uint32_t SubPriorityBits; + + PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); + SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); + + *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); + *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); +} + + +/** + \brief Set Interrupt Vector + \details Sets an interrupt vector in SRAM based interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + VTOR must been relocated to SRAM before. + \param [in] IRQn Interrupt number + \param [in] vector Address of interrupt handler function + */ +__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; + /* ARM Application Note 321 states that the M3 does not require the architectural barrier */ +} + + +/** + \brief Get Interrupt Vector + \details Reads an interrupt vector from interrupt vector table. + The interrupt number can be positive to specify a device specific interrupt, + or negative to specify a processor exception. + \param [in] IRQn Interrupt number. + \return Address of interrupt handler function + */ +__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) +{ + uint32_t *vectors = (uint32_t *)SCB->VTOR; + return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; +} + + +/** + \brief System Reset + \details Initiates a system reset request to reset the MCU. + */ +__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) +{ + __DSB(); /* Ensure all outstanding memory accesses included + buffered write are completed before reset */ + SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | + (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | + SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ + __DSB(); /* Ensure completion of memory access */ + + for(;;) /* wait until reset */ + { + __NOP(); + } +} + +/*@} end of CMSIS_Core_NVICFunctions */ + + +/* ########################## MPU functions #################################### */ + +#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) + +#include "mpu_armv7.h" + +#endif + + +/* ########################## FPU functions #################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_FpuFunctions FPU Functions + \brief Function that provides FPU type. + @{ + */ + +/** + \brief get FPU type + \details returns the FPU type + \returns + - \b 0: No FPU + - \b 1: Single precision FPU + - \b 2: Double + Single precision FPU + */ +__STATIC_INLINE uint32_t SCB_GetFPUType(void) +{ + return 0U; /* No FPU */ +} + + +/*@} end of CMSIS_Core_FpuFunctions */ + + + +/* ################################## SysTick function ############################################ */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_Core_SysTickFunctions SysTick Functions + \brief Functions that configure the System. + @{ + */ + +#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) + +/** + \brief System Tick Configuration + \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. + Counter is in free running mode to generate periodic interrupts. + \param [in] ticks Number of ticks between two interrupts. + \return 0 Function succeeded. + \return 1 Function failed. + \note When the variable __Vendor_SysTickConfig is set to 1, then the + function SysTick_Config is not included. In this case, the file device.h + must contain a vendor-specific implementation of this function. + */ +__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) +{ + if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) + { + return (1UL); /* Reload value impossible */ + } + + SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ + NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ + SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ + SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | + SysTick_CTRL_TICKINT_Msk | + SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ + return (0UL); /* Function successful */ +} + +#endif + +/*@} end of CMSIS_Core_SysTickFunctions */ + + + +/* ##################################### Debug In/Output function ########################################### */ +/** + \ingroup CMSIS_Core_FunctionInterface + \defgroup CMSIS_core_DebugFunctions ITM Functions + \brief Functions that access the ITM debug interface. + @{ + */ + +extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ +#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ + + +/** + \brief ITM Send Character + \details Transmits a character via the ITM channel 0, and + \li Just returns when no debugger is connected that has booked the output. + \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. + \param [in] ch Character to transmit. + \returns Character to transmit. + */ +__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) +{ + if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ + ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ + { + while (ITM->PORT[0U].u32 == 0UL) + { + __NOP(); + } + ITM->PORT[0U].u8 = (uint8_t)ch; + } + return (ch); +} + + +/** + \brief ITM Receive Character + \details Inputs a character via the external variable \ref ITM_RxBuffer. + \return Received character. + \return -1 No character pending. + */ +__STATIC_INLINE int32_t ITM_ReceiveChar (void) +{ + int32_t ch = -1; /* no character available */ + + if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) + { + ch = ITM_RxBuffer; + ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ + } + + return (ch); +} + + +/** + \brief ITM Check Character + \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. + \return 0 No character available. + \return 1 Character available. + */ +__STATIC_INLINE int32_t ITM_CheckChar (void) +{ + + if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) + { + return (0); /* no character available */ + } + else + { + return (1); /* character available */ + } +} + +/*@} end of CMSIS_core_DebugFunctions */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __CORE_CM3_H_DEPENDANT */ + +#endif /* __CMSIS_GENERIC */ diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/mpu_armv7.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/mpu_armv7.h new file mode 100644 index 000000000..d9eedf81a --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/mpu_armv7.h @@ -0,0 +1,275 @@ +/****************************************************************************** + * @file mpu_armv7.h + * @brief CMSIS MPU API for Armv7-M MPU + * @version V5.1.2 + * @date 25. May 2020 + ******************************************************************************/ +/* + * Copyright (c) 2017-2020 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined ( __ICCARM__ ) + #pragma system_include /* treat file as system include file for MISRA check */ +#elif defined (__clang__) + #pragma clang system_header /* treat file as system include file */ +#endif + +#ifndef ARM_MPU_ARMV7_H +#define ARM_MPU_ARMV7_H + +#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes +#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes +#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes +#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes +#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes +#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte +#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes +#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes +#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes +#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes +#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes +#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes +#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes +#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes +#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes +#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte +#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes +#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes +#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes +#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes +#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes +#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes +#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes +#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes +#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes +#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte +#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes +#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes + +#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access +#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only +#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only +#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access +#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only +#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access + +/** MPU Region Base Address Register Value +* +* \param Region The region to be configured, number 0 to 15. +* \param BaseAddress The base address for the region. +*/ +#define ARM_MPU_RBAR(Region, BaseAddress) \ + (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ + ((Region) & MPU_RBAR_REGION_Msk) | \ + (MPU_RBAR_VALID_Msk)) + +/** +* MPU Memory Access Attributes +* +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +*/ +#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ + ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ + (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ + (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ + (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ + ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ + (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ + (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ + (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ + (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ + (((MPU_RASR_ENABLE_Msk)))) + +/** +* MPU Region Attribute and Size Register Value +* +* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. +* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. +* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. +* \param IsShareable Region is shareable between multiple bus masters. +* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. +* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. +* \param SubRegionDisable Sub-region disable field. +* \param Size Region size of the region to be configured, for example 4K, 8K. +*/ +#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ + ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) + +/** +* MPU Memory Access Attribute for strongly ordered memory. +* - TEX: 000b +* - Shareable +* - Non-cacheable +* - Non-bufferable +*/ +#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) + +/** +* MPU Memory Access Attribute for device memory. +* - TEX: 000b (if shareable) or 010b (if non-shareable) +* - Shareable or non-shareable +* - Non-cacheable +* - Bufferable (if shareable) or non-bufferable (if non-shareable) +* +* \param IsShareable Configures the device memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) + +/** +* MPU Memory Access Attribute for normal memory. +* - TEX: 1BBb (reflecting outer cacheability rules) +* - Shareable or non-shareable +* - Cacheable or non-cacheable (reflecting inner cacheability rules) +* - Bufferable or non-bufferable (reflecting inner cacheability rules) +* +* \param OuterCp Configures the outer cache policy. +* \param InnerCp Configures the inner cache policy. +* \param IsShareable Configures the memory as shareable or non-shareable. +*/ +#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U)) + +/** +* MPU Memory Access Attribute non-cacheable policy. +*/ +#define ARM_MPU_CACHEP_NOCACHE 0U + +/** +* MPU Memory Access Attribute write-back, write and read allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_WRA 1U + +/** +* MPU Memory Access Attribute write-through, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WT_NWA 2U + +/** +* MPU Memory Access Attribute write-back, no write allocate policy. +*/ +#define ARM_MPU_CACHEP_WB_NWA 3U + + +/** +* Struct for a single MPU Region +*/ +typedef struct { + uint32_t RBAR; //!< The region base address register value (RBAR) + uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR +} ARM_MPU_Region_t; + +/** Enable the MPU. +* \param MPU_Control Default access permissions for unconfigured regions. +*/ +__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) +{ + __DMB(); + MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; +#endif + __DSB(); + __ISB(); +} + +/** Disable the MPU. +*/ +__STATIC_INLINE void ARM_MPU_Disable(void) +{ + __DMB(); +#ifdef SCB_SHCSR_MEMFAULTENA_Msk + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; +#endif + MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; + __DSB(); + __ISB(); +} + +/** Clear and disable the given MPU region. +* \param rnr Region number to be cleared. +*/ +__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) +{ + MPU->RNR = rnr; + MPU->RASR = 0U; +} + +/** Configure an MPU region. +* \param rbar Value for RBAR register. +* \param rasr Value for RASR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) +{ + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Configure the given MPU region. +* \param rnr Region number to be configured. +* \param rbar Value for RBAR register. +* \param rasr Value for RASR register. +*/ +__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) +{ + MPU->RNR = rnr; + MPU->RBAR = rbar; + MPU->RASR = rasr; +} + +/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load(). +* \param dst Destination data is copied to. +* \param src Source data is copied from. +* \param len Amount of data words to be copied. +*/ +__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) +{ + uint32_t i; + for (i = 0U; i < len; ++i) + { + dst[i] = src[i]; + } +} + +/** Load the given number of MPU regions from a table. +* \param table Pointer to the MPU configuration table. +* \param cnt Amount of regions to be configured. +*/ +__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) +{ + const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; + while (cnt > MPU_TYPE_RALIASES) { + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); + table += MPU_TYPE_RALIASES; + cnt -= MPU_TYPE_RALIASES; + } + ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); +} + +#endif diff --git a/tests/projects/embed/mdk/hello/src/lib/cmsis/system_ARMCM3.h b/tests/projects/embed/mdk/hello/src/lib/cmsis/system_ARMCM3.h new file mode 100644 index 000000000..5d1237770 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/lib/cmsis/system_ARMCM3.h @@ -0,0 +1,62 @@ +/**************************************************************************//** + * @file system_ARMCM3.h + * @brief CMSIS Device System Header File for + * ARMCM3 Device + * @version V5.3.2 + * @date 15. November 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYSTEM_ARMCM3_H +#define SYSTEM_ARMCM3_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + \brief Exception / Interrupt Handler Function Prototype +*/ +typedef void(*VECTOR_TABLE_Type)(void); + +/** + \brief System Clock Frequency (Core Clock) +*/ +extern uint32_t SystemCoreClock; + +/** + \brief Setup the microcontroller system. + + Initialize the System and update the SystemCoreClock variable. + */ +extern void SystemInit (void); + + +/** + \brief Update SystemCoreClock variable. + + Updates the SystemCoreClock with current core Clock retrieved from cpu registers. + */ +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSTEM_ARMCM3_H */ diff --git a/tests/projects/embed/mdk/hello/src/main.c b/tests/projects/embed/mdk/hello/src/main.c new file mode 100644 index 000000000..28d909a18 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/main.c @@ -0,0 +1,6 @@ +int foo(int x); + +int main() +{ + return foo(1); +} diff --git a/tests/projects/embed/mdk/hello/src/startup_ARMCM3.s b/tests/projects/embed/mdk/hello/src/startup_ARMCM3.s new file mode 100644 index 000000000..efe40c1e3 --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/startup_ARMCM3.s @@ -0,0 +1,172 @@ +;/**************************************************************************//** +; * @file startup_ARMCM3.s +; * @brief CMSIS Core Device Startup File for +; * ARMCM3 Device +; * @version V1.0.1 +; * @date 23. July 2019 +; ******************************************************************************/ +;/* +; * Copyright (c) 2009-2019 Arm Limited. All rights reserved. +; * +; * SPDX-License-Identifier: Apache-2.0 +; * +; * Licensed under the Apache License, Version 2.0 (the License); you may +; * not use this file except in compliance with the License. +; * You may obtain a copy of the License at +; * +; * www.apache.org/licenses/LICENSE-2.0 +; * +; * Unless required by applicable law or agreed to in writing, software +; * distributed under the License is distributed on an AS IS BASIS, WITHOUT +; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +; * See the License for the specific language governing permissions and +; * limitations under the License. +; */ + +;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ + + +; Stack Configuration +; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Stack_Size EQU 0x00000400 + + AREA STACK, NOINIT, READWRITE, ALIGN=3 +__stack_limit +Stack_Mem SPACE Stack_Size +__initial_sp + + +; Heap Configuration +; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> +; + +Heap_Size EQU 0x00000C00 + + IF Heap_Size != 0 ; Heap is provided + AREA HEAP, NOINIT, READWRITE, ALIGN=3 +__heap_base +Heap_Mem SPACE Heap_Size +__heap_limit + ENDIF + + + PRESERVE8 + THUMB + + +; Vector Table Mapped to Address 0 at Reset + + AREA RESET, DATA, READONLY + EXPORT __Vectors + EXPORT __Vectors_End + EXPORT __Vectors_Size + +__Vectors DCD __initial_sp ; Top of Stack + DCD Reset_Handler ; Reset Handler + DCD NMI_Handler ; -14 NMI Handler + DCD HardFault_Handler ; -13 Hard Fault Handler + DCD MemManage_Handler ; -12 MPU Fault Handler + DCD BusFault_Handler ; -11 Bus Fault Handler + DCD UsageFault_Handler ; -10 Usage Fault Handler + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD 0 ; Reserved + DCD SVC_Handler ; -5 SVCall Handler + DCD DebugMon_Handler ; -4 Debug Monitor Handler + DCD 0 ; Reserved + DCD PendSV_Handler ; -2 PendSV Handler + DCD SysTick_Handler ; -1 SysTick Handler + + ; Interrupts + DCD Interrupt0_Handler ; 0 Interrupt 0 + DCD Interrupt1_Handler ; 1 Interrupt 1 + DCD Interrupt2_Handler ; 2 Interrupt 2 + DCD Interrupt3_Handler ; 3 Interrupt 3 + DCD Interrupt4_Handler ; 4 Interrupt 4 + DCD Interrupt5_Handler ; 5 Interrupt 5 + DCD Interrupt6_Handler ; 6 Interrupt 6 + DCD Interrupt7_Handler ; 7 Interrupt 7 + DCD Interrupt8_Handler ; 8 Interrupt 8 + DCD Interrupt9_Handler ; 9 Interrupt 9 + + SPACE (214 * 4) ; Interrupts 10 .. 224 are left out +__Vectors_End +__Vectors_Size EQU __Vectors_End - __Vectors + + + AREA |.text|, CODE, READONLY + +; Reset Handler + +Reset_Handler PROC + EXPORT Reset_Handler [WEAK] + IMPORT SystemInit + IMPORT __main + + LDR R0, =SystemInit + BLX R0 + LDR R0, =__main + BX R0 + ENDP + +; The default macro is not used for HardFault_Handler +; because this results in a poor debug illusion. +HardFault_Handler PROC + EXPORT HardFault_Handler [WEAK] + B . + ENDP + +; Macro to define default exception/interrupt handlers. +; Default handler are weak symbols with an endless loop. +; They can be overwritten by real handlers. + MACRO + Set_Default_Handler $Handler_Name +$Handler_Name PROC + EXPORT $Handler_Name [WEAK] + B . + ENDP + MEND + + +; Default exception/interrupt handler + + Set_Default_Handler NMI_Handler + Set_Default_Handler MemManage_Handler + Set_Default_Handler BusFault_Handler + Set_Default_Handler UsageFault_Handler + Set_Default_Handler SVC_Handler + Set_Default_Handler DebugMon_Handler + Set_Default_Handler PendSV_Handler + Set_Default_Handler SysTick_Handler + + Set_Default_Handler Interrupt0_Handler + Set_Default_Handler Interrupt1_Handler + Set_Default_Handler Interrupt2_Handler + Set_Default_Handler Interrupt3_Handler + Set_Default_Handler Interrupt4_Handler + Set_Default_Handler Interrupt5_Handler + Set_Default_Handler Interrupt6_Handler + Set_Default_Handler Interrupt7_Handler + Set_Default_Handler Interrupt8_Handler + Set_Default_Handler Interrupt9_Handler + + ALIGN + + +; User setup Stack & Heap + + IF :LNOT::DEF:__MICROLIB + IMPORT __use_two_region_memory + ENDIF + + EXPORT __stack_limit + EXPORT __initial_sp + IF Heap_Size != 0 ; Heap is provided + EXPORT __heap_base + EXPORT __heap_limit + ENDIF + + END diff --git a/tests/projects/embed/mdk/hello/src/system_ARMCM3.c b/tests/projects/embed/mdk/hello/src/system_ARMCM3.c new file mode 100644 index 000000000..19484537f --- /dev/null +++ b/tests/projects/embed/mdk/hello/src/system_ARMCM3.c @@ -0,0 +1,65 @@ +/**************************************************************************//** + * @file system_ARMCM3.c + * @brief CMSIS Device System Source File for + * ARMCM3 Device + * @version V1.0.1 + * @date 15. November 2019 + ******************************************************************************/ +/* + * Copyright (c) 2009-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ARMCM3.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ +#define XTAL (50000000UL) /* Oscillator frequency */ + +#define SYSTEM_CLOCK (XTAL / 2U) + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[240]; + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Core Clock Frequency */ + + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate (void) +{ + SystemCoreClock = SYSTEM_CLOCK; +} + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit (void) +{ + +#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t) &(__VECTOR_TABLE[0]); +#endif + + SystemCoreClock = SYSTEM_CLOCK; +} diff --git a/tests/projects/embed/mdk/hello/xmake.lua b/tests/projects/embed/mdk/hello/xmake.lua new file mode 100644 index 000000000..6afb714af --- /dev/null +++ b/tests/projects/embed/mdk/hello/xmake.lua @@ -0,0 +1,13 @@ +add_rules("mode.debug", "mode.release") + +set_runtimes("microlib") + +target("foo") + add_rules("mdk.static") + add_files("src/foo/*.c") + +target("hello") + add_deps("foo") + add_rules("mdk.console") + add_files("src/*.c", "src/*.s") + add_includedirs("src/lib/cmsis") diff --git a/tests/projects/linux/bpf/minimal/src/minimal.bpf.c b/tests/projects/linux/bpf/minimal/src/minimal.bpf.c new file mode 100644 index 000000000..ea1eeefbb --- /dev/null +++ b/tests/projects/linux/bpf/minimal/src/minimal.bpf.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright (c) 2020 Facebook */ +#include +#include + +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +int my_pid = 0; + +SEC("tp/syscalls/sys_enter_write") +int handle_tp(void *ctx) +{ + int pid = bpf_get_current_pid_tgid() >> 32; + + if (pid != my_pid) + return 0; + + bpf_printk("BPF triggered from PID %d.\n", pid); + + return 0; +} diff --git a/tests/projects/linux/bpf/minimal/src/minimal.c b/tests/projects/linux/bpf/minimal/src/minimal.c new file mode 100644 index 000000000..4b6ec3181 --- /dev/null +++ b/tests/projects/linux/bpf/minimal/src/minimal.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +/* Copyright (c) 2020 Facebook */ +#include +#include +#include +#include +#include "minimal.skel.h" + +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) +{ + return vfprintf(stderr, format, args); +} + +static void bump_memlock_rlimit(void) +{ + struct rlimit rlim_new = { + .rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY, + }; + + if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) { + fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n"); + exit(1); + } +} + +int main(int argc, char **argv) +{ + struct minimal_bpf *skel; + int err; + + /* Set up libbpf errors and debug info callback */ + libbpf_set_print(libbpf_print_fn); + + /* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */ + bump_memlock_rlimit(); + + /* Open BPF application */ + skel = minimal_bpf__open(); + if (!skel) { + fprintf(stderr, "Failed to open BPF skeleton\n"); + return 1; + } + + /* ensure BPF program only handles write() syscalls from our process */ + skel->bss->my_pid = getpid(); + + /* Load & verify BPF programs */ + err = minimal_bpf__load(skel); + if (err) { + fprintf(stderr, "Failed to load and verify BPF skeleton\n"); + goto cleanup; + } + + /* Attach tracepoint handler */ + err = minimal_bpf__attach(skel); + if (err) { + fprintf(stderr, "Failed to attach BPF skeleton\n"); + goto cleanup; + } + + printf("Successfully started!\n"); + + for (;;) { + /* trigger our BPF program */ + fprintf(stderr, "."); + sleep(1); + } + +cleanup: + minimal_bpf__destroy(skel); + return -err; +} diff --git a/tests/projects/linux/bpf/minimal/test.lua b/tests/projects/linux/bpf/minimal/test.lua new file mode 100644 index 000000000..2856a3831 --- /dev/null +++ b/tests/projects/linux/bpf/minimal/test.lua @@ -0,0 +1,6 @@ +function main(t) + if is_host("linux") and os.arch() == "x86_64" then + os.vrun("xmake f -y -p android -vD") + os.vrun("xmake -y -vD") + end +end diff --git a/tests/projects/linux/bpf/minimal/xmake.lua b/tests/projects/linux/bpf/minimal/xmake.lua new file mode 100644 index 000000000..8507b8aa1 --- /dev/null +++ b/tests/projects/linux/bpf/minimal/xmake.lua @@ -0,0 +1,19 @@ +add_rules("mode.release", "mode.debug") +add_rules("platform.linux.bpf") + +add_requires("linux-tools", {configs = {bpftool = true}}) +add_requires("libbpf") +if is_plat("android") then + add_requires("ndk >=22.x") + set_toolchains("@ndk", {sdkver = "23"}) +else + add_requires("llvm >=10.x") + set_toolchains("@llvm") + add_requires("linux-headers") +end + +target("minimal") + set_kind("binary") + add_files("src/*.c") + add_packages("linux-tools", "linux-headers", "libbpf") + set_license("GPL-2.0") diff --git a/tests/projects/linux/driver/hello/Makefile b/tests/projects/linux/driver/hello/Makefile new file mode 100644 index 000000000..d69924339 --- /dev/null +++ b/tests/projects/linux/driver/hello/Makefile @@ -0,0 +1,13 @@ +ifneq ($(KERNELRELEASE),) + obj-m := hello.o +else + KERN_DIR ?= /usr/src/linux-headers-5.11.0-41-generic/ + PWD := $(shell pwd) + +default: + $(MAKE) -C $(KERN_DIR) V=1 M=$(PWD) modules +endif + +clean: + rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions + diff --git a/tests/projects/linux/driver/hello/hello.c b/tests/projects/linux/driver/hello/hello.c new file mode 100644 index 000000000..2614fb2cc --- /dev/null +++ b/tests/projects/linux/driver/hello/hello.c @@ -0,0 +1,21 @@ +#include +#include + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Ruki"); +MODULE_DESCRIPTION("A simple Hello World Module"); +MODULE_ALIAS("a simplest module"); + +int hello_init(void) +{ + printk(KERN_INFO "Hello World\n"); + return 0; +} + +void hello_exit(void) +{ + printk(KERN_INFO "Goodbye World\n"); +} + +module_init(hello_init); +module_exit(hello_exit); diff --git a/tests/projects/mdk/hello/src/foo/foo.c b/tests/projects/mdk/hello/src/foo/foo.c deleted file mode 100644 index e51afb553..000000000 --- a/tests/projects/mdk/hello/src/foo/foo.c +++ /dev/null @@ -1,4 +0,0 @@ -int foo(int x) -{ - return x; -} diff --git a/tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h b/tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h deleted file mode 100644 index 44c0c23f4..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/ARMCM3.h +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************//** - * @file ARMCM3.h - * @brief CMSIS Core Peripheral Access Layer Header File for - * ARMCM3 Device - * @version V5.3.1 - * @date 09. July 2018 - ******************************************************************************/ -/* - * Copyright (c) 2009-2018 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ARMCM3_H -#define ARMCM3_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/* ------------------------- Interrupt Number Definition ------------------------ */ - -typedef enum IRQn -{ -/* ------------------- Processor Exceptions Numbers ----------------------------- */ - NonMaskableInt_IRQn = -14, /* 2 Non Maskable Interrupt */ - HardFault_IRQn = -13, /* 3 HardFault Interrupt */ - MemoryManagement_IRQn = -12, /* 4 Memory Management Interrupt */ - BusFault_IRQn = -11, /* 5 Bus Fault Interrupt */ - UsageFault_IRQn = -10, /* 6 Usage Fault Interrupt */ - SVCall_IRQn = -5, /* 11 SV Call Interrupt */ - DebugMonitor_IRQn = -4, /* 12 Debug Monitor Interrupt */ - PendSV_IRQn = -2, /* 14 Pend SV Interrupt */ - SysTick_IRQn = -1, /* 15 System Tick Interrupt */ - -/* ------------------- Processor Interrupt Numbers ------------------------------ */ - Interrupt0_IRQn = 0, - Interrupt1_IRQn = 1, - Interrupt2_IRQn = 2, - Interrupt3_IRQn = 3, - Interrupt4_IRQn = 4, - Interrupt5_IRQn = 5, - Interrupt6_IRQn = 6, - Interrupt7_IRQn = 7, - Interrupt8_IRQn = 8, - Interrupt9_IRQn = 9 - /* Interrupts 10 .. 224 are left out */ -} IRQn_Type; - - -/* ================================================================================ */ -/* ================ Processor and Core Peripheral Section ================ */ -/* ================================================================================ */ - -/* ------- Start of section using anonymous unions and disabling warnings ------- */ -#if defined (__CC_ARM) - #pragma push - #pragma anon_unions -#elif defined (__ICCARM__) - #pragma language=extended -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wc11-extensions" - #pragma clang diagnostic ignored "-Wreserved-id-macro" -#elif defined (__GNUC__) - /* anonymous unions are enabled by default */ -#elif defined (__TMS470__) - /* anonymous unions are enabled by default */ -#elif defined (__TASKING__) - #pragma warning 586 -#elif defined (__CSMC__) - /* anonymous unions are enabled by default */ -#else - #warning Not supported compiler type -#endif - - -/* -------- Configuration of Core Peripherals ----------------------------------- */ -#define __CM3_REV 0x0201U /* Core revision r2p1 */ -#define __MPU_PRESENT 1U /* MPU present */ -#define __VTOR_PRESENT 1U /* VTOR present */ -#define __NVIC_PRIO_BITS 3U /* Number of Bits used for Priority Levels */ -#define __Vendor_SysTickConfig 0U /* Set to 1 if different SysTick Config is used */ - -#include "core_cm3.h" /* Processor and core peripherals */ -#include "system_ARMCM3.h" /* System Header */ - - -/* -------- End of section using anonymous unions and disabling warnings -------- */ -#if defined (__CC_ARM) - #pragma pop -#elif defined (__ICCARM__) - /* leave anonymous unions enabled */ -#elif (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)) - #pragma clang diagnostic pop -#elif defined (__GNUC__) - /* anonymous unions are enabled by default */ -#elif defined (__TMS470__) - /* anonymous unions are enabled by default */ -#elif defined (__TASKING__) - #pragma warning restore -#elif defined (__CSMC__) - /* anonymous unions are enabled by default */ -#else - #warning Not supported compiler type -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* ARMCM3_H */ diff --git a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h deleted file mode 100644 index a955d4713..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armcc.h +++ /dev/null @@ -1,888 +0,0 @@ -/**************************************************************************//** - * @file cmsis_armcc.h - * @brief CMSIS compiler ARMCC (Arm Compiler 5) header file - * @version V5.3.2 - * @date 27. May 2021 - ******************************************************************************/ -/* - * Copyright (c) 2009-2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __CMSIS_ARMCC_H -#define __CMSIS_ARMCC_H - - -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677) - #error "Please use Arm Compiler Toolchain V4.0.677 or later!" -#endif - -/* CMSIS compiler control architecture macros */ -#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \ - (defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) ) - #define __ARM_ARCH_6M__ 1 -#endif - -#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1)) - #define __ARM_ARCH_7M__ 1 -#endif - -#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1)) - #define __ARM_ARCH_7EM__ 1 -#endif - - /* __ARM_ARCH_8M_BASE__ not applicable */ - /* __ARM_ARCH_8M_MAIN__ not applicable */ - /* __ARM_ARCH_8_1M_MAIN__ not applicable */ - -/* CMSIS compiler control DSP macros */ -#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) - #define __ARM_FEATURE_DSP 1 -#endif - -/* CMSIS compiler specific defines */ -#ifndef __ASM - #define __ASM __asm -#endif -#ifndef __INLINE - #define __INLINE __inline -#endif -#ifndef __STATIC_INLINE - #define __STATIC_INLINE static __inline -#endif -#ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE static __forceinline -#endif -#ifndef __NO_RETURN - #define __NO_RETURN __declspec(noreturn) -#endif -#ifndef __USED - #define __USED __attribute__((used)) -#endif -#ifndef __WEAK - #define __WEAK __attribute__((weak)) -#endif -#ifndef __PACKED - #define __PACKED __attribute__((packed)) -#endif -#ifndef __PACKED_STRUCT - #define __PACKED_STRUCT __packed struct -#endif -#ifndef __PACKED_UNION - #define __PACKED_UNION __packed union -#endif -#ifndef __UNALIGNED_UINT32 /* deprecated */ - #define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x))) -#endif -#ifndef __UNALIGNED_UINT16_WRITE - #define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val)) -#endif -#ifndef __UNALIGNED_UINT16_READ - #define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr))) -#endif -#ifndef __UNALIGNED_UINT32_WRITE - #define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val)) -#endif -#ifndef __UNALIGNED_UINT32_READ - #define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr))) -#endif -#ifndef __ALIGNED - #define __ALIGNED(x) __attribute__((aligned(x))) -#endif -#ifndef __RESTRICT - #define __RESTRICT __restrict -#endif -#ifndef __COMPILER_BARRIER - #define __COMPILER_BARRIER() __memory_changed() -#endif - -/* ######################### Startup and Lowlevel Init ######################## */ - -#ifndef __PROGRAM_START -#define __PROGRAM_START __main -#endif - -#ifndef __INITIAL_SP -#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit -#endif - -#ifndef __STACK_LIMIT -#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base -#endif - -#ifndef __VECTOR_TABLE -#define __VECTOR_TABLE __Vectors -#endif - -#ifndef __VECTOR_TABLE_ATTRIBUTE -#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) -#endif - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __nop - - -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -#define __WFI __wfi - - -/** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __wfe - - -/** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __sev - - -/** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. - */ -#define __ISB() __isb(0xF) - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() __dsb(0xF) - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() __dmb(0xF) - - -/** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV __rev - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. - \param [in] value Value to reverse - \return Reversed value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) -{ - rev16 r0, r0 - bx lr -} -#endif - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. - \param [in] value Value to reverse - \return Reversed value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value) -{ - revsh r0, r0 - bx lr -} -#endif - - -/** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] op1 Value to rotate - \param [in] op2 Number of Bits to rotate - \return Rotated value - */ -#define __ROR __ror - - -/** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. - */ -#define __BKPT(value) __breakpoint(value) - - -/** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value - */ -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) - #define __RBIT __rbit -#else -__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value) -{ - uint32_t result; - uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */ - - result = value; /* r will be reversed bits of v; first get LSB of v */ - for (value >>= 1U; value != 0U; value >>= 1U) - { - result <<= 1U; - result |= value & 1U; - s--; - } - result <<= s; /* shift when v's highest bits are zero */ - return result; -} -#endif - - -/** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -#define __CLZ __clz - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) - -/** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) -#else - #define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) -#else - #define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) -#else - #define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXB(value, ptr) __strex(value, ptr) -#else - #define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXH(value, ptr) __strex(value, ptr) -#else - #define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020) - #define __STREXW(value, ptr) __strex(value, ptr) -#else - #define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop") -#endif - - -/** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. - */ -#define __CLREX __clrex - - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT __ssat - - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT __usat - - -/** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value - */ -#ifndef __NO_EMBEDDED_ASM -__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value) -{ - rrx r0, r0 - bx lr -} -#endif - - -/** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr)) - - -/** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr)) - - -/** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr)) - - -/** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRBT(value, ptr) __strt(value, ptr) - - -/** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRHT(value, ptr) __strt(value, ptr) - - -/** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -#define __STRT(value, ptr) __strt(value, ptr) - -#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat) -{ - if ((sat >= 1U) && (sat <= 32U)) - { - const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); - const int32_t min = -1 - max ; - if (val > max) - { - return max; - } - else if (val < min) - { - return min; - } - } - return val; -} - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat) -{ - if (sat <= 31U) - { - const uint32_t max = ((1U << sat) - 1U); - if (val > (int32_t)max) - { - return max; - } - else if (val < 0) - { - return 0U; - } - } - return (uint32_t)val; -} - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. - Can only be executed in Privileged modes. - */ -/* intrinsic void __enable_irq(); */ - - -/** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting special-purpose register PRIMASK. - Can only be executed in Privileged modes. - */ -/* intrinsic void __disable_irq(); */ - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__STATIC_INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return(__regControl); -} - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__STATIC_INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; - __ISB(); -} - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__STATIC_INLINE uint32_t __get_IPSR(void) -{ - register uint32_t __regIPSR __ASM("ipsr"); - return(__regIPSR); -} - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__STATIC_INLINE uint32_t __get_APSR(void) -{ - register uint32_t __regAPSR __ASM("apsr"); - return(__regAPSR); -} - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value - */ -__STATIC_INLINE uint32_t __get_xPSR(void) -{ - register uint32_t __regXPSR __ASM("xpsr"); - return(__regXPSR); -} - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__STATIC_INLINE uint32_t __get_PSP(void) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - return(__regProcessStackPointer); -} - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) -{ - register uint32_t __regProcessStackPointer __ASM("psp"); - __regProcessStackPointer = topOfProcStack; -} - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__STATIC_INLINE uint32_t __get_MSP(void) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - return(__regMainStackPointer); -} - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) -{ - register uint32_t __regMainStackPointer __ASM("msp"); - __regMainStackPointer = topOfMainStack; -} - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__STATIC_INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return(__regPriMask); -} - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__STATIC_INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) - -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. - Can only be executed in Privileged modes. - */ -#define __enable_fault_irq __enable_fiq - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. - Can only be executed in Privileged modes. - */ -#define __disable_fault_irq __disable_fiq - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__STATIC_INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return(__regBasePri); -} - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xFFU); -} - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri) -{ - register uint32_t __regBasePriMax __ASM("basepri_max"); - __regBasePriMax = (basePri & 0xFFU); -} - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__STATIC_INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return(__regFaultMask); -} - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & (uint32_t)1U); -} - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ - - -/** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -__STATIC_INLINE uint32_t __get_FPSCR(void) -{ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) - register uint32_t __regfpscr __ASM("fpscr"); - return(__regfpscr); -#else - return(0U); -#endif -} - - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -__STATIC_INLINE void __set_FPSCR(uint32_t fpscr) -{ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) - register uint32_t __regfpscr __ASM("fpscr"); - __regfpscr = (fpscr); -#else - (void)fpscr; -#endif -} - - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) - -#define __SADD8 __sadd8 -#define __QADD8 __qadd8 -#define __SHADD8 __shadd8 -#define __UADD8 __uadd8 -#define __UQADD8 __uqadd8 -#define __UHADD8 __uhadd8 -#define __SSUB8 __ssub8 -#define __QSUB8 __qsub8 -#define __SHSUB8 __shsub8 -#define __USUB8 __usub8 -#define __UQSUB8 __uqsub8 -#define __UHSUB8 __uhsub8 -#define __SADD16 __sadd16 -#define __QADD16 __qadd16 -#define __SHADD16 __shadd16 -#define __UADD16 __uadd16 -#define __UQADD16 __uqadd16 -#define __UHADD16 __uhadd16 -#define __SSUB16 __ssub16 -#define __QSUB16 __qsub16 -#define __SHSUB16 __shsub16 -#define __USUB16 __usub16 -#define __UQSUB16 __uqsub16 -#define __UHSUB16 __uhsub16 -#define __SASX __sasx -#define __QASX __qasx -#define __SHASX __shasx -#define __UASX __uasx -#define __UQASX __uqasx -#define __UHASX __uhasx -#define __SSAX __ssax -#define __QSAX __qsax -#define __SHSAX __shsax -#define __USAX __usax -#define __UQSAX __uqsax -#define __UHSAX __uhsax -#define __USAD8 __usad8 -#define __USADA8 __usada8 -#define __SSAT16 __ssat16 -#define __USAT16 __usat16 -#define __UXTB16 __uxtb16 -#define __UXTAB16 __uxtab16 -#define __SXTB16 __sxtb16 -#define __SXTAB16 __sxtab16 -#define __SMUAD __smuad -#define __SMUADX __smuadx -#define __SMLAD __smlad -#define __SMLADX __smladx -#define __SMLALD __smlald -#define __SMLALDX __smlaldx -#define __SMUSD __smusd -#define __SMUSDX __smusdx -#define __SMLSD __smlsd -#define __SMLSDX __smlsdx -#define __SMLSLD __smlsld -#define __SMLSLDX __smlsldx -#define __SEL __sel -#define __QADD __qadd -#define __QSUB __qsub - -#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ - ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) - -#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ - ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) - -#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \ - ((int64_t)(ARG3) << 32U) ) >> 32U)) - -#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) - -#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) - -#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */ -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#endif /* __CMSIS_ARMCC_H */ diff --git a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armclang.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armclang.h deleted file mode 100644 index 691141774..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_armclang.h +++ /dev/null @@ -1,1503 +0,0 @@ -/**************************************************************************//** - * @file cmsis_armclang.h - * @brief CMSIS compiler armclang (Arm Compiler 6) header file - * @version V5.4.3 - * @date 27. May 2021 - ******************************************************************************/ -/* - * Copyright (c) 2009-2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*lint -esym(9058, IRQn)*/ /* disable MISRA 2012 Rule 2.4 for IRQn */ - -#ifndef __CMSIS_ARMCLANG_H -#define __CMSIS_ARMCLANG_H - -#pragma clang system_header /* treat file as system include file */ - -/* CMSIS compiler specific defines */ -#ifndef __ASM - #define __ASM __asm -#endif -#ifndef __INLINE - #define __INLINE __inline -#endif -#ifndef __STATIC_INLINE - #define __STATIC_INLINE static __inline -#endif -#ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE __attribute__((always_inline)) static __inline -#endif -#ifndef __NO_RETURN - #define __NO_RETURN __attribute__((__noreturn__)) -#endif -#ifndef __USED - #define __USED __attribute__((used)) -#endif -#ifndef __WEAK - #define __WEAK __attribute__((weak)) -#endif -#ifndef __PACKED - #define __PACKED __attribute__((packed, aligned(1))) -#endif -#ifndef __PACKED_STRUCT - #define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) -#endif -#ifndef __PACKED_UNION - #define __PACKED_UNION union __attribute__((packed, aligned(1))) -#endif -#ifndef __UNALIGNED_UINT32 /* deprecated */ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpacked" -/*lint -esym(9058, T_UINT32)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32 */ - struct __attribute__((packed)) T_UINT32 { uint32_t v; }; - #pragma clang diagnostic pop - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) -#endif -#ifndef __UNALIGNED_UINT16_WRITE - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpacked" -/*lint -esym(9058, T_UINT16_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_WRITE */ - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #pragma clang diagnostic pop - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) -#endif -#ifndef __UNALIGNED_UINT16_READ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpacked" -/*lint -esym(9058, T_UINT16_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT16_READ */ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #pragma clang diagnostic pop - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) -#endif -#ifndef __UNALIGNED_UINT32_WRITE - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpacked" -/*lint -esym(9058, T_UINT32_WRITE)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_WRITE */ - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #pragma clang diagnostic pop - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) -#endif -#ifndef __UNALIGNED_UINT32_READ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wpacked" -/*lint -esym(9058, T_UINT32_READ)*/ /* disable MISRA 2012 Rule 2.4 for T_UINT32_READ */ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #pragma clang diagnostic pop - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) -#endif -#ifndef __ALIGNED - #define __ALIGNED(x) __attribute__((aligned(x))) -#endif -#ifndef __RESTRICT - #define __RESTRICT __restrict -#endif -#ifndef __COMPILER_BARRIER - #define __COMPILER_BARRIER() __ASM volatile("":::"memory") -#endif - -/* ######################### Startup and Lowlevel Init ######################## */ - -#ifndef __PROGRAM_START -#define __PROGRAM_START __main -#endif - -#ifndef __INITIAL_SP -#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit -#endif - -#ifndef __STACK_LIMIT -#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base -#endif - -#ifndef __VECTOR_TABLE -#define __VECTOR_TABLE __Vectors -#endif - -#ifndef __VECTOR_TABLE_ATTRIBUTE -#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET"))) -#endif - -#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) -#ifndef __STACK_SEAL -#define __STACK_SEAL Image$$STACKSEAL$$ZI$$Base -#endif - -#ifndef __TZ_STACK_SEAL_SIZE -#define __TZ_STACK_SEAL_SIZE 8U -#endif - -#ifndef __TZ_STACK_SEAL_VALUE -#define __TZ_STACK_SEAL_VALUE 0xFEF5EDA5FEF5EDA5ULL -#endif - - -__STATIC_FORCEINLINE void __TZ_set_STACKSEAL_S (uint32_t* stackTop) { - *((uint64_t *)stackTop) = __TZ_STACK_SEAL_VALUE; -} -#endif - - -/* ########################## Core Instruction Access ######################### */ -/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface - Access to dedicated instructions - @{ -*/ - -/* Define macros for porting to both thumb1 and thumb2. - * For thumb1, use low register (r0-r7), specified by constraint "l" - * Otherwise, use general registers, specified by constraint "r" */ -#if defined (__thumb__) && !defined (__thumb2__) -#define __CMSIS_GCC_OUT_REG(r) "=l" (r) -#define __CMSIS_GCC_RW_REG(r) "+l" (r) -#define __CMSIS_GCC_USE_REG(r) "l" (r) -#else -#define __CMSIS_GCC_OUT_REG(r) "=r" (r) -#define __CMSIS_GCC_RW_REG(r) "+r" (r) -#define __CMSIS_GCC_USE_REG(r) "r" (r) -#endif - -/** - \brief No Operation - \details No Operation does nothing. This instruction can be used for code alignment purposes. - */ -#define __NOP __builtin_arm_nop - -/** - \brief Wait For Interrupt - \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs. - */ -#define __WFI __builtin_arm_wfi - - -/** - \brief Wait For Event - \details Wait For Event is a hint instruction that permits the processor to enter - a low-power state until one of a number of events occurs. - */ -#define __WFE __builtin_arm_wfe - - -/** - \brief Send Event - \details Send Event is a hint instruction. It causes an event to be signaled to the CPU. - */ -#define __SEV __builtin_arm_sev - - -/** - \brief Instruction Synchronization Barrier - \details Instruction Synchronization Barrier flushes the pipeline in the processor, - so that all instructions following the ISB are fetched from cache or memory, - after the instruction has been completed. - */ -#define __ISB() __builtin_arm_isb(0xF) - -/** - \brief Data Synchronization Barrier - \details Acts as a special kind of Data Memory Barrier. - It completes when all explicit memory accesses before this instruction complete. - */ -#define __DSB() __builtin_arm_dsb(0xF) - - -/** - \brief Data Memory Barrier - \details Ensures the apparent order of the explicit memory operations before - and after the instruction, without ensuring their completion. - */ -#define __DMB() __builtin_arm_dmb(0xF) - - -/** - \brief Reverse byte order (32 bit) - \details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV(value) __builtin_bswap32(value) - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REV16(value) __ROR(__REV(value), 16) - - -/** - \brief Reverse byte order (16 bit) - \details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000. - \param [in] value Value to reverse - \return Reversed value - */ -#define __REVSH(value) (int16_t)__builtin_bswap16(value) - - -/** - \brief Rotate Right in unsigned value (32 bit) - \details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. - \param [in] op1 Value to rotate - \param [in] op2 Number of Bits to rotate - \return Rotated value - */ -__STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2) -{ - op2 %= 32U; - if (op2 == 0U) - { - return op1; - } - return (op1 >> op2) | (op1 << (32U - op2)); -} - - -/** - \brief Breakpoint - \details Causes the processor to enter Debug state. - Debug tools can use this to investigate system state when the instruction at a particular address is reached. - \param [in] value is ignored by the processor. - If required, a debugger can use it to store additional information about the breakpoint. - */ -#define __BKPT(value) __ASM volatile ("bkpt "#value) - - -/** - \brief Reverse bit order of value - \details Reverses the bit order of the given value. - \param [in] value Value to reverse - \return Reversed value - */ -#define __RBIT __builtin_arm_rbit - -/** - \brief Count leading zeros - \details Counts the number of leading zeros of a data value. - \param [in] value Value to count the leading zeros - \return number of leading zeros in value - */ -__STATIC_FORCEINLINE uint8_t __CLZ(uint32_t value) -{ - /* Even though __builtin_clz produces a CLZ instruction on ARM, formally - __builtin_clz(0) is undefined behaviour, so handle this case specially. - This guarantees ARM-compatible results if happening to compile on a non-ARM - target, and ensures the compiler doesn't decide to activate any - optimisations using the logic "value was passed to __builtin_clz, so it - is non-zero". - ARM Compiler 6.10 and possibly earlier will optimise this test away, leaving a - single CLZ instruction. - */ - if (value == 0U) - { - return 32U; - } - return __builtin_clz(value); -} - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - -/** - \brief LDR Exclusive (8 bit) - \details Executes a exclusive LDR instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDREXB (uint8_t)__builtin_arm_ldrex - - -/** - \brief LDR Exclusive (16 bit) - \details Executes a exclusive LDR instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDREXH (uint16_t)__builtin_arm_ldrex - - -/** - \brief LDR Exclusive (32 bit) - \details Executes a exclusive LDR instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDREXW (uint32_t)__builtin_arm_ldrex - - -/** - \brief STR Exclusive (8 bit) - \details Executes a exclusive STR instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXB (uint32_t)__builtin_arm_strex - - -/** - \brief STR Exclusive (16 bit) - \details Executes a exclusive STR instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXH (uint32_t)__builtin_arm_strex - - -/** - \brief STR Exclusive (32 bit) - \details Executes a exclusive STR instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STREXW (uint32_t)__builtin_arm_strex - - -/** - \brief Remove the exclusive lock - \details Removes the exclusive lock which is created by LDREX. - */ -#define __CLREX __builtin_arm_clrex - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -#define __SSAT __builtin_arm_ssat - - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -#define __USAT __builtin_arm_usat - - -/** - \brief Rotate Right with Extend (32 bit) - \details Moves each bit of a bitstring right by one bit. - The carry input is shifted in at the left end of the bitstring. - \param [in] value Value to rotate - \return Rotated value - */ -__STATIC_FORCEINLINE uint32_t __RRX(uint32_t value) -{ - uint32_t result; - - __ASM volatile ("rrx %0, %1" : __CMSIS_GCC_OUT_REG (result) : __CMSIS_GCC_USE_REG (value) ); - return(result); -} - - -/** - \brief LDRT Unprivileged (8 bit) - \details Executes a Unprivileged LDRT instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__STATIC_FORCEINLINE uint8_t __LDRBT(volatile uint8_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldrbt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint8_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDRT Unprivileged (16 bit) - \details Executes a Unprivileged LDRT instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__STATIC_FORCEINLINE uint16_t __LDRHT(volatile uint16_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldrht %0, %1" : "=r" (result) : "Q" (*ptr) ); - return ((uint16_t) result); /* Add explicit type cast here */ -} - - -/** - \brief LDRT Unprivileged (32 bit) - \details Executes a Unprivileged LDRT instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__STATIC_FORCEINLINE uint32_t __LDRT(volatile uint32_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldrt %0, %1" : "=r" (result) : "Q" (*ptr) ); - return(result); -} - - -/** - \brief STRT Unprivileged (8 bit) - \details Executes a Unprivileged STRT instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__STATIC_FORCEINLINE void __STRBT(uint8_t value, volatile uint8_t *ptr) -{ - __ASM volatile ("strbt %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief STRT Unprivileged (16 bit) - \details Executes a Unprivileged STRT instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__STATIC_FORCEINLINE void __STRHT(uint16_t value, volatile uint16_t *ptr) -{ - __ASM volatile ("strht %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) ); -} - - -/** - \brief STRT Unprivileged (32 bit) - \details Executes a Unprivileged STRT instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__STATIC_FORCEINLINE void __STRT(uint32_t value, volatile uint32_t *ptr) -{ - __ASM volatile ("strt %1, %0" : "=Q" (*ptr) : "r" (value) ); -} - -#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - -/** - \brief Signed Saturate - \details Saturates a signed value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (1..32) - \return Saturated value - */ -__STATIC_FORCEINLINE int32_t __SSAT(int32_t val, uint32_t sat) -{ - if ((sat >= 1U) && (sat <= 32U)) - { - const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U); - const int32_t min = -1 - max ; - if (val > max) - { - return max; - } - else if (val < min) - { - return min; - } - } - return val; -} - -/** - \brief Unsigned Saturate - \details Saturates an unsigned value. - \param [in] value Value to be saturated - \param [in] sat Bit position to saturate to (0..31) - \return Saturated value - */ -__STATIC_FORCEINLINE uint32_t __USAT(int32_t val, uint32_t sat) -{ - if (sat <= 31U) - { - const uint32_t max = ((1U << sat) - 1U); - if (val > (int32_t)max) - { - return max; - } - else if (val < 0) - { - return 0U; - } - } - return (uint32_t)val; -} - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - - -#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - -/** - \brief Load-Acquire (8 bit) - \details Executes a LDAB instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -__STATIC_FORCEINLINE uint8_t __LDAB(volatile uint8_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldab %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint8_t) result); -} - - -/** - \brief Load-Acquire (16 bit) - \details Executes a LDAH instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -__STATIC_FORCEINLINE uint16_t __LDAH(volatile uint16_t *ptr) -{ - uint32_t result; - - __ASM volatile ("ldah %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return ((uint16_t) result); -} - - -/** - \brief Load-Acquire (32 bit) - \details Executes a LDA instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -__STATIC_FORCEINLINE uint32_t __LDA(volatile uint32_t *ptr) -{ - uint32_t result; - - __ASM volatile ("lda %0, %1" : "=r" (result) : "Q" (*ptr) : "memory" ); - return(result); -} - - -/** - \brief Store-Release (8 bit) - \details Executes a STLB instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__STATIC_FORCEINLINE void __STLB(uint8_t value, volatile uint8_t *ptr) -{ - __ASM volatile ("stlb %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); -} - - -/** - \brief Store-Release (16 bit) - \details Executes a STLH instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__STATIC_FORCEINLINE void __STLH(uint16_t value, volatile uint16_t *ptr) -{ - __ASM volatile ("stlh %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); -} - - -/** - \brief Store-Release (32 bit) - \details Executes a STL instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - */ -__STATIC_FORCEINLINE void __STL(uint32_t value, volatile uint32_t *ptr) -{ - __ASM volatile ("stl %1, %0" : "=Q" (*ptr) : "r" ((uint32_t)value) : "memory" ); -} - - -/** - \brief Load-Acquire Exclusive (8 bit) - \details Executes a LDAB exclusive instruction for 8 bit value. - \param [in] ptr Pointer to data - \return value of type uint8_t at (*ptr) - */ -#define __LDAEXB (uint8_t)__builtin_arm_ldaex - - -/** - \brief Load-Acquire Exclusive (16 bit) - \details Executes a LDAH exclusive instruction for 16 bit values. - \param [in] ptr Pointer to data - \return value of type uint16_t at (*ptr) - */ -#define __LDAEXH (uint16_t)__builtin_arm_ldaex - - -/** - \brief Load-Acquire Exclusive (32 bit) - \details Executes a LDA exclusive instruction for 32 bit values. - \param [in] ptr Pointer to data - \return value of type uint32_t at (*ptr) - */ -#define __LDAEX (uint32_t)__builtin_arm_ldaex - - -/** - \brief Store-Release Exclusive (8 bit) - \details Executes a STLB exclusive instruction for 8 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STLEXB (uint32_t)__builtin_arm_stlex - - -/** - \brief Store-Release Exclusive (16 bit) - \details Executes a STLH exclusive instruction for 16 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STLEXH (uint32_t)__builtin_arm_stlex - - -/** - \brief Store-Release Exclusive (32 bit) - \details Executes a STL exclusive instruction for 32 bit values. - \param [in] value Value to store - \param [in] ptr Pointer to location - \return 0 Function succeeded - \return 1 Function failed - */ -#define __STLEX (uint32_t)__builtin_arm_stlex - -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - -/*@}*/ /* end of group CMSIS_Core_InstructionInterface */ - - -/* ########################### Core Function Access ########################### */ -/** \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions - @{ - */ - -/** - \brief Enable IRQ Interrupts - \details Enables IRQ interrupts by clearing special-purpose register PRIMASK. - Can only be executed in Privileged modes. - */ -#ifndef __ARM_COMPAT_H -__STATIC_FORCEINLINE void __enable_irq(void) -{ - __ASM volatile ("cpsie i" : : : "memory"); -} -#endif - - -/** - \brief Disable IRQ Interrupts - \details Disables IRQ interrupts by setting special-purpose register PRIMASK. - Can only be executed in Privileged modes. - */ -#ifndef __ARM_COMPAT_H -__STATIC_FORCEINLINE void __disable_irq(void) -{ - __ASM volatile ("cpsid i" : : : "memory"); -} -#endif - - -/** - \brief Get Control Register - \details Returns the content of the Control Register. - \return Control Register value - */ -__STATIC_FORCEINLINE uint32_t __get_CONTROL(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Control Register (non-secure) - \details Returns the content of the non-secure Control Register when in secure mode. - \return non-secure Control Register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_CONTROL_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, control_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Control Register - \details Writes the given value to the Control Register. - \param [in] control Control Register value to set - */ -__STATIC_FORCEINLINE void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) : "memory"); - __ISB(); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Control Register (non-secure) - \details Writes the given value to the non-secure Control Register when in secure state. - \param [in] control Control Register value to set - */ -__STATIC_FORCEINLINE void __TZ_set_CONTROL_NS(uint32_t control) -{ - __ASM volatile ("MSR control_ns, %0" : : "r" (control) : "memory"); - __ISB(); -} -#endif - - -/** - \brief Get IPSR Register - \details Returns the content of the IPSR Register. - \return IPSR Register value - */ -__STATIC_FORCEINLINE uint32_t __get_IPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); - return(result); -} - - -/** - \brief Get APSR Register - \details Returns the content of the APSR Register. - \return APSR Register value - */ -__STATIC_FORCEINLINE uint32_t __get_APSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, apsr" : "=r" (result) ); - return(result); -} - - -/** - \brief Get xPSR Register - \details Returns the content of the xPSR Register. - \return xPSR Register value - */ -__STATIC_FORCEINLINE uint32_t __get_xPSR(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); - return(result); -} - - -/** - \brief Get Process Stack Pointer - \details Returns the current value of the Process Stack Pointer (PSP). - \return PSP Register value - */ -__STATIC_FORCEINLINE uint32_t __get_PSP(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, psp" : "=r" (result) ); - return(result); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Process Stack Pointer (non-secure) - \details Returns the current value of the non-secure Process Stack Pointer (PSP) when in secure state. - \return PSP Register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSP_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, psp_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Process Stack Pointer - \details Assigns the given value to the Process Stack Pointer (PSP). - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Process Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Process Stack Pointer (PSP) when in secure state. - \param [in] topOfProcStack Process Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __TZ_set_PSP_NS(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp_ns, %0" : : "r" (topOfProcStack) : ); -} -#endif - - -/** - \brief Get Main Stack Pointer - \details Returns the current value of the Main Stack Pointer (MSP). - \return MSP Register value - */ -__STATIC_FORCEINLINE uint32_t __get_MSP(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, msp" : "=r" (result) ); - return(result); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Main Stack Pointer (non-secure) - \details Returns the current value of the non-secure Main Stack Pointer (MSP) when in secure state. - \return MSP Register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSP_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, msp_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Main Stack Pointer - \details Assigns the given value to the Main Stack Pointer (MSP). - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) : ); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Main Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Main Stack Pointer (MSP) when in secure state. - \param [in] topOfMainStack Main Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __TZ_set_MSP_NS(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp_ns, %0" : : "r" (topOfMainStack) : ); -} -#endif - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Stack Pointer (non-secure) - \details Returns the current value of the non-secure Stack Pointer (SP) when in secure state. - \return SP Register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_SP_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, sp_ns" : "=r" (result) ); - return(result); -} - - -/** - \brief Set Stack Pointer (non-secure) - \details Assigns the given value to the non-secure Stack Pointer (SP) when in secure state. - \param [in] topOfStack Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __TZ_set_SP_NS(uint32_t topOfStack) -{ - __ASM volatile ("MSR sp_ns, %0" : : "r" (topOfStack) : ); -} -#endif - - -/** - \brief Get Priority Mask - \details Returns the current state of the priority mask bit from the Priority Mask Register. - \return Priority Mask value - */ -__STATIC_FORCEINLINE uint32_t __get_PRIMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Priority Mask (non-secure) - \details Returns the current state of the non-secure priority mask bit from the Priority Mask Register when in secure state. - \return Priority Mask value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PRIMASK_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, primask_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Priority Mask - \details Assigns the given value to the Priority Mask Register. - \param [in] priMask Priority Mask - */ -__STATIC_FORCEINLINE void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Priority Mask (non-secure) - \details Assigns the given value to the non-secure Priority Mask Register when in secure state. - \param [in] priMask Priority Mask - */ -__STATIC_FORCEINLINE void __TZ_set_PRIMASK_NS(uint32_t priMask) -{ - __ASM volatile ("MSR primask_ns, %0" : : "r" (priMask) : "memory"); -} -#endif - - -#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) -/** - \brief Enable FIQ - \details Enables FIQ interrupts by clearing special-purpose register FAULTMASK. - Can only be executed in Privileged modes. - */ -__STATIC_FORCEINLINE void __enable_fault_irq(void) -{ - __ASM volatile ("cpsie f" : : : "memory"); -} - - -/** - \brief Disable FIQ - \details Disables FIQ interrupts by setting special-purpose register FAULTMASK. - Can only be executed in Privileged modes. - */ -__STATIC_FORCEINLINE void __disable_fault_irq(void) -{ - __ASM volatile ("cpsid f" : : : "memory"); -} - - -/** - \brief Get Base Priority - \details Returns the current value of the Base Priority register. - \return Base Priority register value - */ -__STATIC_FORCEINLINE uint32_t __get_BASEPRI(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, basepri" : "=r" (result) ); - return(result); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Base Priority (non-secure) - \details Returns the current value of the non-secure Base Priority register when in secure state. - \return Base Priority register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_BASEPRI_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, basepri_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Base Priority - \details Assigns the given value to the Base Priority register. - \param [in] basePri Base Priority value to set - */ -__STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) -{ - __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Base Priority (non-secure) - \details Assigns the given value to the non-secure Base Priority register when in secure state. - \param [in] basePri Base Priority value to set - */ -__STATIC_FORCEINLINE void __TZ_set_BASEPRI_NS(uint32_t basePri) -{ - __ASM volatile ("MSR basepri_ns, %0" : : "r" (basePri) : "memory"); -} -#endif - - -/** - \brief Set Base Priority with condition - \details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled, - or the new value increases the BASEPRI priority level. - \param [in] basePri Base Priority value to set - */ -__STATIC_FORCEINLINE void __set_BASEPRI_MAX(uint32_t basePri) -{ - __ASM volatile ("MSR basepri_max, %0" : : "r" (basePri) : "memory"); -} - - -/** - \brief Get Fault Mask - \details Returns the current value of the Fault Mask register. - \return Fault Mask register value - */ -__STATIC_FORCEINLINE uint32_t __get_FAULTMASK(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Fault Mask (non-secure) - \details Returns the current value of the non-secure Fault Mask register when in secure state. - \return Fault Mask register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_FAULTMASK_NS(void) -{ - uint32_t result; - - __ASM volatile ("MRS %0, faultmask_ns" : "=r" (result) ); - return(result); -} -#endif - - -/** - \brief Set Fault Mask - \details Assigns the given value to the Fault Mask register. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_FORCEINLINE void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) : "memory"); -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Fault Mask (non-secure) - \details Assigns the given value to the non-secure Fault Mask register when in secure state. - \param [in] faultMask Fault Mask value to set - */ -__STATIC_FORCEINLINE void __TZ_set_FAULTMASK_NS(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask_ns, %0" : : "r" (faultMask) : "memory"); -} -#endif - -#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \ - (defined (__ARM_ARCH_7EM__ ) && (__ARM_ARCH_7EM__ == 1)) || \ - (defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - - -#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) - -/** - \brief Get Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - - \details Returns the current value of the Process Stack Pointer Limit (PSPLIM). - \return PSPLIM Register value - */ -__STATIC_FORCEINLINE uint32_t __get_PSPLIM(void) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, psplim" : "=r" (result) ); - return result; -#endif -} - -#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Process Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always in non-secure - mode. - - \details Returns the current value of the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \return PSPLIM Register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_PSPLIM_NS(void) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure PSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, psplim_ns" : "=r" (result) ); - return result; -#endif -} -#endif - - -/** - \brief Set Process Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the Process Stack Pointer Limit (PSPLIM). - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set - */ -__STATIC_FORCEINLINE void __set_PSPLIM(uint32_t ProcStackPtrLimit) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim, %0" : : "r" (ProcStackPtrLimit)); -#endif -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Process Stack Pointer (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored in non-secure - mode. - - \details Assigns the given value to the non-secure Process Stack Pointer Limit (PSPLIM) when in secure state. - \param [in] ProcStackPtrLimit Process Stack Pointer Limit value to set - */ -__STATIC_FORCEINLINE void __TZ_set_PSPLIM_NS(uint32_t ProcStackPtrLimit) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure PSPLIM is RAZ/WI - (void)ProcStackPtrLimit; -#else - __ASM volatile ("MSR psplim_ns, %0\n" : : "r" (ProcStackPtrLimit)); -#endif -} -#endif - - -/** - \brief Get Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the Main Stack Pointer Limit (MSPLIM). - \return MSPLIM Register value - */ -__STATIC_FORCEINLINE uint32_t __get_MSPLIM(void) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim" : "=r" (result) ); - return result; -#endif -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Get Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence zero is returned always. - - \details Returns the current value of the non-secure Main Stack Pointer Limit(MSPLIM) when in secure state. - \return MSPLIM Register value - */ -__STATIC_FORCEINLINE uint32_t __TZ_get_MSPLIM_NS(void) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure MSPLIM is RAZ/WI - return 0U; -#else - uint32_t result; - __ASM volatile ("MRS %0, msplim_ns" : "=r" (result) ); - return result; -#endif -} -#endif - - -/** - \brief Set Main Stack Pointer Limit - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. - - \details Assigns the given value to the Main Stack Pointer Limit (MSPLIM). - \param [in] MainStackPtrLimit Main Stack Pointer Limit value to set - */ -__STATIC_FORCEINLINE void __set_MSPLIM(uint32_t MainStackPtrLimit) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) && \ - (!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3))) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim, %0" : : "r" (MainStackPtrLimit)); -#endif -} - - -#if (defined (__ARM_FEATURE_CMSE ) && (__ARM_FEATURE_CMSE == 3)) -/** - \brief Set Main Stack Pointer Limit (non-secure) - Devices without ARMv8-M Main Extensions (i.e. Cortex-M23) lack the non-secure - Stack Pointer Limit register hence the write is silently ignored. - - \details Assigns the given value to the non-secure Main Stack Pointer Limit (MSPLIM) when in secure state. - \param [in] MainStackPtrLimit Main Stack Pointer value to set - */ -__STATIC_FORCEINLINE void __TZ_set_MSPLIM_NS(uint32_t MainStackPtrLimit) -{ -#if (!((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__ ) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) ) - // without main extensions, the non-secure MSPLIM is RAZ/WI - (void)MainStackPtrLimit; -#else - __ASM volatile ("MSR msplim_ns, %0" : : "r" (MainStackPtrLimit)); -#endif -} -#endif - -#endif /* ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \ - (defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) || \ - (defined (__ARM_ARCH_8_1M_MAIN__) && (__ARM_ARCH_8_1M_MAIN__ == 1)) ) */ - -/** - \brief Get FPSCR - \details Returns the current value of the Floating Point Status/Control register. - \return Floating Point Status/Control register value - */ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#define __get_FPSCR (uint32_t)__builtin_arm_get_fpscr -#else -#define __get_FPSCR() ((uint32_t)0U) -#endif - -/** - \brief Set FPSCR - \details Assigns the given value to the Floating Point Status/Control register. - \param [in] fpscr Floating Point Status/Control value to set - */ -#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ - (defined (__FPU_USED ) && (__FPU_USED == 1U)) ) -#define __set_FPSCR __builtin_arm_set_fpscr -#else -#define __set_FPSCR(x) ((void)(x)) -#endif - - -/*@} end of CMSIS_Core_RegAccFunctions */ - - -/* ################### Compiler specific Intrinsics ########################### */ -/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics - Access to dedicated SIMD instructions - @{ -*/ - -#if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) - -#define __SADD8 __builtin_arm_sadd8 -#define __QADD8 __builtin_arm_qadd8 -#define __SHADD8 __builtin_arm_shadd8 -#define __UADD8 __builtin_arm_uadd8 -#define __UQADD8 __builtin_arm_uqadd8 -#define __UHADD8 __builtin_arm_uhadd8 -#define __SSUB8 __builtin_arm_ssub8 -#define __QSUB8 __builtin_arm_qsub8 -#define __SHSUB8 __builtin_arm_shsub8 -#define __USUB8 __builtin_arm_usub8 -#define __UQSUB8 __builtin_arm_uqsub8 -#define __UHSUB8 __builtin_arm_uhsub8 -#define __SADD16 __builtin_arm_sadd16 -#define __QADD16 __builtin_arm_qadd16 -#define __SHADD16 __builtin_arm_shadd16 -#define __UADD16 __builtin_arm_uadd16 -#define __UQADD16 __builtin_arm_uqadd16 -#define __UHADD16 __builtin_arm_uhadd16 -#define __SSUB16 __builtin_arm_ssub16 -#define __QSUB16 __builtin_arm_qsub16 -#define __SHSUB16 __builtin_arm_shsub16 -#define __USUB16 __builtin_arm_usub16 -#define __UQSUB16 __builtin_arm_uqsub16 -#define __UHSUB16 __builtin_arm_uhsub16 -#define __SASX __builtin_arm_sasx -#define __QASX __builtin_arm_qasx -#define __SHASX __builtin_arm_shasx -#define __UASX __builtin_arm_uasx -#define __UQASX __builtin_arm_uqasx -#define __UHASX __builtin_arm_uhasx -#define __SSAX __builtin_arm_ssax -#define __QSAX __builtin_arm_qsax -#define __SHSAX __builtin_arm_shsax -#define __USAX __builtin_arm_usax -#define __UQSAX __builtin_arm_uqsax -#define __UHSAX __builtin_arm_uhsax -#define __USAD8 __builtin_arm_usad8 -#define __USADA8 __builtin_arm_usada8 -#define __SSAT16 __builtin_arm_ssat16 -#define __USAT16 __builtin_arm_usat16 -#define __UXTB16 __builtin_arm_uxtb16 -#define __UXTAB16 __builtin_arm_uxtab16 -#define __SXTB16 __builtin_arm_sxtb16 -#define __SXTAB16 __builtin_arm_sxtab16 -#define __SMUAD __builtin_arm_smuad -#define __SMUADX __builtin_arm_smuadx -#define __SMLAD __builtin_arm_smlad -#define __SMLADX __builtin_arm_smladx -#define __SMLALD __builtin_arm_smlald -#define __SMLALDX __builtin_arm_smlaldx -#define __SMUSD __builtin_arm_smusd -#define __SMUSDX __builtin_arm_smusdx -#define __SMLSD __builtin_arm_smlsd -#define __SMLSDX __builtin_arm_smlsdx -#define __SMLSLD __builtin_arm_smlsld -#define __SMLSLDX __builtin_arm_smlsldx -#define __SEL __builtin_arm_sel -#define __QADD __builtin_arm_qadd -#define __QSUB __builtin_arm_qsub - -#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \ - ((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) ) - -#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \ - ((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) ) - -#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2)) - -#define __SXTAB16_RORn(ARG1, ARG2, ARG3) __SXTAB16(ARG1, __ROR(ARG2, ARG3)) - -__STATIC_FORCEINLINE int32_t __SMMLA (int32_t op1, int32_t op2, int32_t op3) -{ - int32_t result; - - __ASM volatile ("smmla %0, %1, %2, %3" : "=r" (result): "r" (op1), "r" (op2), "r" (op3) ); - return(result); -} - -#endif /* (__ARM_FEATURE_DSP == 1) */ -/*@} end of group CMSIS_SIMD_intrinsics */ - - -#endif /* __CMSIS_ARMCLANG_H */ diff --git a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_compiler.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_compiler.h deleted file mode 100644 index adbf296f1..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_compiler.h +++ /dev/null @@ -1,283 +0,0 @@ -/**************************************************************************//** - * @file cmsis_compiler.h - * @brief CMSIS compiler generic header file - * @version V5.1.0 - * @date 09. October 2018 - ******************************************************************************/ -/* - * Copyright (c) 2009-2018 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __CMSIS_COMPILER_H -#define __CMSIS_COMPILER_H - -#include - -/* - * Arm Compiler 4/5 - */ -#if defined ( __CC_ARM ) - #include "cmsis_armcc.h" - - -/* - * Arm Compiler 6.6 LTM (armclang) - */ -#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100) - #include "cmsis_armclang_ltm.h" - - /* - * Arm Compiler above 6.10.1 (armclang) - */ -#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100) - #include "cmsis_armclang.h" - - -/* - * GNU Compiler - */ -#elif defined ( __GNUC__ ) - #include "cmsis_gcc.h" - - -/* - * IAR Compiler - */ -#elif defined ( __ICCARM__ ) - #include - - -/* - * TI Arm Compiler - */ -#elif defined ( __TI_ARM__ ) - #include - - #ifndef __ASM - #define __ASM __asm - #endif - #ifndef __INLINE - #define __INLINE inline - #endif - #ifndef __STATIC_INLINE - #define __STATIC_INLINE static inline - #endif - #ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE __STATIC_INLINE - #endif - #ifndef __NO_RETURN - #define __NO_RETURN __attribute__((noreturn)) - #endif - #ifndef __USED - #define __USED __attribute__((used)) - #endif - #ifndef __WEAK - #define __WEAK __attribute__((weak)) - #endif - #ifndef __PACKED - #define __PACKED __attribute__((packed)) - #endif - #ifndef __PACKED_STRUCT - #define __PACKED_STRUCT struct __attribute__((packed)) - #endif - #ifndef __PACKED_UNION - #define __PACKED_UNION union __attribute__((packed)) - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - struct __attribute__((packed)) T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED - #define __ALIGNED(x) __attribute__((aligned(x))) - #endif - #ifndef __RESTRICT - #define __RESTRICT __restrict - #endif - #ifndef __COMPILER_BARRIER - #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. - #define __COMPILER_BARRIER() (void)0 - #endif - - -/* - * TASKING Compiler - */ -#elif defined ( __TASKING__ ) - /* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all intrinsics, - * Including the CMSIS ones. - */ - - #ifndef __ASM - #define __ASM __asm - #endif - #ifndef __INLINE - #define __INLINE inline - #endif - #ifndef __STATIC_INLINE - #define __STATIC_INLINE static inline - #endif - #ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE __STATIC_INLINE - #endif - #ifndef __NO_RETURN - #define __NO_RETURN __attribute__((noreturn)) - #endif - #ifndef __USED - #define __USED __attribute__((used)) - #endif - #ifndef __WEAK - #define __WEAK __attribute__((weak)) - #endif - #ifndef __PACKED - #define __PACKED __packed__ - #endif - #ifndef __PACKED_STRUCT - #define __PACKED_STRUCT struct __packed__ - #endif - #ifndef __PACKED_UNION - #define __PACKED_UNION union __packed__ - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - struct __packed__ T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED - #define __ALIGNED(x) __align(x) - #endif - #ifndef __RESTRICT - #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. - #define __RESTRICT - #endif - #ifndef __COMPILER_BARRIER - #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. - #define __COMPILER_BARRIER() (void)0 - #endif - - -/* - * COSMIC Compiler - */ -#elif defined ( __CSMC__ ) - #include - - #ifndef __ASM - #define __ASM _asm - #endif - #ifndef __INLINE - #define __INLINE inline - #endif - #ifndef __STATIC_INLINE - #define __STATIC_INLINE static inline - #endif - #ifndef __STATIC_FORCEINLINE - #define __STATIC_FORCEINLINE __STATIC_INLINE - #endif - #ifndef __NO_RETURN - // NO RETURN is automatically detected hence no warning here - #define __NO_RETURN - #endif - #ifndef __USED - #warning No compiler specific solution for __USED. __USED is ignored. - #define __USED - #endif - #ifndef __WEAK - #define __WEAK __weak - #endif - #ifndef __PACKED - #define __PACKED @packed - #endif - #ifndef __PACKED_STRUCT - #define __PACKED_STRUCT @packed struct - #endif - #ifndef __PACKED_UNION - #define __PACKED_UNION @packed union - #endif - #ifndef __UNALIGNED_UINT32 /* deprecated */ - @packed struct T_UINT32 { uint32_t v; }; - #define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v) - #endif - #ifndef __UNALIGNED_UINT16_WRITE - __PACKED_STRUCT T_UINT16_WRITE { uint16_t v; }; - #define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT16_READ - __PACKED_STRUCT T_UINT16_READ { uint16_t v; }; - #define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v) - #endif - #ifndef __UNALIGNED_UINT32_WRITE - __PACKED_STRUCT T_UINT32_WRITE { uint32_t v; }; - #define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val)) - #endif - #ifndef __UNALIGNED_UINT32_READ - __PACKED_STRUCT T_UINT32_READ { uint32_t v; }; - #define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v) - #endif - #ifndef __ALIGNED - #warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored. - #define __ALIGNED(x) - #endif - #ifndef __RESTRICT - #warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored. - #define __RESTRICT - #endif - #ifndef __COMPILER_BARRIER - #warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored. - #define __COMPILER_BARRIER() (void)0 - #endif - - -#else - #error Unknown compiler. -#endif - - -#endif /* __CMSIS_COMPILER_H */ - diff --git a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_version.h b/tests/projects/mdk/hello/src/lib/cmsis/cmsis_version.h deleted file mode 100644 index 2f048e455..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/cmsis_version.h +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************//** - * @file cmsis_version.h - * @brief CMSIS Core(M) Version definitions - * @version V5.0.4 - * @date 23. July 2019 - ******************************************************************************/ -/* - * Copyright (c) 2009-2019 ARM Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined (__clang__) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef __CMSIS_VERSION_H -#define __CMSIS_VERSION_H - -/* CMSIS Version definitions */ -#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */ -#define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */ -#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \ - __CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */ -#endif diff --git a/tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h b/tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h deleted file mode 100644 index 74fb87e5c..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/core_cm3.h +++ /dev/null @@ -1,1943 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.h - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V5.1.2 - * @date 04. June 2021 - ******************************************************************************/ -/* - * Copyright (c) 2009-2021 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined (__clang__) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef __CORE_CM3_H_GENERIC -#define __CORE_CM3_H_GENERIC - -#include - -#ifdef __cplusplus - extern "C" { -#endif - -/** - \page CMSIS_MISRA_Exceptions MISRA-C:2004 Compliance Exceptions - CMSIS violates the following MISRA-C:2004 rules: - - \li Required Rule 8.5, object/function definition in header file.
- Function definitions in header files are used to allow 'inlining'. - - \li Required Rule 18.4, declaration of union type or object of union type: '{...}'.
- Unions are used for effective representation of core registers. - - \li Advisory Rule 19.7, Function-like macro defined.
- Function-like macros are used to allow more efficient code. - */ - - -/******************************************************************************* - * CMSIS definitions - ******************************************************************************/ -/** - \ingroup Cortex_M3 - @{ - */ - -#include "cmsis_version.h" - -/* CMSIS CM3 definitions */ -#define __CM3_CMSIS_VERSION_MAIN (__CM_CMSIS_VERSION_MAIN) /*!< \deprecated [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB (__CM_CMSIS_VERSION_SUB) /*!< \deprecated [15:0] CMSIS HAL sub version */ -#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16U) | \ - __CM3_CMSIS_VERSION_SUB ) /*!< \deprecated CMSIS HAL version number */ - -#define __CORTEX_M (3U) /*!< Cortex-M Core */ - -/** __FPU_USED indicates whether an FPU is used or not. - This core does not support an FPU at all -*/ -#define __FPU_USED 0U - -#if defined ( __CC_ARM ) - #if defined __TARGET_FPU_VFP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #if defined __ARM_FP - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __GNUC__ ) - #if defined (__VFP_FP__) && !defined(__SOFTFP__) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __ICCARM__ ) - #if defined __ARMVFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __TI_ARM__ ) - #if defined __TI_VFP_SUPPORT__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __TASKING__ ) - #if defined __FPU_VFP__ - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#elif defined ( __CSMC__ ) - #if ( __CSMC__ & 0x400U) - #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)" - #endif - -#endif - -#include "cmsis_compiler.h" /* CMSIS compiler specific defines */ - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CM3_H_GENERIC */ - -#ifndef __CMSIS_GENERIC - -#ifndef __CORE_CM3_H_DEPENDANT -#define __CORE_CM3_H_DEPENDANT - -#ifdef __cplusplus - extern "C" { -#endif - -/* check device defines and use defaults */ -#if defined __CHECK_DEVICE_DEFINES - #ifndef __CM3_REV - #define __CM3_REV 0x0200U - #warning "__CM3_REV not defined in device header file; using default!" - #endif - - #ifndef __MPU_PRESENT - #define __MPU_PRESENT 0U - #warning "__MPU_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __VTOR_PRESENT - #define __VTOR_PRESENT 1U - #warning "__VTOR_PRESENT not defined in device header file; using default!" - #endif - - #ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 3U - #warning "__NVIC_PRIO_BITS not defined in device header file; using default!" - #endif - - #ifndef __Vendor_SysTickConfig - #define __Vendor_SysTickConfig 0U - #warning "__Vendor_SysTickConfig not defined in device header file; using default!" - #endif -#endif - -/* IO definitions (access restrictions to peripheral registers) */ -/** - \defgroup CMSIS_glob_defs CMSIS Global Defines - - IO Type Qualifiers are used - \li to specify the access to peripheral variables. - \li for automatic generation of peripheral register debug information. -*/ -#ifdef __cplusplus - #define __I volatile /*!< Defines 'read only' permissions */ -#else - #define __I volatile const /*!< Defines 'read only' permissions */ -#endif -#define __O volatile /*!< Defines 'write only' permissions */ -#define __IO volatile /*!< Defines 'read / write' permissions */ - -/* following defines should be used for structure members */ -#define __IM volatile const /*! Defines 'read only' structure member permissions */ -#define __OM volatile /*! Defines 'write only' structure member permissions */ -#define __IOM volatile /*! Defines 'read / write' structure member permissions */ - -/*@} end of group Cortex_M3 */ - - - -/******************************************************************************* - * Register Abstraction - Core Register contain: - - Core Register - - Core NVIC Register - - Core SCB Register - - Core SysTick Register - - Core Debug Register - - Core MPU Register - ******************************************************************************/ -/** - \defgroup CMSIS_core_register Defines and Type Definitions - \brief Type definitions and defines for Cortex-M processor based devices. -*/ - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_CORE Status and Control Registers - \brief Core Register type definitions. - @{ - */ - -/** - \brief Union type to access the Application Program Status Register (APSR). - */ -typedef union -{ - struct - { - uint32_t _reserved0:27; /*!< bit: 0..26 Reserved */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} APSR_Type; - -/* APSR Register Definitions */ -#define APSR_N_Pos 31U /*!< APSR: N Position */ -#define APSR_N_Msk (1UL << APSR_N_Pos) /*!< APSR: N Mask */ - -#define APSR_Z_Pos 30U /*!< APSR: Z Position */ -#define APSR_Z_Msk (1UL << APSR_Z_Pos) /*!< APSR: Z Mask */ - -#define APSR_C_Pos 29U /*!< APSR: C Position */ -#define APSR_C_Msk (1UL << APSR_C_Pos) /*!< APSR: C Mask */ - -#define APSR_V_Pos 28U /*!< APSR: V Position */ -#define APSR_V_Msk (1UL << APSR_V_Pos) /*!< APSR: V Mask */ - -#define APSR_Q_Pos 27U /*!< APSR: Q Position */ -#define APSR_Q_Msk (1UL << APSR_Q_Pos) /*!< APSR: Q Mask */ - - -/** - \brief Union type to access the Interrupt Program Status Register (IPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:23; /*!< bit: 9..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} IPSR_Type; - -/* IPSR Register Definitions */ -#define IPSR_ISR_Pos 0U /*!< IPSR: ISR Position */ -#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */ - - -/** - \brief Union type to access the Special-Purpose Program Status Registers (xPSR). - */ -typedef union -{ - struct - { - uint32_t ISR:9; /*!< bit: 0.. 8 Exception number */ - uint32_t _reserved0:1; /*!< bit: 9 Reserved */ - uint32_t ICI_IT_1:6; /*!< bit: 10..15 ICI/IT part 1 */ - uint32_t _reserved1:8; /*!< bit: 16..23 Reserved */ - uint32_t T:1; /*!< bit: 24 Thumb bit */ - uint32_t ICI_IT_2:2; /*!< bit: 25..26 ICI/IT part 2 */ - uint32_t Q:1; /*!< bit: 27 Saturation condition flag */ - uint32_t V:1; /*!< bit: 28 Overflow condition code flag */ - uint32_t C:1; /*!< bit: 29 Carry condition code flag */ - uint32_t Z:1; /*!< bit: 30 Zero condition code flag */ - uint32_t N:1; /*!< bit: 31 Negative condition code flag */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} xPSR_Type; - -/* xPSR Register Definitions */ -#define xPSR_N_Pos 31U /*!< xPSR: N Position */ -#define xPSR_N_Msk (1UL << xPSR_N_Pos) /*!< xPSR: N Mask */ - -#define xPSR_Z_Pos 30U /*!< xPSR: Z Position */ -#define xPSR_Z_Msk (1UL << xPSR_Z_Pos) /*!< xPSR: Z Mask */ - -#define xPSR_C_Pos 29U /*!< xPSR: C Position */ -#define xPSR_C_Msk (1UL << xPSR_C_Pos) /*!< xPSR: C Mask */ - -#define xPSR_V_Pos 28U /*!< xPSR: V Position */ -#define xPSR_V_Msk (1UL << xPSR_V_Pos) /*!< xPSR: V Mask */ - -#define xPSR_Q_Pos 27U /*!< xPSR: Q Position */ -#define xPSR_Q_Msk (1UL << xPSR_Q_Pos) /*!< xPSR: Q Mask */ - -#define xPSR_ICI_IT_2_Pos 25U /*!< xPSR: ICI/IT part 2 Position */ -#define xPSR_ICI_IT_2_Msk (3UL << xPSR_ICI_IT_2_Pos) /*!< xPSR: ICI/IT part 2 Mask */ - -#define xPSR_T_Pos 24U /*!< xPSR: T Position */ -#define xPSR_T_Msk (1UL << xPSR_T_Pos) /*!< xPSR: T Mask */ - -#define xPSR_ICI_IT_1_Pos 10U /*!< xPSR: ICI/IT part 1 Position */ -#define xPSR_ICI_IT_1_Msk (0x3FUL << xPSR_ICI_IT_1_Pos) /*!< xPSR: ICI/IT part 1 Mask */ - -#define xPSR_ISR_Pos 0U /*!< xPSR: ISR Position */ -#define xPSR_ISR_Msk (0x1FFUL /*<< xPSR_ISR_Pos*/) /*!< xPSR: ISR Mask */ - - -/** - \brief Union type to access the Control Registers (CONTROL). - */ -typedef union -{ - struct - { - uint32_t nPRIV:1; /*!< bit: 0 Execution privilege in Thread mode */ - uint32_t SPSEL:1; /*!< bit: 1 Stack to be used */ - uint32_t _reserved1:30; /*!< bit: 2..31 Reserved */ - } b; /*!< Structure used for bit access */ - uint32_t w; /*!< Type used for word access */ -} CONTROL_Type; - -/* CONTROL Register Definitions */ -#define CONTROL_SPSEL_Pos 1U /*!< CONTROL: SPSEL Position */ -#define CONTROL_SPSEL_Msk (1UL << CONTROL_SPSEL_Pos) /*!< CONTROL: SPSEL Mask */ - -#define CONTROL_nPRIV_Pos 0U /*!< CONTROL: nPRIV Position */ -#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */ - -/*@} end of group CMSIS_CORE */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_NVIC Nested Vectored Interrupt Controller (NVIC) - \brief Type definitions for the NVIC Registers - @{ - */ - -/** - \brief Structure type to access the Nested Vectored Interrupt Controller (NVIC). - */ -typedef struct -{ - __IOM uint32_t ISER[8U]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */ - uint32_t RESERVED0[24U]; - __IOM uint32_t ICER[8U]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */ - uint32_t RESERVED1[24U]; - __IOM uint32_t ISPR[8U]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */ - uint32_t RESERVED2[24U]; - __IOM uint32_t ICPR[8U]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */ - uint32_t RESERVED3[24U]; - __IOM uint32_t IABR[8U]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ - uint32_t RESERVED4[56U]; - __IOM uint8_t IP[240U]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644U]; - __OM uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */ -} NVIC_Type; - -/* Software Triggered Interrupt Register Definitions */ -#define NVIC_STIR_INTID_Pos 0U /*!< STIR: INTLINESNUM Position */ -#define NVIC_STIR_INTID_Msk (0x1FFUL /*<< NVIC_STIR_INTID_Pos*/) /*!< STIR: INTLINESNUM Mask */ - -/*@} end of group CMSIS_NVIC */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SCB System Control Block (SCB) - \brief Type definitions for the System Control Block Registers - @{ - */ - -/** - \brief Structure type to access the System Control Block (SCB). - */ -typedef struct -{ - __IM uint32_t CPUID; /*!< Offset: 0x000 (R/ ) CPUID Base Register */ - __IOM uint32_t ICSR; /*!< Offset: 0x004 (R/W) Interrupt Control and State Register */ - __IOM uint32_t VTOR; /*!< Offset: 0x008 (R/W) Vector Table Offset Register */ - __IOM uint32_t AIRCR; /*!< Offset: 0x00C (R/W) Application Interrupt and Reset Control Register */ - __IOM uint32_t SCR; /*!< Offset: 0x010 (R/W) System Control Register */ - __IOM uint32_t CCR; /*!< Offset: 0x014 (R/W) Configuration Control Register */ - __IOM uint8_t SHP[12U]; /*!< Offset: 0x018 (R/W) System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IOM uint32_t SHCSR; /*!< Offset: 0x024 (R/W) System Handler Control and State Register */ - __IOM uint32_t CFSR; /*!< Offset: 0x028 (R/W) Configurable Fault Status Register */ - __IOM uint32_t HFSR; /*!< Offset: 0x02C (R/W) HardFault Status Register */ - __IOM uint32_t DFSR; /*!< Offset: 0x030 (R/W) Debug Fault Status Register */ - __IOM uint32_t MMFAR; /*!< Offset: 0x034 (R/W) MemManage Fault Address Register */ - __IOM uint32_t BFAR; /*!< Offset: 0x038 (R/W) BusFault Address Register */ - __IOM uint32_t AFSR; /*!< Offset: 0x03C (R/W) Auxiliary Fault Status Register */ - __IM uint32_t PFR[2U]; /*!< Offset: 0x040 (R/ ) Processor Feature Register */ - __IM uint32_t DFR; /*!< Offset: 0x048 (R/ ) Debug Feature Register */ - __IM uint32_t ADR; /*!< Offset: 0x04C (R/ ) Auxiliary Feature Register */ - __IM uint32_t MMFR[4U]; /*!< Offset: 0x050 (R/ ) Memory Model Feature Register */ - __IM uint32_t ISAR[5U]; /*!< Offset: 0x060 (R/ ) Instruction Set Attributes Register */ - uint32_t RESERVED0[5U]; - __IOM uint32_t CPACR; /*!< Offset: 0x088 (R/W) Coprocessor Access Control Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24U /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFUL << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20U /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFUL << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_ARCHITECTURE_Pos 16U /*!< SCB CPUID: ARCHITECTURE Position */ -#define SCB_CPUID_ARCHITECTURE_Msk (0xFUL << SCB_CPUID_ARCHITECTURE_Pos) /*!< SCB CPUID: ARCHITECTURE Mask */ - -#define SCB_CPUID_PARTNO_Pos 4U /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFUL << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0U /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFUL /*<< SCB_CPUID_REVISION_Pos*/) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31U /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1UL << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28U /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1UL << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27U /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1UL << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26U /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1UL << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25U /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1UL << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23U /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1UL << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22U /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1UL << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12U /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFUL << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11U /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1UL << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0U /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFUL /*<< SCB_ICSR_VECTACTIVE_Pos*/) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Vector Table Offset Register Definitions */ -#if defined (__CM3_REV) && (__CM3_REV < 0x0201U) /* core r2p1 */ -#define SCB_VTOR_TBLBASE_Pos 29U /*!< SCB VTOR: TBLBASE Position */ -#define SCB_VTOR_TBLBASE_Msk (1UL << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ - -#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#else -#define SCB_VTOR_TBLOFF_Pos 7U /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x1FFFFFFUL << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ -#endif - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16U /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFUL << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16U /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFUL << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15U /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1UL << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2U /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1UL << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1U /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1UL << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0U /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1UL /*<< SCB_AIRCR_VECTRESET_Pos*/) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4U /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1UL << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2U /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1UL << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1U /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1UL << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_STKALIGN_Pos 9U /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1UL << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8U /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1UL << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4U /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1UL << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3U /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1UL << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1U /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1UL << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0U /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1UL /*<< SCB_CCR_NONBASETHRDENA_Pos*/) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18U /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1UL << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17U /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1UL << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16U /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1UL << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15U /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1UL << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14U /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1UL << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13U /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1UL << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12U /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1UL << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11U /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1UL << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10U /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1UL << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8U /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1UL << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7U /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1UL << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3U /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1UL << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1U /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1UL << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0U /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1UL /*<< SCB_SHCSR_MEMFAULTACT_Pos*/) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Register Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16U /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFUL << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8U /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFUL << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0U /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFUL /*<< SCB_CFSR_MEMFAULTSR_Pos*/) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* MemManage Fault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_MMARVALID_Pos (SCB_CFSR_MEMFAULTSR_Pos + 7U) /*!< SCB CFSR (MMFSR): MMARVALID Position */ -#define SCB_CFSR_MMARVALID_Msk (1UL << SCB_CFSR_MMARVALID_Pos) /*!< SCB CFSR (MMFSR): MMARVALID Mask */ - -#define SCB_CFSR_MSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 4U) /*!< SCB CFSR (MMFSR): MSTKERR Position */ -#define SCB_CFSR_MSTKERR_Msk (1UL << SCB_CFSR_MSTKERR_Pos) /*!< SCB CFSR (MMFSR): MSTKERR Mask */ - -#define SCB_CFSR_MUNSTKERR_Pos (SCB_CFSR_MEMFAULTSR_Pos + 3U) /*!< SCB CFSR (MMFSR): MUNSTKERR Position */ -#define SCB_CFSR_MUNSTKERR_Msk (1UL << SCB_CFSR_MUNSTKERR_Pos) /*!< SCB CFSR (MMFSR): MUNSTKERR Mask */ - -#define SCB_CFSR_DACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 1U) /*!< SCB CFSR (MMFSR): DACCVIOL Position */ -#define SCB_CFSR_DACCVIOL_Msk (1UL << SCB_CFSR_DACCVIOL_Pos) /*!< SCB CFSR (MMFSR): DACCVIOL Mask */ - -#define SCB_CFSR_IACCVIOL_Pos (SCB_CFSR_MEMFAULTSR_Pos + 0U) /*!< SCB CFSR (MMFSR): IACCVIOL Position */ -#define SCB_CFSR_IACCVIOL_Msk (1UL /*<< SCB_CFSR_IACCVIOL_Pos*/) /*!< SCB CFSR (MMFSR): IACCVIOL Mask */ - -/* BusFault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_BFARVALID_Pos (SCB_CFSR_BUSFAULTSR_Pos + 7U) /*!< SCB CFSR (BFSR): BFARVALID Position */ -#define SCB_CFSR_BFARVALID_Msk (1UL << SCB_CFSR_BFARVALID_Pos) /*!< SCB CFSR (BFSR): BFARVALID Mask */ - -#define SCB_CFSR_STKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 4U) /*!< SCB CFSR (BFSR): STKERR Position */ -#define SCB_CFSR_STKERR_Msk (1UL << SCB_CFSR_STKERR_Pos) /*!< SCB CFSR (BFSR): STKERR Mask */ - -#define SCB_CFSR_UNSTKERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 3U) /*!< SCB CFSR (BFSR): UNSTKERR Position */ -#define SCB_CFSR_UNSTKERR_Msk (1UL << SCB_CFSR_UNSTKERR_Pos) /*!< SCB CFSR (BFSR): UNSTKERR Mask */ - -#define SCB_CFSR_IMPRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 2U) /*!< SCB CFSR (BFSR): IMPRECISERR Position */ -#define SCB_CFSR_IMPRECISERR_Msk (1UL << SCB_CFSR_IMPRECISERR_Pos) /*!< SCB CFSR (BFSR): IMPRECISERR Mask */ - -#define SCB_CFSR_PRECISERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 1U) /*!< SCB CFSR (BFSR): PRECISERR Position */ -#define SCB_CFSR_PRECISERR_Msk (1UL << SCB_CFSR_PRECISERR_Pos) /*!< SCB CFSR (BFSR): PRECISERR Mask */ - -#define SCB_CFSR_IBUSERR_Pos (SCB_CFSR_BUSFAULTSR_Pos + 0U) /*!< SCB CFSR (BFSR): IBUSERR Position */ -#define SCB_CFSR_IBUSERR_Msk (1UL << SCB_CFSR_IBUSERR_Pos) /*!< SCB CFSR (BFSR): IBUSERR Mask */ - -/* UsageFault Status Register (part of SCB Configurable Fault Status Register) */ -#define SCB_CFSR_DIVBYZERO_Pos (SCB_CFSR_USGFAULTSR_Pos + 9U) /*!< SCB CFSR (UFSR): DIVBYZERO Position */ -#define SCB_CFSR_DIVBYZERO_Msk (1UL << SCB_CFSR_DIVBYZERO_Pos) /*!< SCB CFSR (UFSR): DIVBYZERO Mask */ - -#define SCB_CFSR_UNALIGNED_Pos (SCB_CFSR_USGFAULTSR_Pos + 8U) /*!< SCB CFSR (UFSR): UNALIGNED Position */ -#define SCB_CFSR_UNALIGNED_Msk (1UL << SCB_CFSR_UNALIGNED_Pos) /*!< SCB CFSR (UFSR): UNALIGNED Mask */ - -#define SCB_CFSR_NOCP_Pos (SCB_CFSR_USGFAULTSR_Pos + 3U) /*!< SCB CFSR (UFSR): NOCP Position */ -#define SCB_CFSR_NOCP_Msk (1UL << SCB_CFSR_NOCP_Pos) /*!< SCB CFSR (UFSR): NOCP Mask */ - -#define SCB_CFSR_INVPC_Pos (SCB_CFSR_USGFAULTSR_Pos + 2U) /*!< SCB CFSR (UFSR): INVPC Position */ -#define SCB_CFSR_INVPC_Msk (1UL << SCB_CFSR_INVPC_Pos) /*!< SCB CFSR (UFSR): INVPC Mask */ - -#define SCB_CFSR_INVSTATE_Pos (SCB_CFSR_USGFAULTSR_Pos + 1U) /*!< SCB CFSR (UFSR): INVSTATE Position */ -#define SCB_CFSR_INVSTATE_Msk (1UL << SCB_CFSR_INVSTATE_Pos) /*!< SCB CFSR (UFSR): INVSTATE Mask */ - -#define SCB_CFSR_UNDEFINSTR_Pos (SCB_CFSR_USGFAULTSR_Pos + 0U) /*!< SCB CFSR (UFSR): UNDEFINSTR Position */ -#define SCB_CFSR_UNDEFINSTR_Msk (1UL << SCB_CFSR_UNDEFINSTR_Pos) /*!< SCB CFSR (UFSR): UNDEFINSTR Mask */ - -/* SCB Hard Fault Status Register Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31U /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1UL << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30U /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1UL << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1U /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1UL << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4U /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1UL << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3U /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1UL << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2U /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1UL << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1U /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1UL << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0U /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1UL /*<< SCB_DFSR_HALTED_Pos*/) /*!< SCB DFSR: HALTED Mask */ - -/*@} end of group CMSIS_SCB */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SCnSCB System Controls not in SCB (SCnSCB) - \brief Type definitions for the System Control and ID Register not in the SCB - @{ - */ - -/** - \brief Structure type to access the System Control and ID Register not in the SCB. - */ -typedef struct -{ - uint32_t RESERVED0[1U]; - __IM uint32_t ICTR; /*!< Offset: 0x004 (R/ ) Interrupt Controller Type Register */ -#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) - __IOM uint32_t ACTLR; /*!< Offset: 0x008 (R/W) Auxiliary Control Register */ -#else - uint32_t RESERVED1[1U]; -#endif -} SCnSCB_Type; - -/* Interrupt Controller Type Register Definitions */ -#define SCnSCB_ICTR_INTLINESNUM_Pos 0U /*!< ICTR: INTLINESNUM Position */ -#define SCnSCB_ICTR_INTLINESNUM_Msk (0xFUL /*<< SCnSCB_ICTR_INTLINESNUM_Pos*/) /*!< ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ -#if defined (__CM3_REV) && (__CM3_REV >= 0x200U) -#define SCnSCB_ACTLR_DISOOFP_Pos 9U /*!< ACTLR: DISOOFP Position */ -#define SCnSCB_ACTLR_DISOOFP_Msk (1UL << SCnSCB_ACTLR_DISOOFP_Pos) /*!< ACTLR: DISOOFP Mask */ - -#define SCnSCB_ACTLR_DISFPCA_Pos 8U /*!< ACTLR: DISFPCA Position */ -#define SCnSCB_ACTLR_DISFPCA_Msk (1UL << SCnSCB_ACTLR_DISFPCA_Pos) /*!< ACTLR: DISFPCA Mask */ - -#define SCnSCB_ACTLR_DISFOLD_Pos 2U /*!< ACTLR: DISFOLD Position */ -#define SCnSCB_ACTLR_DISFOLD_Msk (1UL << SCnSCB_ACTLR_DISFOLD_Pos) /*!< ACTLR: DISFOLD Mask */ - -#define SCnSCB_ACTLR_DISDEFWBUF_Pos 1U /*!< ACTLR: DISDEFWBUF Position */ -#define SCnSCB_ACTLR_DISDEFWBUF_Msk (1UL << SCnSCB_ACTLR_DISDEFWBUF_Pos) /*!< ACTLR: DISDEFWBUF Mask */ - -#define SCnSCB_ACTLR_DISMCYCINT_Pos 0U /*!< ACTLR: DISMCYCINT Position */ -#define SCnSCB_ACTLR_DISMCYCINT_Msk (1UL /*<< SCnSCB_ACTLR_DISMCYCINT_Pos*/) /*!< ACTLR: DISMCYCINT Mask */ -#endif - -/*@} end of group CMSIS_SCnotSCB */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_SysTick System Tick Timer (SysTick) - \brief Type definitions for the System Timer Registers. - @{ - */ - -/** - \brief Structure type to access the System Timer (SysTick). - */ -typedef struct -{ - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */ - __IOM uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */ - __IOM uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */ - __IM uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16U /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1UL << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2U /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1UL << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1U /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1UL << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0U /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1UL /*<< SysTick_CTRL_ENABLE_Pos*/) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0U /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFUL /*<< SysTick_LOAD_RELOAD_Pos*/) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0U /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFUL /*<< SysTick_VAL_CURRENT_Pos*/) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31U /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1UL << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30U /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1UL << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0U /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFUL /*<< SysTick_CALIB_TENMS_Pos*/) /*!< SysTick CALIB: TENMS Mask */ - -/*@} end of group CMSIS_SysTick */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_ITM Instrumentation Trace Macrocell (ITM) - \brief Type definitions for the Instrumentation Trace Macrocell (ITM) - @{ - */ - -/** - \brief Structure type to access the Instrumentation Trace Macrocell Register (ITM). - */ -typedef struct -{ - __OM union - { - __OM uint8_t u8; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 8-bit */ - __OM uint16_t u16; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 16-bit */ - __OM uint32_t u32; /*!< Offset: 0x000 ( /W) ITM Stimulus Port 32-bit */ - } PORT [32U]; /*!< Offset: 0x000 ( /W) ITM Stimulus Port Registers */ - uint32_t RESERVED0[864U]; - __IOM uint32_t TER; /*!< Offset: 0xE00 (R/W) ITM Trace Enable Register */ - uint32_t RESERVED1[15U]; - __IOM uint32_t TPR; /*!< Offset: 0xE40 (R/W) ITM Trace Privilege Register */ - uint32_t RESERVED2[15U]; - __IOM uint32_t TCR; /*!< Offset: 0xE80 (R/W) ITM Trace Control Register */ - uint32_t RESERVED3[32U]; - uint32_t RESERVED4[43U]; - __OM uint32_t LAR; /*!< Offset: 0xFB0 ( /W) ITM Lock Access Register */ - __IM uint32_t LSR; /*!< Offset: 0xFB4 (R/ ) ITM Lock Status Register */ - uint32_t RESERVED5[6U]; - __IM uint32_t PID4; /*!< Offset: 0xFD0 (R/ ) ITM Peripheral Identification Register #4 */ - __IM uint32_t PID5; /*!< Offset: 0xFD4 (R/ ) ITM Peripheral Identification Register #5 */ - __IM uint32_t PID6; /*!< Offset: 0xFD8 (R/ ) ITM Peripheral Identification Register #6 */ - __IM uint32_t PID7; /*!< Offset: 0xFDC (R/ ) ITM Peripheral Identification Register #7 */ - __IM uint32_t PID0; /*!< Offset: 0xFE0 (R/ ) ITM Peripheral Identification Register #0 */ - __IM uint32_t PID1; /*!< Offset: 0xFE4 (R/ ) ITM Peripheral Identification Register #1 */ - __IM uint32_t PID2; /*!< Offset: 0xFE8 (R/ ) ITM Peripheral Identification Register #2 */ - __IM uint32_t PID3; /*!< Offset: 0xFEC (R/ ) ITM Peripheral Identification Register #3 */ - __IM uint32_t CID0; /*!< Offset: 0xFF0 (R/ ) ITM Component Identification Register #0 */ - __IM uint32_t CID1; /*!< Offset: 0xFF4 (R/ ) ITM Component Identification Register #1 */ - __IM uint32_t CID2; /*!< Offset: 0xFF8 (R/ ) ITM Component Identification Register #2 */ - __IM uint32_t CID3; /*!< Offset: 0xFFC (R/ ) ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0U /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFFFFFFFFUL /*<< ITM_TPR_PRIVMASK_Pos*/) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23U /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1UL << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_TraceBusID_Pos 16U /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_TraceBusID_Msk (0x7FUL << ITM_TCR_TraceBusID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_GTSFREQ_Pos 10U /*!< ITM TCR: Global timestamp frequency Position */ -#define ITM_TCR_GTSFREQ_Msk (3UL << ITM_TCR_GTSFREQ_Pos) /*!< ITM TCR: Global timestamp frequency Mask */ - -#define ITM_TCR_TSPrescale_Pos 8U /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3UL << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4U /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1UL << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3U /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1UL << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2U /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1UL << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1U /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1UL << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0U /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1UL /*<< ITM_TCR_ITMENA_Pos*/) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2U /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1UL << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1U /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1UL << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0U /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1UL /*<< ITM_LSR_Present_Pos*/) /*!< ITM LSR: Present Mask */ - -/*@}*/ /* end of group CMSIS_ITM */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_DWT Data Watchpoint and Trace (DWT) - \brief Type definitions for the Data Watchpoint and Trace (DWT) - @{ - */ - -/** - \brief Structure type to access the Data Watchpoint and Trace Register (DWT). - */ -typedef struct -{ - __IOM uint32_t CTRL; /*!< Offset: 0x000 (R/W) Control Register */ - __IOM uint32_t CYCCNT; /*!< Offset: 0x004 (R/W) Cycle Count Register */ - __IOM uint32_t CPICNT; /*!< Offset: 0x008 (R/W) CPI Count Register */ - __IOM uint32_t EXCCNT; /*!< Offset: 0x00C (R/W) Exception Overhead Count Register */ - __IOM uint32_t SLEEPCNT; /*!< Offset: 0x010 (R/W) Sleep Count Register */ - __IOM uint32_t LSUCNT; /*!< Offset: 0x014 (R/W) LSU Count Register */ - __IOM uint32_t FOLDCNT; /*!< Offset: 0x018 (R/W) Folded-instruction Count Register */ - __IM uint32_t PCSR; /*!< Offset: 0x01C (R/ ) Program Counter Sample Register */ - __IOM uint32_t COMP0; /*!< Offset: 0x020 (R/W) Comparator Register 0 */ - __IOM uint32_t MASK0; /*!< Offset: 0x024 (R/W) Mask Register 0 */ - __IOM uint32_t FUNCTION0; /*!< Offset: 0x028 (R/W) Function Register 0 */ - uint32_t RESERVED0[1U]; - __IOM uint32_t COMP1; /*!< Offset: 0x030 (R/W) Comparator Register 1 */ - __IOM uint32_t MASK1; /*!< Offset: 0x034 (R/W) Mask Register 1 */ - __IOM uint32_t FUNCTION1; /*!< Offset: 0x038 (R/W) Function Register 1 */ - uint32_t RESERVED1[1U]; - __IOM uint32_t COMP2; /*!< Offset: 0x040 (R/W) Comparator Register 2 */ - __IOM uint32_t MASK2; /*!< Offset: 0x044 (R/W) Mask Register 2 */ - __IOM uint32_t FUNCTION2; /*!< Offset: 0x048 (R/W) Function Register 2 */ - uint32_t RESERVED2[1U]; - __IOM uint32_t COMP3; /*!< Offset: 0x050 (R/W) Comparator Register 3 */ - __IOM uint32_t MASK3; /*!< Offset: 0x054 (R/W) Mask Register 3 */ - __IOM uint32_t FUNCTION3; /*!< Offset: 0x058 (R/W) Function Register 3 */ -} DWT_Type; - -/* DWT Control Register Definitions */ -#define DWT_CTRL_NUMCOMP_Pos 28U /*!< DWT CTRL: NUMCOMP Position */ -#define DWT_CTRL_NUMCOMP_Msk (0xFUL << DWT_CTRL_NUMCOMP_Pos) /*!< DWT CTRL: NUMCOMP Mask */ - -#define DWT_CTRL_NOTRCPKT_Pos 27U /*!< DWT CTRL: NOTRCPKT Position */ -#define DWT_CTRL_NOTRCPKT_Msk (0x1UL << DWT_CTRL_NOTRCPKT_Pos) /*!< DWT CTRL: NOTRCPKT Mask */ - -#define DWT_CTRL_NOEXTTRIG_Pos 26U /*!< DWT CTRL: NOEXTTRIG Position */ -#define DWT_CTRL_NOEXTTRIG_Msk (0x1UL << DWT_CTRL_NOEXTTRIG_Pos) /*!< DWT CTRL: NOEXTTRIG Mask */ - -#define DWT_CTRL_NOCYCCNT_Pos 25U /*!< DWT CTRL: NOCYCCNT Position */ -#define DWT_CTRL_NOCYCCNT_Msk (0x1UL << DWT_CTRL_NOCYCCNT_Pos) /*!< DWT CTRL: NOCYCCNT Mask */ - -#define DWT_CTRL_NOPRFCNT_Pos 24U /*!< DWT CTRL: NOPRFCNT Position */ -#define DWT_CTRL_NOPRFCNT_Msk (0x1UL << DWT_CTRL_NOPRFCNT_Pos) /*!< DWT CTRL: NOPRFCNT Mask */ - -#define DWT_CTRL_CYCEVTENA_Pos 22U /*!< DWT CTRL: CYCEVTENA Position */ -#define DWT_CTRL_CYCEVTENA_Msk (0x1UL << DWT_CTRL_CYCEVTENA_Pos) /*!< DWT CTRL: CYCEVTENA Mask */ - -#define DWT_CTRL_FOLDEVTENA_Pos 21U /*!< DWT CTRL: FOLDEVTENA Position */ -#define DWT_CTRL_FOLDEVTENA_Msk (0x1UL << DWT_CTRL_FOLDEVTENA_Pos) /*!< DWT CTRL: FOLDEVTENA Mask */ - -#define DWT_CTRL_LSUEVTENA_Pos 20U /*!< DWT CTRL: LSUEVTENA Position */ -#define DWT_CTRL_LSUEVTENA_Msk (0x1UL << DWT_CTRL_LSUEVTENA_Pos) /*!< DWT CTRL: LSUEVTENA Mask */ - -#define DWT_CTRL_SLEEPEVTENA_Pos 19U /*!< DWT CTRL: SLEEPEVTENA Position */ -#define DWT_CTRL_SLEEPEVTENA_Msk (0x1UL << DWT_CTRL_SLEEPEVTENA_Pos) /*!< DWT CTRL: SLEEPEVTENA Mask */ - -#define DWT_CTRL_EXCEVTENA_Pos 18U /*!< DWT CTRL: EXCEVTENA Position */ -#define DWT_CTRL_EXCEVTENA_Msk (0x1UL << DWT_CTRL_EXCEVTENA_Pos) /*!< DWT CTRL: EXCEVTENA Mask */ - -#define DWT_CTRL_CPIEVTENA_Pos 17U /*!< DWT CTRL: CPIEVTENA Position */ -#define DWT_CTRL_CPIEVTENA_Msk (0x1UL << DWT_CTRL_CPIEVTENA_Pos) /*!< DWT CTRL: CPIEVTENA Mask */ - -#define DWT_CTRL_EXCTRCENA_Pos 16U /*!< DWT CTRL: EXCTRCENA Position */ -#define DWT_CTRL_EXCTRCENA_Msk (0x1UL << DWT_CTRL_EXCTRCENA_Pos) /*!< DWT CTRL: EXCTRCENA Mask */ - -#define DWT_CTRL_PCSAMPLENA_Pos 12U /*!< DWT CTRL: PCSAMPLENA Position */ -#define DWT_CTRL_PCSAMPLENA_Msk (0x1UL << DWT_CTRL_PCSAMPLENA_Pos) /*!< DWT CTRL: PCSAMPLENA Mask */ - -#define DWT_CTRL_SYNCTAP_Pos 10U /*!< DWT CTRL: SYNCTAP Position */ -#define DWT_CTRL_SYNCTAP_Msk (0x3UL << DWT_CTRL_SYNCTAP_Pos) /*!< DWT CTRL: SYNCTAP Mask */ - -#define DWT_CTRL_CYCTAP_Pos 9U /*!< DWT CTRL: CYCTAP Position */ -#define DWT_CTRL_CYCTAP_Msk (0x1UL << DWT_CTRL_CYCTAP_Pos) /*!< DWT CTRL: CYCTAP Mask */ - -#define DWT_CTRL_POSTINIT_Pos 5U /*!< DWT CTRL: POSTINIT Position */ -#define DWT_CTRL_POSTINIT_Msk (0xFUL << DWT_CTRL_POSTINIT_Pos) /*!< DWT CTRL: POSTINIT Mask */ - -#define DWT_CTRL_POSTPRESET_Pos 1U /*!< DWT CTRL: POSTPRESET Position */ -#define DWT_CTRL_POSTPRESET_Msk (0xFUL << DWT_CTRL_POSTPRESET_Pos) /*!< DWT CTRL: POSTPRESET Mask */ - -#define DWT_CTRL_CYCCNTENA_Pos 0U /*!< DWT CTRL: CYCCNTENA Position */ -#define DWT_CTRL_CYCCNTENA_Msk (0x1UL /*<< DWT_CTRL_CYCCNTENA_Pos*/) /*!< DWT CTRL: CYCCNTENA Mask */ - -/* DWT CPI Count Register Definitions */ -#define DWT_CPICNT_CPICNT_Pos 0U /*!< DWT CPICNT: CPICNT Position */ -#define DWT_CPICNT_CPICNT_Msk (0xFFUL /*<< DWT_CPICNT_CPICNT_Pos*/) /*!< DWT CPICNT: CPICNT Mask */ - -/* DWT Exception Overhead Count Register Definitions */ -#define DWT_EXCCNT_EXCCNT_Pos 0U /*!< DWT EXCCNT: EXCCNT Position */ -#define DWT_EXCCNT_EXCCNT_Msk (0xFFUL /*<< DWT_EXCCNT_EXCCNT_Pos*/) /*!< DWT EXCCNT: EXCCNT Mask */ - -/* DWT Sleep Count Register Definitions */ -#define DWT_SLEEPCNT_SLEEPCNT_Pos 0U /*!< DWT SLEEPCNT: SLEEPCNT Position */ -#define DWT_SLEEPCNT_SLEEPCNT_Msk (0xFFUL /*<< DWT_SLEEPCNT_SLEEPCNT_Pos*/) /*!< DWT SLEEPCNT: SLEEPCNT Mask */ - -/* DWT LSU Count Register Definitions */ -#define DWT_LSUCNT_LSUCNT_Pos 0U /*!< DWT LSUCNT: LSUCNT Position */ -#define DWT_LSUCNT_LSUCNT_Msk (0xFFUL /*<< DWT_LSUCNT_LSUCNT_Pos*/) /*!< DWT LSUCNT: LSUCNT Mask */ - -/* DWT Folded-instruction Count Register Definitions */ -#define DWT_FOLDCNT_FOLDCNT_Pos 0U /*!< DWT FOLDCNT: FOLDCNT Position */ -#define DWT_FOLDCNT_FOLDCNT_Msk (0xFFUL /*<< DWT_FOLDCNT_FOLDCNT_Pos*/) /*!< DWT FOLDCNT: FOLDCNT Mask */ - -/* DWT Comparator Mask Register Definitions */ -#define DWT_MASK_MASK_Pos 0U /*!< DWT MASK: MASK Position */ -#define DWT_MASK_MASK_Msk (0x1FUL /*<< DWT_MASK_MASK_Pos*/) /*!< DWT MASK: MASK Mask */ - -/* DWT Comparator Function Register Definitions */ -#define DWT_FUNCTION_MATCHED_Pos 24U /*!< DWT FUNCTION: MATCHED Position */ -#define DWT_FUNCTION_MATCHED_Msk (0x1UL << DWT_FUNCTION_MATCHED_Pos) /*!< DWT FUNCTION: MATCHED Mask */ - -#define DWT_FUNCTION_DATAVADDR1_Pos 16U /*!< DWT FUNCTION: DATAVADDR1 Position */ -#define DWT_FUNCTION_DATAVADDR1_Msk (0xFUL << DWT_FUNCTION_DATAVADDR1_Pos) /*!< DWT FUNCTION: DATAVADDR1 Mask */ - -#define DWT_FUNCTION_DATAVADDR0_Pos 12U /*!< DWT FUNCTION: DATAVADDR0 Position */ -#define DWT_FUNCTION_DATAVADDR0_Msk (0xFUL << DWT_FUNCTION_DATAVADDR0_Pos) /*!< DWT FUNCTION: DATAVADDR0 Mask */ - -#define DWT_FUNCTION_DATAVSIZE_Pos 10U /*!< DWT FUNCTION: DATAVSIZE Position */ -#define DWT_FUNCTION_DATAVSIZE_Msk (0x3UL << DWT_FUNCTION_DATAVSIZE_Pos) /*!< DWT FUNCTION: DATAVSIZE Mask */ - -#define DWT_FUNCTION_LNK1ENA_Pos 9U /*!< DWT FUNCTION: LNK1ENA Position */ -#define DWT_FUNCTION_LNK1ENA_Msk (0x1UL << DWT_FUNCTION_LNK1ENA_Pos) /*!< DWT FUNCTION: LNK1ENA Mask */ - -#define DWT_FUNCTION_DATAVMATCH_Pos 8U /*!< DWT FUNCTION: DATAVMATCH Position */ -#define DWT_FUNCTION_DATAVMATCH_Msk (0x1UL << DWT_FUNCTION_DATAVMATCH_Pos) /*!< DWT FUNCTION: DATAVMATCH Mask */ - -#define DWT_FUNCTION_CYCMATCH_Pos 7U /*!< DWT FUNCTION: CYCMATCH Position */ -#define DWT_FUNCTION_CYCMATCH_Msk (0x1UL << DWT_FUNCTION_CYCMATCH_Pos) /*!< DWT FUNCTION: CYCMATCH Mask */ - -#define DWT_FUNCTION_EMITRANGE_Pos 5U /*!< DWT FUNCTION: EMITRANGE Position */ -#define DWT_FUNCTION_EMITRANGE_Msk (0x1UL << DWT_FUNCTION_EMITRANGE_Pos) /*!< DWT FUNCTION: EMITRANGE Mask */ - -#define DWT_FUNCTION_FUNCTION_Pos 0U /*!< DWT FUNCTION: FUNCTION Position */ -#define DWT_FUNCTION_FUNCTION_Msk (0xFUL /*<< DWT_FUNCTION_FUNCTION_Pos*/) /*!< DWT FUNCTION: FUNCTION Mask */ - -/*@}*/ /* end of group CMSIS_DWT */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_TPI Trace Port Interface (TPI) - \brief Type definitions for the Trace Port Interface (TPI) - @{ - */ - -/** - \brief Structure type to access the Trace Port Interface Register (TPI). - */ -typedef struct -{ - __IM uint32_t SSPSR; /*!< Offset: 0x000 (R/ ) Supported Parallel Port Size Register */ - __IOM uint32_t CSPSR; /*!< Offset: 0x004 (R/W) Current Parallel Port Size Register */ - uint32_t RESERVED0[2U]; - __IOM uint32_t ACPR; /*!< Offset: 0x010 (R/W) Asynchronous Clock Prescaler Register */ - uint32_t RESERVED1[55U]; - __IOM uint32_t SPPR; /*!< Offset: 0x0F0 (R/W) Selected Pin Protocol Register */ - uint32_t RESERVED2[131U]; - __IM uint32_t FFSR; /*!< Offset: 0x300 (R/ ) Formatter and Flush Status Register */ - __IOM uint32_t FFCR; /*!< Offset: 0x304 (R/W) Formatter and Flush Control Register */ - __IM uint32_t FSCR; /*!< Offset: 0x308 (R/ ) Formatter Synchronization Counter Register */ - uint32_t RESERVED3[759U]; - __IM uint32_t TRIGGER; /*!< Offset: 0xEE8 (R/ ) TRIGGER Register */ - __IM uint32_t FIFO0; /*!< Offset: 0xEEC (R/ ) Integration ETM Data */ - __IM uint32_t ITATBCTR2; /*!< Offset: 0xEF0 (R/ ) ITATBCTR2 */ - uint32_t RESERVED4[1U]; - __IM uint32_t ITATBCTR0; /*!< Offset: 0xEF8 (R/ ) ITATBCTR0 */ - __IM uint32_t FIFO1; /*!< Offset: 0xEFC (R/ ) Integration ITM Data */ - __IOM uint32_t ITCTRL; /*!< Offset: 0xF00 (R/W) Integration Mode Control */ - uint32_t RESERVED5[39U]; - __IOM uint32_t CLAIMSET; /*!< Offset: 0xFA0 (R/W) Claim tag set */ - __IOM uint32_t CLAIMCLR; /*!< Offset: 0xFA4 (R/W) Claim tag clear */ - uint32_t RESERVED7[8U]; - __IM uint32_t DEVID; /*!< Offset: 0xFC8 (R/ ) TPIU_DEVID */ - __IM uint32_t DEVTYPE; /*!< Offset: 0xFCC (R/ ) TPIU_DEVTYPE */ -} TPI_Type; - -/* TPI Asynchronous Clock Prescaler Register Definitions */ -#define TPI_ACPR_PRESCALER_Pos 0U /*!< TPI ACPR: PRESCALER Position */ -#define TPI_ACPR_PRESCALER_Msk (0x1FFFUL /*<< TPI_ACPR_PRESCALER_Pos*/) /*!< TPI ACPR: PRESCALER Mask */ - -/* TPI Selected Pin Protocol Register Definitions */ -#define TPI_SPPR_TXMODE_Pos 0U /*!< TPI SPPR: TXMODE Position */ -#define TPI_SPPR_TXMODE_Msk (0x3UL /*<< TPI_SPPR_TXMODE_Pos*/) /*!< TPI SPPR: TXMODE Mask */ - -/* TPI Formatter and Flush Status Register Definitions */ -#define TPI_FFSR_FtNonStop_Pos 3U /*!< TPI FFSR: FtNonStop Position */ -#define TPI_FFSR_FtNonStop_Msk (0x1UL << TPI_FFSR_FtNonStop_Pos) /*!< TPI FFSR: FtNonStop Mask */ - -#define TPI_FFSR_TCPresent_Pos 2U /*!< TPI FFSR: TCPresent Position */ -#define TPI_FFSR_TCPresent_Msk (0x1UL << TPI_FFSR_TCPresent_Pos) /*!< TPI FFSR: TCPresent Mask */ - -#define TPI_FFSR_FtStopped_Pos 1U /*!< TPI FFSR: FtStopped Position */ -#define TPI_FFSR_FtStopped_Msk (0x1UL << TPI_FFSR_FtStopped_Pos) /*!< TPI FFSR: FtStopped Mask */ - -#define TPI_FFSR_FlInProg_Pos 0U /*!< TPI FFSR: FlInProg Position */ -#define TPI_FFSR_FlInProg_Msk (0x1UL /*<< TPI_FFSR_FlInProg_Pos*/) /*!< TPI FFSR: FlInProg Mask */ - -/* TPI Formatter and Flush Control Register Definitions */ -#define TPI_FFCR_TrigIn_Pos 8U /*!< TPI FFCR: TrigIn Position */ -#define TPI_FFCR_TrigIn_Msk (0x1UL << TPI_FFCR_TrigIn_Pos) /*!< TPI FFCR: TrigIn Mask */ - -#define TPI_FFCR_EnFCont_Pos 1U /*!< TPI FFCR: EnFCont Position */ -#define TPI_FFCR_EnFCont_Msk (0x1UL << TPI_FFCR_EnFCont_Pos) /*!< TPI FFCR: EnFCont Mask */ - -/* TPI TRIGGER Register Definitions */ -#define TPI_TRIGGER_TRIGGER_Pos 0U /*!< TPI TRIGGER: TRIGGER Position */ -#define TPI_TRIGGER_TRIGGER_Msk (0x1UL /*<< TPI_TRIGGER_TRIGGER_Pos*/) /*!< TPI TRIGGER: TRIGGER Mask */ - -/* TPI Integration ETM Data Register Definitions (FIFO0) */ -#define TPI_FIFO0_ITM_ATVALID_Pos 29U /*!< TPI FIFO0: ITM_ATVALID Position */ -#define TPI_FIFO0_ITM_ATVALID_Msk (0x1UL << TPI_FIFO0_ITM_ATVALID_Pos) /*!< TPI FIFO0: ITM_ATVALID Mask */ - -#define TPI_FIFO0_ITM_bytecount_Pos 27U /*!< TPI FIFO0: ITM_bytecount Position */ -#define TPI_FIFO0_ITM_bytecount_Msk (0x3UL << TPI_FIFO0_ITM_bytecount_Pos) /*!< TPI FIFO0: ITM_bytecount Mask */ - -#define TPI_FIFO0_ETM_ATVALID_Pos 26U /*!< TPI FIFO0: ETM_ATVALID Position */ -#define TPI_FIFO0_ETM_ATVALID_Msk (0x1UL << TPI_FIFO0_ETM_ATVALID_Pos) /*!< TPI FIFO0: ETM_ATVALID Mask */ - -#define TPI_FIFO0_ETM_bytecount_Pos 24U /*!< TPI FIFO0: ETM_bytecount Position */ -#define TPI_FIFO0_ETM_bytecount_Msk (0x3UL << TPI_FIFO0_ETM_bytecount_Pos) /*!< TPI FIFO0: ETM_bytecount Mask */ - -#define TPI_FIFO0_ETM2_Pos 16U /*!< TPI FIFO0: ETM2 Position */ -#define TPI_FIFO0_ETM2_Msk (0xFFUL << TPI_FIFO0_ETM2_Pos) /*!< TPI FIFO0: ETM2 Mask */ - -#define TPI_FIFO0_ETM1_Pos 8U /*!< TPI FIFO0: ETM1 Position */ -#define TPI_FIFO0_ETM1_Msk (0xFFUL << TPI_FIFO0_ETM1_Pos) /*!< TPI FIFO0: ETM1 Mask */ - -#define TPI_FIFO0_ETM0_Pos 0U /*!< TPI FIFO0: ETM0 Position */ -#define TPI_FIFO0_ETM0_Msk (0xFFUL /*<< TPI_FIFO0_ETM0_Pos*/) /*!< TPI FIFO0: ETM0 Mask */ - -/* TPI ITATBCTR2 Register Definitions */ -#define TPI_ITATBCTR2_ATREADY2_Pos 0U /*!< TPI ITATBCTR2: ATREADY2 Position */ -#define TPI_ITATBCTR2_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY2_Pos*/) /*!< TPI ITATBCTR2: ATREADY2 Mask */ - -#define TPI_ITATBCTR2_ATREADY1_Pos 0U /*!< TPI ITATBCTR2: ATREADY1 Position */ -#define TPI_ITATBCTR2_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR2_ATREADY1_Pos*/) /*!< TPI ITATBCTR2: ATREADY1 Mask */ - -/* TPI Integration ITM Data Register Definitions (FIFO1) */ -#define TPI_FIFO1_ITM_ATVALID_Pos 29U /*!< TPI FIFO1: ITM_ATVALID Position */ -#define TPI_FIFO1_ITM_ATVALID_Msk (0x1UL << TPI_FIFO1_ITM_ATVALID_Pos) /*!< TPI FIFO1: ITM_ATVALID Mask */ - -#define TPI_FIFO1_ITM_bytecount_Pos 27U /*!< TPI FIFO1: ITM_bytecount Position */ -#define TPI_FIFO1_ITM_bytecount_Msk (0x3UL << TPI_FIFO1_ITM_bytecount_Pos) /*!< TPI FIFO1: ITM_bytecount Mask */ - -#define TPI_FIFO1_ETM_ATVALID_Pos 26U /*!< TPI FIFO1: ETM_ATVALID Position */ -#define TPI_FIFO1_ETM_ATVALID_Msk (0x1UL << TPI_FIFO1_ETM_ATVALID_Pos) /*!< TPI FIFO1: ETM_ATVALID Mask */ - -#define TPI_FIFO1_ETM_bytecount_Pos 24U /*!< TPI FIFO1: ETM_bytecount Position */ -#define TPI_FIFO1_ETM_bytecount_Msk (0x3UL << TPI_FIFO1_ETM_bytecount_Pos) /*!< TPI FIFO1: ETM_bytecount Mask */ - -#define TPI_FIFO1_ITM2_Pos 16U /*!< TPI FIFO1: ITM2 Position */ -#define TPI_FIFO1_ITM2_Msk (0xFFUL << TPI_FIFO1_ITM2_Pos) /*!< TPI FIFO1: ITM2 Mask */ - -#define TPI_FIFO1_ITM1_Pos 8U /*!< TPI FIFO1: ITM1 Position */ -#define TPI_FIFO1_ITM1_Msk (0xFFUL << TPI_FIFO1_ITM1_Pos) /*!< TPI FIFO1: ITM1 Mask */ - -#define TPI_FIFO1_ITM0_Pos 0U /*!< TPI FIFO1: ITM0 Position */ -#define TPI_FIFO1_ITM0_Msk (0xFFUL /*<< TPI_FIFO1_ITM0_Pos*/) /*!< TPI FIFO1: ITM0 Mask */ - -/* TPI ITATBCTR0 Register Definitions */ -#define TPI_ITATBCTR0_ATREADY2_Pos 0U /*!< TPI ITATBCTR0: ATREADY2 Position */ -#define TPI_ITATBCTR0_ATREADY2_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY2_Pos*/) /*!< TPI ITATBCTR0: ATREADY2 Mask */ - -#define TPI_ITATBCTR0_ATREADY1_Pos 0U /*!< TPI ITATBCTR0: ATREADY1 Position */ -#define TPI_ITATBCTR0_ATREADY1_Msk (0x1UL /*<< TPI_ITATBCTR0_ATREADY1_Pos*/) /*!< TPI ITATBCTR0: ATREADY1 Mask */ - -/* TPI Integration Mode Control Register Definitions */ -#define TPI_ITCTRL_Mode_Pos 0U /*!< TPI ITCTRL: Mode Position */ -#define TPI_ITCTRL_Mode_Msk (0x3UL /*<< TPI_ITCTRL_Mode_Pos*/) /*!< TPI ITCTRL: Mode Mask */ - -/* TPI DEVID Register Definitions */ -#define TPI_DEVID_NRZVALID_Pos 11U /*!< TPI DEVID: NRZVALID Position */ -#define TPI_DEVID_NRZVALID_Msk (0x1UL << TPI_DEVID_NRZVALID_Pos) /*!< TPI DEVID: NRZVALID Mask */ - -#define TPI_DEVID_MANCVALID_Pos 10U /*!< TPI DEVID: MANCVALID Position */ -#define TPI_DEVID_MANCVALID_Msk (0x1UL << TPI_DEVID_MANCVALID_Pos) /*!< TPI DEVID: MANCVALID Mask */ - -#define TPI_DEVID_PTINVALID_Pos 9U /*!< TPI DEVID: PTINVALID Position */ -#define TPI_DEVID_PTINVALID_Msk (0x1UL << TPI_DEVID_PTINVALID_Pos) /*!< TPI DEVID: PTINVALID Mask */ - -#define TPI_DEVID_MinBufSz_Pos 6U /*!< TPI DEVID: MinBufSz Position */ -#define TPI_DEVID_MinBufSz_Msk (0x7UL << TPI_DEVID_MinBufSz_Pos) /*!< TPI DEVID: MinBufSz Mask */ - -#define TPI_DEVID_AsynClkIn_Pos 5U /*!< TPI DEVID: AsynClkIn Position */ -#define TPI_DEVID_AsynClkIn_Msk (0x1UL << TPI_DEVID_AsynClkIn_Pos) /*!< TPI DEVID: AsynClkIn Mask */ - -#define TPI_DEVID_NrTraceInput_Pos 0U /*!< TPI DEVID: NrTraceInput Position */ -#define TPI_DEVID_NrTraceInput_Msk (0x1FUL /*<< TPI_DEVID_NrTraceInput_Pos*/) /*!< TPI DEVID: NrTraceInput Mask */ - -/* TPI DEVTYPE Register Definitions */ -#define TPI_DEVTYPE_SubType_Pos 4U /*!< TPI DEVTYPE: SubType Position */ -#define TPI_DEVTYPE_SubType_Msk (0xFUL /*<< TPI_DEVTYPE_SubType_Pos*/) /*!< TPI DEVTYPE: SubType Mask */ - -#define TPI_DEVTYPE_MajorType_Pos 0U /*!< TPI DEVTYPE: MajorType Position */ -#define TPI_DEVTYPE_MajorType_Msk (0xFUL << TPI_DEVTYPE_MajorType_Pos) /*!< TPI DEVTYPE: MajorType Mask */ - -/*@}*/ /* end of group CMSIS_TPI */ - - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_MPU Memory Protection Unit (MPU) - \brief Type definitions for the Memory Protection Unit (MPU) - @{ - */ - -/** - \brief Structure type to access the Memory Protection Unit (MPU). - */ -typedef struct -{ - __IM uint32_t TYPE; /*!< Offset: 0x000 (R/ ) MPU Type Register */ - __IOM uint32_t CTRL; /*!< Offset: 0x004 (R/W) MPU Control Register */ - __IOM uint32_t RNR; /*!< Offset: 0x008 (R/W) MPU Region RNRber Register */ - __IOM uint32_t RBAR; /*!< Offset: 0x00C (R/W) MPU Region Base Address Register */ - __IOM uint32_t RASR; /*!< Offset: 0x010 (R/W) MPU Region Attribute and Size Register */ - __IOM uint32_t RBAR_A1; /*!< Offset: 0x014 (R/W) MPU Alias 1 Region Base Address Register */ - __IOM uint32_t RASR_A1; /*!< Offset: 0x018 (R/W) MPU Alias 1 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A2; /*!< Offset: 0x01C (R/W) MPU Alias 2 Region Base Address Register */ - __IOM uint32_t RASR_A2; /*!< Offset: 0x020 (R/W) MPU Alias 2 Region Attribute and Size Register */ - __IOM uint32_t RBAR_A3; /*!< Offset: 0x024 (R/W) MPU Alias 3 Region Base Address Register */ - __IOM uint32_t RASR_A3; /*!< Offset: 0x028 (R/W) MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -#define MPU_TYPE_RALIASES 4U - -/* MPU Type Register Definitions */ -#define MPU_TYPE_IREGION_Pos 16U /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFUL << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8U /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFUL << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0U /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1UL /*<< MPU_TYPE_SEPARATE_Pos*/) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register Definitions */ -#define MPU_CTRL_PRIVDEFENA_Pos 2U /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1UL << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1U /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1UL << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0U /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1UL /*<< MPU_CTRL_ENABLE_Pos*/) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register Definitions */ -#define MPU_RNR_REGION_Pos 0U /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFUL /*<< MPU_RNR_REGION_Pos*/) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register Definitions */ -#define MPU_RBAR_ADDR_Pos 5U /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFUL << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4U /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1UL << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0U /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register Definitions */ -#define MPU_RASR_ATTRS_Pos 16U /*!< MPU RASR: MPU Region Attribute field Position */ -#define MPU_RASR_ATTRS_Msk (0xFFFFUL << MPU_RASR_ATTRS_Pos) /*!< MPU RASR: MPU Region Attribute field Mask */ - -#define MPU_RASR_XN_Pos 28U /*!< MPU RASR: ATTRS.XN Position */ -#define MPU_RASR_XN_Msk (1UL << MPU_RASR_XN_Pos) /*!< MPU RASR: ATTRS.XN Mask */ - -#define MPU_RASR_AP_Pos 24U /*!< MPU RASR: ATTRS.AP Position */ -#define MPU_RASR_AP_Msk (0x7UL << MPU_RASR_AP_Pos) /*!< MPU RASR: ATTRS.AP Mask */ - -#define MPU_RASR_TEX_Pos 19U /*!< MPU RASR: ATTRS.TEX Position */ -#define MPU_RASR_TEX_Msk (0x7UL << MPU_RASR_TEX_Pos) /*!< MPU RASR: ATTRS.TEX Mask */ - -#define MPU_RASR_S_Pos 18U /*!< MPU RASR: ATTRS.S Position */ -#define MPU_RASR_S_Msk (1UL << MPU_RASR_S_Pos) /*!< MPU RASR: ATTRS.S Mask */ - -#define MPU_RASR_C_Pos 17U /*!< MPU RASR: ATTRS.C Position */ -#define MPU_RASR_C_Msk (1UL << MPU_RASR_C_Pos) /*!< MPU RASR: ATTRS.C Mask */ - -#define MPU_RASR_B_Pos 16U /*!< MPU RASR: ATTRS.B Position */ -#define MPU_RASR_B_Msk (1UL << MPU_RASR_B_Pos) /*!< MPU RASR: ATTRS.B Mask */ - -#define MPU_RASR_SRD_Pos 8U /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFUL << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1U /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1FUL << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENABLE_Pos 0U /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENABLE_Msk (1UL /*<< MPU_RASR_ENABLE_Pos*/) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@} end of group CMSIS_MPU */ -#endif - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_CoreDebug Core Debug Registers (CoreDebug) - \brief Type definitions for the Core Debug Registers - @{ - */ - -/** - \brief Structure type to access the Core Debug Register (CoreDebug). - */ -typedef struct -{ - __IOM uint32_t DHCSR; /*!< Offset: 0x000 (R/W) Debug Halting Control and Status Register */ - __OM uint32_t DCRSR; /*!< Offset: 0x004 ( /W) Debug Core Register Selector Register */ - __IOM uint32_t DCRDR; /*!< Offset: 0x008 (R/W) Debug Core Register Data Register */ - __IOM uint32_t DEMCR; /*!< Offset: 0x00C (R/W) Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register Definitions */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16U /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFUL << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25U /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1UL << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24U /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1UL << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19U /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1UL << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18U /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1UL << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17U /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1UL << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16U /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1UL << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5U /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1UL << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3U /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1UL << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2U /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1UL << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1U /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1UL << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0U /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1UL /*<< CoreDebug_DHCSR_C_DEBUGEN_Pos*/) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register Definitions */ -#define CoreDebug_DCRSR_REGWnR_Pos 16U /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1UL << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0U /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1FUL /*<< CoreDebug_DCRSR_REGSEL_Pos*/) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register Definitions */ -#define CoreDebug_DEMCR_TRCENA_Pos 24U /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1UL << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19U /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1UL << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18U /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1UL << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17U /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1UL << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16U /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1UL << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10U /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1UL << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9U /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1UL << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8U /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1UL << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7U /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1UL << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6U /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1UL << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5U /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1UL << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4U /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1UL << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0U /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1UL /*<< CoreDebug_DEMCR_VC_CORERESET_Pos*/) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ - -/*@} end of group CMSIS_CoreDebug */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_core_bitfield Core register bit field macros - \brief Macros for use with bit field definitions (xxx_Pos, xxx_Msk). - @{ - */ - -/** - \brief Mask and shift a bit field value for use in a register bit range. - \param[in] field Name of the register bit field. - \param[in] value Value of the bit field. This parameter is interpreted as an uint32_t type. - \return Masked and shifted value. -*/ -#define _VAL2FLD(field, value) (((uint32_t)(value) << field ## _Pos) & field ## _Msk) - -/** - \brief Mask and shift a register value to extract a bit filed value. - \param[in] field Name of the register bit field. - \param[in] value Value of register. This parameter is interpreted as an uint32_t type. - \return Masked and shifted bit field value. -*/ -#define _FLD2VAL(field, value) (((uint32_t)(value) & field ## _Msk) >> field ## _Pos) - -/*@} end of group CMSIS_core_bitfield */ - - -/** - \ingroup CMSIS_core_register - \defgroup CMSIS_core_base Core Definitions - \brief Definitions for base addresses, unions, and structures. - @{ - */ - -/* Memory mapping of Core Hardware */ -#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000UL) /*!< ITM Base Address */ -#define DWT_BASE (0xE0001000UL) /*!< DWT Base Address */ -#define TPI_BASE (0xE0040000UL) /*!< TPI Base Address */ -#define CoreDebug_BASE (0xE000EDF0UL) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100UL) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00UL) /*!< System Control Block Base Address */ - -#define SCnSCB ((SCnSCB_Type *) SCS_BASE ) /*!< System control Register not in SCB */ -#define SCB ((SCB_Type *) SCB_BASE ) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE ) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE ) /*!< ITM configuration struct */ -#define DWT ((DWT_Type *) DWT_BASE ) /*!< DWT configuration struct */ -#define TPI ((TPI_Type *) TPI_BASE ) /*!< TPI configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - #define MPU_BASE (SCS_BASE + 0x0D90UL) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type *) MPU_BASE ) /*!< Memory Protection Unit */ -#endif - -/*@} */ - - - -/******************************************************************************* - * Hardware Abstraction Layer - Core Function Interface contains: - - Core NVIC Functions - - Core SysTick Functions - - Core Debug Functions - - Core Register Access Functions - ******************************************************************************/ -/** - \defgroup CMSIS_Core_FunctionInterface Functions and Instructions Reference -*/ - - - -/* ########################## NVIC functions #################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_NVICFunctions NVIC Functions - \brief Functions that manage interrupts and exceptions via the NVIC. - @{ - */ - -#ifdef CMSIS_NVIC_VIRTUAL - #ifndef CMSIS_NVIC_VIRTUAL_HEADER_FILE - #define CMSIS_NVIC_VIRTUAL_HEADER_FILE "cmsis_nvic_virtual.h" - #endif - #include CMSIS_NVIC_VIRTUAL_HEADER_FILE -#else - #define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping - #define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping - #define NVIC_EnableIRQ __NVIC_EnableIRQ - #define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ - #define NVIC_DisableIRQ __NVIC_DisableIRQ - #define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ - #define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ - #define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ - #define NVIC_GetActive __NVIC_GetActive - #define NVIC_SetPriority __NVIC_SetPriority - #define NVIC_GetPriority __NVIC_GetPriority - #define NVIC_SystemReset __NVIC_SystemReset -#endif /* CMSIS_NVIC_VIRTUAL */ - -#ifdef CMSIS_VECTAB_VIRTUAL - #ifndef CMSIS_VECTAB_VIRTUAL_HEADER_FILE - #define CMSIS_VECTAB_VIRTUAL_HEADER_FILE "cmsis_vectab_virtual.h" - #endif - #include CMSIS_VECTAB_VIRTUAL_HEADER_FILE -#else - #define NVIC_SetVector __NVIC_SetVector - #define NVIC_GetVector __NVIC_GetVector -#endif /* (CMSIS_VECTAB_VIRTUAL) */ - -#define NVIC_USER_IRQ_OFFSET 16 - - -/* The following EXC_RETURN values are saved the LR on exception entry */ -#define EXC_RETURN_HANDLER (0xFFFFFFF1UL) /* return to Handler mode, uses MSP after return */ -#define EXC_RETURN_THREAD_MSP (0xFFFFFFF9UL) /* return to Thread mode, uses MSP after return */ -#define EXC_RETURN_THREAD_PSP (0xFFFFFFFDUL) /* return to Thread mode, uses PSP after return */ - - -/** - \brief Set Priority Grouping - \details Sets the priority grouping field using the required unlock sequence. - The parameter PriorityGroup is assigned to the field SCB->AIRCR [10:8] PRIGROUP field. - Only values from 0..7 are used. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - \param [in] PriorityGroup Priority grouping field. - */ -__STATIC_INLINE void __NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ - reg_value = (reg_value | - ((uint32_t)0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << SCB_AIRCR_PRIGROUP_Pos) ); /* Insert write key and priority group */ - SCB->AIRCR = reg_value; -} - - -/** - \brief Get Priority Grouping - \details Reads the priority grouping field from the NVIC Interrupt Controller. - \return Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field). - */ -__STATIC_INLINE uint32_t __NVIC_GetPriorityGrouping(void) -{ - return ((uint32_t)((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos)); -} - - -/** - \brief Enable Interrupt - \details Enables a device specific interrupt in the NVIC interrupt controller. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_EnableIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - __COMPILER_BARRIER(); - NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - __COMPILER_BARRIER(); - } -} - - -/** - \brief Get Interrupt Enable status - \details Returns a device specific interrupt enable status from the NVIC interrupt controller. - \param [in] IRQn Device specific interrupt number. - \return 0 Interrupt is not enabled. - \return 1 Interrupt is enabled. - \note IRQn must not be negative. - */ -__STATIC_INLINE uint32_t __NVIC_GetEnableIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISER[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } -} - - -/** - \brief Disable Interrupt - \details Disables a device specific interrupt in the NVIC interrupt controller. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_DisableIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - __DSB(); - __ISB(); - } -} - - -/** - \brief Get Pending Interrupt - \details Reads the NVIC pending register and returns the pending bit for the specified device specific interrupt. - \param [in] IRQn Device specific interrupt number. - \return 0 Interrupt status is not pending. - \return 1 Interrupt status is pending. - \note IRQn must not be negative. - */ -__STATIC_INLINE uint32_t __NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } -} - - -/** - \brief Set Pending Interrupt - \details Sets the pending bit of a device specific interrupt in the NVIC pending register. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ISPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - } -} - - -/** - \brief Clear Pending Interrupt - \details Clears the pending bit of a device specific interrupt in the NVIC pending register. - \param [in] IRQn Device specific interrupt number. - \note IRQn must not be negative. - */ -__STATIC_INLINE void __NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); - } -} - - -/** - \brief Get Active Interrupt - \details Reads the active register in the NVIC and returns the active bit for the device specific interrupt. - \param [in] IRQn Device specific interrupt number. - \return 0 Interrupt status is not active. - \return 1 Interrupt status is active. - \note IRQn must not be negative. - */ -__STATIC_INLINE uint32_t __NVIC_GetActive(IRQn_Type IRQn) -{ - if ((int32_t)(IRQn) >= 0) - { - return((uint32_t)(((NVIC->IABR[(((uint32_t)IRQn) >> 5UL)] & (1UL << (((uint32_t)IRQn) & 0x1FUL))) != 0UL) ? 1UL : 0UL)); - } - else - { - return(0U); - } -} - - -/** - \brief Set Interrupt Priority - \details Sets the priority of a device specific interrupt or a processor exception. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - \param [in] IRQn Interrupt number. - \param [in] priority Priority to set. - \note The priority cannot be set for every processor exception. - */ -__STATIC_INLINE void __NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if ((int32_t)(IRQn) >= 0) - { - NVIC->IP[((uint32_t)IRQn)] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } - else - { - SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); - } -} - - -/** - \brief Get Interrupt Priority - \details Reads the priority of a device specific interrupt or a processor exception. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - \param [in] IRQn Interrupt number. - \return Interrupt Priority. - Value is aligned automatically to the implemented priority bits of the microcontroller. - */ -__STATIC_INLINE uint32_t __NVIC_GetPriority(IRQn_Type IRQn) -{ - - if ((int32_t)(IRQn) >= 0) - { - return(((uint32_t)NVIC->IP[((uint32_t)IRQn)] >> (8U - __NVIC_PRIO_BITS))); - } - else - { - return(((uint32_t)SCB->SHP[(((uint32_t)IRQn) & 0xFUL)-4UL] >> (8U - __NVIC_PRIO_BITS))); - } -} - - -/** - \brief Encode Priority - \details Encodes the priority for an interrupt with the given priority group, - preemptive priority value, and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS), the smallest possible priority group is set. - \param [in] PriorityGroup Used priority group. - \param [in] PreemptPriority Preemptive priority value (starting from 0). - \param [in] SubPriority Subpriority value (starting from 0). - \return Encoded priority. Value can be used in the function \ref NVIC_SetPriority(). - */ -__STATIC_INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - - return ( - ((PreemptPriority & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL)) << SubPriorityBits) | - ((SubPriority & (uint32_t)((1UL << (SubPriorityBits )) - 1UL))) - ); -} - - -/** - \brief Decode Priority - \details Decodes an interrupt priority value with a given priority group to - preemptive priority value and subpriority value. - In case of a conflict between priority grouping and available - priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. - \param [in] Priority Priority value, which can be retrieved with the function \ref NVIC_GetPriority(). - \param [in] PriorityGroup Used priority group. - \param [out] pPreemptPriority Preemptive priority value (starting from 0). - \param [out] pSubPriority Subpriority value (starting from 0). - */ -__STATIC_INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* const pPreemptPriority, uint32_t* const pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & (uint32_t)0x07UL); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7UL - PriorityGroupTmp) > (uint32_t)(__NVIC_PRIO_BITS)) ? (uint32_t)(__NVIC_PRIO_BITS) : (uint32_t)(7UL - PriorityGroupTmp); - SubPriorityBits = ((PriorityGroupTmp + (uint32_t)(__NVIC_PRIO_BITS)) < (uint32_t)7UL) ? (uint32_t)0UL : (uint32_t)((PriorityGroupTmp - 7UL) + (uint32_t)(__NVIC_PRIO_BITS)); - - *pPreemptPriority = (Priority >> SubPriorityBits) & (uint32_t)((1UL << (PreemptPriorityBits)) - 1UL); - *pSubPriority = (Priority ) & (uint32_t)((1UL << (SubPriorityBits )) - 1UL); -} - - -/** - \brief Set Interrupt Vector - \details Sets an interrupt vector in SRAM based interrupt vector table. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - VTOR must been relocated to SRAM before. - \param [in] IRQn Interrupt number - \param [in] vector Address of interrupt handler function - */ -__STATIC_INLINE void __NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) -{ - uint32_t *vectors = (uint32_t *)SCB->VTOR; - vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET] = vector; - /* ARM Application Note 321 states that the M3 does not require the architectural barrier */ -} - - -/** - \brief Get Interrupt Vector - \details Reads an interrupt vector from interrupt vector table. - The interrupt number can be positive to specify a device specific interrupt, - or negative to specify a processor exception. - \param [in] IRQn Interrupt number. - \return Address of interrupt handler function - */ -__STATIC_INLINE uint32_t __NVIC_GetVector(IRQn_Type IRQn) -{ - uint32_t *vectors = (uint32_t *)SCB->VTOR; - return vectors[(int32_t)IRQn + NVIC_USER_IRQ_OFFSET]; -} - - -/** - \brief System Reset - \details Initiates a system reset request to reset the MCU. - */ -__NO_RETURN __STATIC_INLINE void __NVIC_SystemReset(void) -{ - __DSB(); /* Ensure all outstanding memory accesses included - buffered write are completed before reset */ - SCB->AIRCR = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk ); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ - - for(;;) /* wait until reset */ - { - __NOP(); - } -} - -/*@} end of CMSIS_Core_NVICFunctions */ - - -/* ########################## MPU functions #################################### */ - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) - -#include "mpu_armv7.h" - -#endif - - -/* ########################## FPU functions #################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_FpuFunctions FPU Functions - \brief Function that provides FPU type. - @{ - */ - -/** - \brief get FPU type - \details returns the FPU type - \returns - - \b 0: No FPU - - \b 1: Single precision FPU - - \b 2: Double + Single precision FPU - */ -__STATIC_INLINE uint32_t SCB_GetFPUType(void) -{ - return 0U; /* No FPU */ -} - - -/*@} end of CMSIS_Core_FpuFunctions */ - - - -/* ################################## SysTick function ############################################ */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_Core_SysTickFunctions SysTick Functions - \brief Functions that configure the System. - @{ - */ - -#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U) - -/** - \brief System Tick Configuration - \details Initializes the System Timer and its interrupt, and starts the System Tick Timer. - Counter is in free running mode to generate periodic interrupts. - \param [in] ticks Number of ticks between two interrupts. - \return 0 Function succeeded. - \return 1 Function failed. - \note When the variable __Vendor_SysTickConfig is set to 1, then the - function SysTick_Config is not included. In this case, the file device.h - must contain a vendor-specific implementation of this function. - */ -__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) - { - return (1UL); /* Reload value impossible */ - } - - SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */ - SysTick->VAL = 0UL; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0UL); /* Function successful */ -} - -#endif - -/*@} end of CMSIS_Core_SysTickFunctions */ - - - -/* ##################################### Debug In/Output function ########################################### */ -/** - \ingroup CMSIS_Core_FunctionInterface - \defgroup CMSIS_core_DebugFunctions ITM Functions - \brief Functions that access the ITM debug interface. - @{ - */ - -extern volatile int32_t ITM_RxBuffer; /*!< External variable to receive characters. */ -#define ITM_RXBUFFER_EMPTY ((int32_t)0x5AA55AA5U) /*!< Value identifying \ref ITM_RxBuffer is ready for next character. */ - - -/** - \brief ITM Send Character - \details Transmits a character via the ITM channel 0, and - \li Just returns when no debugger is connected that has booked the output. - \li Is blocking when a debugger is connected, but the previous character sent has not been transmitted. - \param [in] ch Character to transmit. - \returns Character to transmit. - */ -__STATIC_INLINE uint32_t ITM_SendChar (uint32_t ch) -{ - if (((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0UL) && /* ITM enabled */ - ((ITM->TER & 1UL ) != 0UL) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0U].u32 == 0UL) - { - __NOP(); - } - ITM->PORT[0U].u8 = (uint8_t)ch; - } - return (ch); -} - - -/** - \brief ITM Receive Character - \details Inputs a character via the external variable \ref ITM_RxBuffer. - \return Received character. - \return -1 No character pending. - */ -__STATIC_INLINE int32_t ITM_ReceiveChar (void) -{ - int32_t ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) - { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** - \brief ITM Check Character - \details Checks whether a character is pending for reading in the variable \ref ITM_RxBuffer. - \return 0 No character available. - \return 1 Character available. - */ -__STATIC_INLINE int32_t ITM_CheckChar (void) -{ - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) - { - return (0); /* no character available */ - } - else - { - return (1); /* character available */ - } -} - -/*@} end of CMSIS_core_DebugFunctions */ - - - - -#ifdef __cplusplus -} -#endif - -#endif /* __CORE_CM3_H_DEPENDANT */ - -#endif /* __CMSIS_GENERIC */ diff --git a/tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h b/tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h deleted file mode 100644 index d9eedf81a..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/mpu_armv7.h +++ /dev/null @@ -1,275 +0,0 @@ -/****************************************************************************** - * @file mpu_armv7.h - * @brief CMSIS MPU API for Armv7-M MPU - * @version V5.1.2 - * @date 25. May 2020 - ******************************************************************************/ -/* - * Copyright (c) 2017-2020 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if defined ( __ICCARM__ ) - #pragma system_include /* treat file as system include file for MISRA check */ -#elif defined (__clang__) - #pragma clang system_header /* treat file as system include file */ -#endif - -#ifndef ARM_MPU_ARMV7_H -#define ARM_MPU_ARMV7_H - -#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes -#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes -#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes -#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes -#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes -#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte -#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes -#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes -#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes -#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes -#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes -#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes -#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes -#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes -#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes -#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte -#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes -#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes -#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes -#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes -#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes -#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes -#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes -#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes -#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes -#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte -#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes -#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes - -#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access -#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only -#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only -#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access -#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only -#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access - -/** MPU Region Base Address Register Value -* -* \param Region The region to be configured, number 0 to 15. -* \param BaseAddress The base address for the region. -*/ -#define ARM_MPU_RBAR(Region, BaseAddress) \ - (((BaseAddress) & MPU_RBAR_ADDR_Msk) | \ - ((Region) & MPU_RBAR_REGION_Msk) | \ - (MPU_RBAR_VALID_Msk)) - -/** -* MPU Memory Access Attributes -* -* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. -* \param IsShareable Region is shareable between multiple bus masters. -* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. -* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. -*/ -#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \ - ((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \ - (((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \ - (((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \ - (((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk)) - -/** -* MPU Region Attribute and Size Register Value -* -* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. -* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. -* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. -* \param SubRegionDisable Sub-region disable field. -* \param Size Region size of the region to be configured, for example 4K, 8K. -*/ -#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \ - ((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \ - (((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \ - (((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \ - (((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \ - (((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \ - (((MPU_RASR_ENABLE_Msk)))) - -/** -* MPU Region Attribute and Size Register Value -* -* \param DisableExec Instruction access disable bit, 1= disable instruction fetches. -* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. -* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. -* \param IsShareable Region is shareable between multiple bus masters. -* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. -* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. -* \param SubRegionDisable Sub-region disable field. -* \param Size Region size of the region to be configured, for example 4K, 8K. -*/ -#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \ - ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size) - -/** -* MPU Memory Access Attribute for strongly ordered memory. -* - TEX: 000b -* - Shareable -* - Non-cacheable -* - Non-bufferable -*/ -#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U) - -/** -* MPU Memory Access Attribute for device memory. -* - TEX: 000b (if shareable) or 010b (if non-shareable) -* - Shareable or non-shareable -* - Non-cacheable -* - Bufferable (if shareable) or non-bufferable (if non-shareable) -* -* \param IsShareable Configures the device memory as shareable or non-shareable. -*/ -#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U)) - -/** -* MPU Memory Access Attribute for normal memory. -* - TEX: 1BBb (reflecting outer cacheability rules) -* - Shareable or non-shareable -* - Cacheable or non-cacheable (reflecting inner cacheability rules) -* - Bufferable or non-bufferable (reflecting inner cacheability rules) -* -* \param OuterCp Configures the outer cache policy. -* \param InnerCp Configures the inner cache policy. -* \param IsShareable Configures the memory as shareable or non-shareable. -*/ -#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U)) - -/** -* MPU Memory Access Attribute non-cacheable policy. -*/ -#define ARM_MPU_CACHEP_NOCACHE 0U - -/** -* MPU Memory Access Attribute write-back, write and read allocate policy. -*/ -#define ARM_MPU_CACHEP_WB_WRA 1U - -/** -* MPU Memory Access Attribute write-through, no write allocate policy. -*/ -#define ARM_MPU_CACHEP_WT_NWA 2U - -/** -* MPU Memory Access Attribute write-back, no write allocate policy. -*/ -#define ARM_MPU_CACHEP_WB_NWA 3U - - -/** -* Struct for a single MPU Region -*/ -typedef struct { - uint32_t RBAR; //!< The region base address register value (RBAR) - uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR -} ARM_MPU_Region_t; - -/** Enable the MPU. -* \param MPU_Control Default access permissions for unconfigured regions. -*/ -__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control) -{ - __DMB(); - MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; -#ifdef SCB_SHCSR_MEMFAULTENA_Msk - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; -#endif - __DSB(); - __ISB(); -} - -/** Disable the MPU. -*/ -__STATIC_INLINE void ARM_MPU_Disable(void) -{ - __DMB(); -#ifdef SCB_SHCSR_MEMFAULTENA_Msk - SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; -#endif - MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; - __DSB(); - __ISB(); -} - -/** Clear and disable the given MPU region. -* \param rnr Region number to be cleared. -*/ -__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr) -{ - MPU->RNR = rnr; - MPU->RASR = 0U; -} - -/** Configure an MPU region. -* \param rbar Value for RBAR register. -* \param rasr Value for RASR register. -*/ -__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr) -{ - MPU->RBAR = rbar; - MPU->RASR = rasr; -} - -/** Configure the given MPU region. -* \param rnr Region number to be configured. -* \param rbar Value for RBAR register. -* \param rasr Value for RASR register. -*/ -__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr) -{ - MPU->RNR = rnr; - MPU->RBAR = rbar; - MPU->RASR = rasr; -} - -/** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_Load(). -* \param dst Destination data is copied to. -* \param src Source data is copied from. -* \param len Amount of data words to be copied. -*/ -__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len) -{ - uint32_t i; - for (i = 0U; i < len; ++i) - { - dst[i] = src[i]; - } -} - -/** Load the given number of MPU regions from a table. -* \param table Pointer to the MPU configuration table. -* \param cnt Amount of regions to be configured. -*/ -__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt) -{ - const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U; - while (cnt > MPU_TYPE_RALIASES) { - ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize); - table += MPU_TYPE_RALIASES; - cnt -= MPU_TYPE_RALIASES; - } - ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize); -} - -#endif diff --git a/tests/projects/mdk/hello/src/lib/cmsis/system_ARMCM3.h b/tests/projects/mdk/hello/src/lib/cmsis/system_ARMCM3.h deleted file mode 100644 index 5d1237770..000000000 --- a/tests/projects/mdk/hello/src/lib/cmsis/system_ARMCM3.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************//** - * @file system_ARMCM3.h - * @brief CMSIS Device System Header File for - * ARMCM3 Device - * @version V5.3.2 - * @date 15. November 2019 - ******************************************************************************/ -/* - * Copyright (c) 2009-2019 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SYSTEM_ARMCM3_H -#define SYSTEM_ARMCM3_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - \brief Exception / Interrupt Handler Function Prototype -*/ -typedef void(*VECTOR_TABLE_Type)(void); - -/** - \brief System Clock Frequency (Core Clock) -*/ -extern uint32_t SystemCoreClock; - -/** - \brief Setup the microcontroller system. - - Initialize the System and update the SystemCoreClock variable. - */ -extern void SystemInit (void); - - -/** - \brief Update SystemCoreClock variable. - - Updates the SystemCoreClock with current core Clock retrieved from cpu registers. - */ -extern void SystemCoreClockUpdate (void); - -#ifdef __cplusplus -} -#endif - -#endif /* SYSTEM_ARMCM3_H */ diff --git a/tests/projects/mdk/hello/src/main.c b/tests/projects/mdk/hello/src/main.c deleted file mode 100644 index 28d909a18..000000000 --- a/tests/projects/mdk/hello/src/main.c +++ /dev/null @@ -1,6 +0,0 @@ -int foo(int x); - -int main() -{ - return foo(1); -} diff --git a/tests/projects/mdk/hello/src/startup_ARMCM3.s b/tests/projects/mdk/hello/src/startup_ARMCM3.s deleted file mode 100644 index efe40c1e3..000000000 --- a/tests/projects/mdk/hello/src/startup_ARMCM3.s +++ /dev/null @@ -1,172 +0,0 @@ -;/**************************************************************************//** -; * @file startup_ARMCM3.s -; * @brief CMSIS Core Device Startup File for -; * ARMCM3 Device -; * @version V1.0.1 -; * @date 23. July 2019 -; ******************************************************************************/ -;/* -; * Copyright (c) 2009-2019 Arm Limited. All rights reserved. -; * -; * SPDX-License-Identifier: Apache-2.0 -; * -; * Licensed under the Apache License, Version 2.0 (the License); you may -; * not use this file except in compliance with the License. -; * You may obtain a copy of the License at -; * -; * www.apache.org/licenses/LICENSE-2.0 -; * -; * Unless required by applicable law or agreed to in writing, software -; * distributed under the License is distributed on an AS IS BASIS, WITHOUT -; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -; * See the License for the specific language governing permissions and -; * limitations under the License. -; */ - -;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ - - -; Stack Configuration -; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - -Stack_Size EQU 0x00000400 - - AREA STACK, NOINIT, READWRITE, ALIGN=3 -__stack_limit -Stack_Mem SPACE Stack_Size -__initial_sp - - -; Heap Configuration -; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> -; - -Heap_Size EQU 0x00000C00 - - IF Heap_Size != 0 ; Heap is provided - AREA HEAP, NOINIT, READWRITE, ALIGN=3 -__heap_base -Heap_Mem SPACE Heap_Size -__heap_limit - ENDIF - - - PRESERVE8 - THUMB - - -; Vector Table Mapped to Address 0 at Reset - - AREA RESET, DATA, READONLY - EXPORT __Vectors - EXPORT __Vectors_End - EXPORT __Vectors_Size - -__Vectors DCD __initial_sp ; Top of Stack - DCD Reset_Handler ; Reset Handler - DCD NMI_Handler ; -14 NMI Handler - DCD HardFault_Handler ; -13 Hard Fault Handler - DCD MemManage_Handler ; -12 MPU Fault Handler - DCD BusFault_Handler ; -11 Bus Fault Handler - DCD UsageFault_Handler ; -10 Usage Fault Handler - DCD 0 ; Reserved - DCD 0 ; Reserved - DCD 0 ; Reserved - DCD 0 ; Reserved - DCD SVC_Handler ; -5 SVCall Handler - DCD DebugMon_Handler ; -4 Debug Monitor Handler - DCD 0 ; Reserved - DCD PendSV_Handler ; -2 PendSV Handler - DCD SysTick_Handler ; -1 SysTick Handler - - ; Interrupts - DCD Interrupt0_Handler ; 0 Interrupt 0 - DCD Interrupt1_Handler ; 1 Interrupt 1 - DCD Interrupt2_Handler ; 2 Interrupt 2 - DCD Interrupt3_Handler ; 3 Interrupt 3 - DCD Interrupt4_Handler ; 4 Interrupt 4 - DCD Interrupt5_Handler ; 5 Interrupt 5 - DCD Interrupt6_Handler ; 6 Interrupt 6 - DCD Interrupt7_Handler ; 7 Interrupt 7 - DCD Interrupt8_Handler ; 8 Interrupt 8 - DCD Interrupt9_Handler ; 9 Interrupt 9 - - SPACE (214 * 4) ; Interrupts 10 .. 224 are left out -__Vectors_End -__Vectors_Size EQU __Vectors_End - __Vectors - - - AREA |.text|, CODE, READONLY - -; Reset Handler - -Reset_Handler PROC - EXPORT Reset_Handler [WEAK] - IMPORT SystemInit - IMPORT __main - - LDR R0, =SystemInit - BLX R0 - LDR R0, =__main - BX R0 - ENDP - -; The default macro is not used for HardFault_Handler -; because this results in a poor debug illusion. -HardFault_Handler PROC - EXPORT HardFault_Handler [WEAK] - B . - ENDP - -; Macro to define default exception/interrupt handlers. -; Default handler are weak symbols with an endless loop. -; They can be overwritten by real handlers. - MACRO - Set_Default_Handler $Handler_Name -$Handler_Name PROC - EXPORT $Handler_Name [WEAK] - B . - ENDP - MEND - - -; Default exception/interrupt handler - - Set_Default_Handler NMI_Handler - Set_Default_Handler MemManage_Handler - Set_Default_Handler BusFault_Handler - Set_Default_Handler UsageFault_Handler - Set_Default_Handler SVC_Handler - Set_Default_Handler DebugMon_Handler - Set_Default_Handler PendSV_Handler - Set_Default_Handler SysTick_Handler - - Set_Default_Handler Interrupt0_Handler - Set_Default_Handler Interrupt1_Handler - Set_Default_Handler Interrupt2_Handler - Set_Default_Handler Interrupt3_Handler - Set_Default_Handler Interrupt4_Handler - Set_Default_Handler Interrupt5_Handler - Set_Default_Handler Interrupt6_Handler - Set_Default_Handler Interrupt7_Handler - Set_Default_Handler Interrupt8_Handler - Set_Default_Handler Interrupt9_Handler - - ALIGN - - -; User setup Stack & Heap - - IF :LNOT::DEF:__MICROLIB - IMPORT __use_two_region_memory - ENDIF - - EXPORT __stack_limit - EXPORT __initial_sp - IF Heap_Size != 0 ; Heap is provided - EXPORT __heap_base - EXPORT __heap_limit - ENDIF - - END diff --git a/tests/projects/mdk/hello/src/system_ARMCM3.c b/tests/projects/mdk/hello/src/system_ARMCM3.c deleted file mode 100644 index 19484537f..000000000 --- a/tests/projects/mdk/hello/src/system_ARMCM3.c +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************//** - * @file system_ARMCM3.c - * @brief CMSIS Device System Source File for - * ARMCM3 Device - * @version V1.0.1 - * @date 15. November 2019 - ******************************************************************************/ -/* - * Copyright (c) 2009-2019 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ARMCM3.h" - -/*---------------------------------------------------------------------------- - Define clocks - *----------------------------------------------------------------------------*/ -#define XTAL (50000000UL) /* Oscillator frequency */ - -#define SYSTEM_CLOCK (XTAL / 2U) - -/*---------------------------------------------------------------------------- - Exception / Interrupt Vector table - *----------------------------------------------------------------------------*/ -extern const VECTOR_TABLE_Type __VECTOR_TABLE[240]; - -/*---------------------------------------------------------------------------- - System Core Clock Variable - *----------------------------------------------------------------------------*/ -uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Core Clock Frequency */ - - -/*---------------------------------------------------------------------------- - System Core Clock update function - *----------------------------------------------------------------------------*/ -void SystemCoreClockUpdate (void) -{ - SystemCoreClock = SYSTEM_CLOCK; -} - -/*---------------------------------------------------------------------------- - System initialization function - *----------------------------------------------------------------------------*/ -void SystemInit (void) -{ - -#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) - SCB->VTOR = (uint32_t) &(__VECTOR_TABLE[0]); -#endif - - SystemCoreClock = SYSTEM_CLOCK; -} diff --git a/tests/projects/mdk/hello/xmake.lua b/tests/projects/mdk/hello/xmake.lua deleted file mode 100644 index 6afb714af..000000000 --- a/tests/projects/mdk/hello/xmake.lua +++ /dev/null @@ -1,13 +0,0 @@ -add_rules("mode.debug", "mode.release") - -set_runtimes("microlib") - -target("foo") - add_rules("mdk.static") - add_files("src/foo/*.c") - -target("hello") - add_deps("foo") - add_rules("mdk.console") - add_files("src/*.c", "src/*.s") - add_includedirs("src/lib/cmsis") diff --git a/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.c b/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.c deleted file mode 100644 index 13f811f35..000000000 --- a/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.c +++ /dev/null @@ -1,1309 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - nonpnp.c - -Abstract: - - Purpose of this driver is to demonstrate how to write a legacy (NON WDM) - driver using framework, show how to handle 4 different ioctls - - METHOD_NEITHER - in particular and also show how to read & write to file - from KernelMode using Zw functions. - - For a non-framework version of sample on how to handle IOCTLs in driver, - study src\general\IOCTL in the DDK. - -Environment: - - Kernel mode only. - ---*/ - -#include "nonpnp.h" - -// -// The trace message header file must be included in a source file -// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS -// macro. During the compilation, WPP scans the source files for -// TraceEvents() calls and builds a .tmh file which stores a unique -// data GUID for each message, the text resource string for each message, -// and the data types of the variables passed in for each message. -// This file is automatically generated and used during post-processing. -// -#include "nonpnp.tmh" - - -#ifdef ALLOC_PRAGMA -#pragma alloc_text( INIT, DriverEntry ) -#pragma alloc_text( PAGE, NonPnpDeviceAdd) -#pragma alloc_text( PAGE, NonPnpEvtDriverContextCleanup) -#pragma alloc_text( PAGE, NonPnpEvtDriverUnload) -#pragma alloc_text( PAGE, NonPnpEvtDeviceIoInCallerContext) -#pragma alloc_text( PAGE, NonPnpEvtDeviceFileCreate) -#pragma alloc_text( PAGE, NonPnpEvtFileClose) -#pragma alloc_text( PAGE, FileEvtIoRead) -#pragma alloc_text( PAGE, FileEvtIoWrite) -#pragma alloc_text( PAGE, FileEvtIoDeviceControl) -#endif // ALLOC_PRAGMA - - -NTSTATUS -DriverEntry( - IN OUT PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - This routine is called by the Operating System to initialize the driver. - - It creates the device object, fills in the dispatch entry points and - completes the initialization. - -Arguments: - DriverObject - a pointer to the object that represents this device - driver. - - RegistryPath - a pointer to our Services key in the registry. - -Return Value: - STATUS_SUCCESS if initialized; an error otherwise. - ---*/ -{ - NTSTATUS status; - WDF_DRIVER_CONFIG config; - WDFDRIVER hDriver; - PWDFDEVICE_INIT pInit = NULL; - WDF_OBJECT_ATTRIBUTES attributes; - - KdPrint(("Driver Frameworks NONPNP Legacy Driver Example\n")); - - - WDF_DRIVER_CONFIG_INIT( - &config, - WDF_NO_EVENT_CALLBACK // This is a non-pnp driver. - ); - - // - // Tell the framework that this is non-pnp driver so that it doesn't - // set the default AddDevice routine. - // - config.DriverInitFlags |= WdfDriverInitNonPnpDriver; - - // - // NonPnp driver must explicitly register an unload routine for - // the driver to be unloaded. - // - config.EvtDriverUnload = NonPnpEvtDriverUnload; - - // - // Register a cleanup callback so that we can call WPP_CLEANUP when - // the framework driver object is deleted during driver unload. - // - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.EvtCleanupCallback = NonPnpEvtDriverContextCleanup; - - // - // Create a framework driver object to represent our driver. - // - status = WdfDriverCreate(DriverObject, - RegistryPath, - &attributes, - &config, - &hDriver); - if (!NT_SUCCESS(status)) { - KdPrint (("NonPnp: WdfDriverCreate failed with status 0x%x\n", status)); - return status; - } - - // - // Since we are calling WPP_CLEANUP in the DriverContextCleanup - // callback we should initialize WPP Tracing after WDFDRIVER - // object is created to ensure that we cleanup WPP properly - // if we return failure status from DriverEntry. This - // eliminates the need to call WPP_CLEANUP in every path - // of DriverEntry. - // - WPP_INIT_TRACING( DriverObject, RegistryPath ); - - // - // On Win2K system, you will experience some delay in getting trace events - // due to the way the ETW is activated to accept trace messages. - // - KdPrint(("NonPnp: DriverEntry: tracing enabled\n")); - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, - "Driver Frameworks NONPNP Legacy Driver Example"); - - // - // - // In order to create a control device, we first need to allocate a - // WDFDEVICE_INIT structure and set all properties. - // - pInit = WdfControlDeviceInitAllocate( - hDriver, - &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R - ); - - if (pInit == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - return status; - } - - // - // Call NonPnpDeviceAdd to create a deviceobject to represent our - // software device. - // - status = NonPnpDeviceAdd(hDriver, pInit); - - return status; -} - -NTSTATUS -NonPnpDeviceAdd( - IN WDFDRIVER Driver, - IN PWDFDEVICE_INIT DeviceInit - ) -/*++ - -Routine Description: - - Called by the DriverEntry to create a control-device. This call is - responsible for freeing the memory for DeviceInit. - -Arguments: - - DriverObject - a pointer to the object that represents this device - driver. - - DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. - -Return Value: - - STATUS_SUCCESS if initialized; an error otherwise. - ---*/ -{ - NTSTATUS status; - WDF_OBJECT_ATTRIBUTES attributes; - WDF_IO_QUEUE_CONFIG ioQueueConfig; - WDF_FILEOBJECT_CONFIG fileConfig; - WDFQUEUE queue; - WDFDEVICE controlDevice; - DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; - DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; - - UNREFERENCED_PARAMETER( Driver ); - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, - "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit); - // - // Set exclusive to TRUE so that no more than one app can talk to the - // control device at any time. - // - WdfDeviceInitSetExclusive(DeviceInit, TRUE); - - WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); - - - status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); - - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status); - goto End; - } - - WdfControlDeviceInitSetShutdownNotification(DeviceInit, - NonPnpShutdown, - WdfDeviceShutdown); - - // - // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the - // framework whether you are interested in handling Create, Close and - // Cleanup requests that gets generated when an application or another - // kernel component opens an handle to the device. If you don't register - // the framework default behaviour would be to complete these requests - // with STATUS_SUCCESS. A driver might be interested in registering these - // events if it wants to do security validation and also wants to maintain - // per handle (fileobject) context. - // - - WDF_FILEOBJECT_CONFIG_INIT( - &fileConfig, - NonPnpEvtDeviceFileCreate, - NonPnpEvtFileClose, - WDF_NO_EVENT_CALLBACK // not interested in Cleanup - ); - - WdfDeviceInitSetFileObjectConfig(DeviceInit, - &fileConfig, - WDF_NO_OBJECT_ATTRIBUTES); - - // - // In order to support METHOD_NEITHER Device controls, or - // NEITHER device I/O type, we need to register for the - // EvtDeviceIoInProcessContext callback so that we can handle the request - // in the calling threads context. - // - WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, - NonPnpEvtDeviceIoInCallerContext); - - // - // Specify the size of device context - // - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, - CONTROL_DEVICE_EXTENSION); - - status = WdfDeviceCreate(&DeviceInit, - &attributes, - &controlDevice); - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status); - goto End; - } - - // - // Create a symbolic link for the control object so that usermode can open - // the device. - // - - - status = WdfDeviceCreateSymbolicLink(controlDevice, - &symbolicLinkName); - - if (!NT_SUCCESS(status)) { - // - // Control device will be deleted automatically by the framework. - // - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status); - goto End; - } - - // - // Configure a default queue so that requests that are not - // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto - // other queues get dispatched here. - // - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, - WdfIoQueueDispatchSequential); - - ioQueueConfig.EvtIoRead = FileEvtIoRead; - ioQueueConfig.EvtIoWrite = FileEvtIoWrite; - ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl; - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - // - // Since we are using Zw function set execution level to passive so that - // framework ensures that our Io callbacks called at only passive-level - // even if the request came in at DISPATCH_LEVEL from another driver. - // - //attributes.ExecutionLevel = WdfExecutionLevelPassive; - - // - // By default, Static Driver Verifier (SDV) displays a warning if it - // doesn't find the EvtIoStop callback on a power-managed queue. - // The 'assume' below causes SDV to suppress this warning. If the driver - // has not explicitly set PowerManaged to WdfFalse, the framework creates - // power-managed queues when the device is not a filter driver. Normally - // the EvtIoStop is required for power-managed queues, but for this driver - // it is not needed b/c the driver doesn't hold on to the requests or - // forward them to other drivers. This driver completes the requests - // directly in the queue's handlers. If the EvtIoStop callback is not - // implemented, the framework waits for all driver-owned requests to be - // done before moving in the Dx/sleep states or before removing the - // device, which is the correct behavior for this type of driver. - // If the requests were taking an indeterminate amount of time to complete, - // or if the driver forwarded the requests to a lower driver/another stack, - // the queue should have an EvtIoStop/EvtIoResume. - // - __analysis_assume(ioQueueConfig.EvtIoStop != 0); - status = WdfIoQueueCreate(controlDevice, - &ioQueueConfig, - &attributes, - &queue // pointer to default queue - ); - __analysis_assume(ioQueueConfig.EvtIoStop == 0); - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status); - goto End; - } - - // - // Control devices must notify WDF when they are done initializing. I/O is - // rejected until this call is made. - // - WdfControlFinishInitializing(controlDevice); - -End: - // - // If the device is created successfully, framework would clear the - // DeviceInit value. Otherwise device create must have failed so we - // should free the memory ourself. - // - if (DeviceInit != NULL) { - WdfDeviceInitFree(DeviceInit); - } - - return status; - -} - -VOID -NonPnpEvtDriverContextCleanup( - IN WDFOBJECT Driver - ) -/*++ -Routine Description: - - Called when the driver object is deleted during driver unload. - You can free all the resources created in DriverEntry that are - not automatically freed by the framework. - -Arguments: - - Driver - Handle to a framework driver object created in DriverEntry - -Return Value: - - NTSTATUS - ---*/ -{ - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, - "Entered NonPnpEvtDriverContextCleanup\n"); - - PAGED_CODE(); - - // - // No need to free the controldevice object explicitly because it will - // be deleted when the Driver object is deleted due to the default parent - // child relationship between Driver and ControlDevice. - // - WPP_CLEANUP( WdfDriverWdmGetDriverObject( (WDFDRIVER)Driver ) ); - -} - - - -VOID -NonPnpEvtDeviceFileCreate ( - IN WDFDEVICE Device, - IN WDFREQUEST Request, - IN WDFFILEOBJECT FileObject - ) -/*++ - -Routine Description: - - The framework calls a driver's EvtDeviceFileCreate callback - when it receives an IRP_MJ_CREATE request. - The system sends this request when a user application opens the - device to perform an I/O operation, such as reading or writing a file. - This callback is called synchronously, in the context of the thread - that created the IRP_MJ_CREATE request. - -Arguments: - - Device - Handle to a framework device object. - FileObject - Pointer to fileobject that represents the open handle. - CreateParams - Parameters of IO_STACK_LOCATION for create - -Return Value: - - NT status code - ---*/ -{ - PUNICODE_STRING fileName; - UNICODE_STRING absFileName, directory; - OBJECT_ATTRIBUTES fileAttributes; - IO_STATUS_BLOCK ioStatus; - PCONTROL_DEVICE_EXTENSION devExt; - NTSTATUS status; - USHORT length = 0; - - - UNREFERENCED_PARAMETER( FileObject ); - - PAGED_CODE (); - - devExt = ControlGetData(Device); - - // - // Assume the directory is a temp directory under %windir% - // - RtlInitUnicodeString(&directory, L"\\SystemRoot\\temp"); - - // - // Parsed filename has "\" in the begining. The object manager strips - // of all "\", except one, after the device name. - // - fileName = WdfFileObjectGetFileName(FileObject); - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpEvtDeviceFileCreate %wZ%wZ", - &directory, fileName); - - // - // Find the total length of the directory + filename - // - length = directory.Length + fileName->Length; - - absFileName.Buffer = ExAllocatePoolWithTag(PagedPool, length, POOL_TAG); - if(absFileName.Buffer == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed"); - goto End; - } - absFileName.Length = 0; - absFileName.MaximumLength = length; - - status = RtlAppendUnicodeStringToString(&absFileName, &directory); - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, - "RtlAppendUnicodeStringToString failed with status %!STATUS!", - status); - goto End; - } - - status = RtlAppendUnicodeStringToString(&absFileName, fileName); - if (!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, - "RtlAppendUnicodeStringToString failed with status %!STATUS!", - status); - goto End; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "Absolute Filename %wZ", &absFileName); - - InitializeObjectAttributes( &fileAttributes, - &absFileName, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, // RootDirectory - NULL // SecurityDescriptor - ); - - status = ZwCreateFile ( - &devExt->FileHandle, - SYNCHRONIZE | GENERIC_WRITE | GENERIC_READ, - &fileAttributes, - &ioStatus, - NULL,// alloc size = none - FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ, - FILE_OPEN_IF, - FILE_SYNCHRONOUS_IO_NONALERT |FILE_NON_DIRECTORY_FILE, - NULL,// eabuffer - 0// ealength - ); - - if (!NT_SUCCESS(status)) { - - TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, - "ZwCreateFile failed with status %!STATUS!", status); - devExt->FileHandle = NULL; - } - -End: - if(absFileName.Buffer != NULL) { - ExFreePool(absFileName.Buffer); - } - - WdfRequestComplete(Request, status); - - return; -} - - -VOID -NonPnpEvtFileClose ( - IN WDFFILEOBJECT FileObject - ) - -/*++ - -Routine Description: - - EvtFileClose is called when all the handles represented by the FileObject - is closed and all the references to FileObject is removed. This callback - may get called in an arbitrary thread context instead of the thread that - called CloseHandle. If you want to delete any per FileObject context that - must be done in the context of the user thread that made the Create call, - you should do that in the EvtDeviceCleanp callback. - -Arguments: - - FileObject - Pointer to fileobject that represents the open handle. - -Return Value: - - VOID - ---*/ -{ - PCONTROL_DEVICE_EXTENSION devExt; - - PAGED_CODE (); - - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpEvtFileClose\n"); - - devExt = ControlGetData(WdfFileObjectGetDevice(FileObject)); - - if(devExt->FileHandle) { - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, - "Closing File Handle %p", devExt->FileHandle); - ZwClose(devExt->FileHandle); - } - - return; -} - - -VOID -FileEvtIoRead( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t Length - ) -/*++ - -Routine Description: - - This event is called when the framework receives IRP_MJ_READ requests. - We will just read the file. - -Arguments: - - Queue - Handle to the framework queue object that is associated with the - I/O request. - Request - Handle to a framework request object. - - Length - number of bytes to be read. - Queue is by default configured to fail zero length read & write requests. - -Return Value: - - None. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PVOID outBuf; - IO_STATUS_BLOCK ioStatus; - PCONTROL_DEVICE_EXTENSION devExt; - FILE_POSITION_INFORMATION position; - ULONG_PTR bytesRead = 0; - size_t bufLength; - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_RW, "FileEvtIoRead: Request: 0x%p, Queue: 0x%p\n", - Request, Queue); - - PAGED_CODE (); - - // - // Get the request buffer. Since the device is set to do buffered - // I/O, this function will retrieve Irp->AssociatedIrp.SystemBuffer. - // - status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufLength); - if(!NT_SUCCESS(status)) { - WdfRequestComplete(Request, status); - return; - - } - - devExt = ControlGetData(WdfIoQueueGetDevice(Queue)); - - if(devExt->FileHandle) { - - // - // Set the file position to the beginning of the file. - // - position.CurrentByteOffset.QuadPart = 0; - status = ZwSetInformationFile(devExt->FileHandle, - &ioStatus, - &position, - sizeof(FILE_POSITION_INFORMATION), - FilePositionInformation); - if (NT_SUCCESS(status)) { - - status = ZwReadFile (devExt->FileHandle, - NULL,// Event, - NULL,// PIO_APC_ROUTINE ApcRoutine - NULL,// PVOID ApcContext - &ioStatus, - outBuf, - (ULONG)Length, - 0, // ByteOffset - NULL // Key - ); - - if (!NT_SUCCESS(status)) { - - TraceEvents(TRACE_LEVEL_ERROR, DBG_RW, - "ZwReadFile failed with status 0x%x", - status); - } - - status = ioStatus.Status; - bytesRead = ioStatus.Information; - } - } - - WdfRequestCompleteWithInformation(Request, status, bytesRead); - -} - - - -VOID -FileEvtIoWrite( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t Length - ) -/*++ - -Routine Description: - - This event is called when the framework receives IRP_MJ_WRITE requests. - -Arguments: - - Queue - Handle to the framework queue object that is associated with the - I/O request. - Request - Handle to a framework request object. - - Length - number of bytes to be written. - Queue is by default configured to fail zero length read & write requests. - - -Return Value: - - None ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PVOID inBuf; - IO_STATUS_BLOCK ioStatus; - PCONTROL_DEVICE_EXTENSION devExt; - FILE_POSITION_INFORMATION position; - ULONG_PTR bytesWritten = 0; - size_t bufLength; - - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_RW, "FileEvtIoWrite: Request: 0x%p, Queue: 0x%p\n", - Request, Queue); - PAGED_CODE (); - - // - // Get the request buffer. Since the device is set to do buffered - // I/O, this function will retrieve Irp->AssociatedIrp.SystemBuffer. - // - status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufLength); - if(!NT_SUCCESS(status)) { - WdfRequestComplete(Request, status); - return; - - } - - devExt = ControlGetData(WdfIoQueueGetDevice(Queue)); - - if(devExt->FileHandle) { - - // - // Set the file position to the beginning of the file. - // - position.CurrentByteOffset.QuadPart = 0; - - status = ZwSetInformationFile(devExt->FileHandle, - &ioStatus, - &position, - sizeof(FILE_POSITION_INFORMATION), - FilePositionInformation); - if (NT_SUCCESS(status)) - { - - status = ZwWriteFile(devExt->FileHandle, - NULL,// Event, - NULL,// PIO_APC_ROUTINE ApcRoutine - NULL,// PVOID ApcContext - &ioStatus, - inBuf, - (ULONG)Length, - 0, // ByteOffset - NULL // Key - ); - if (!NT_SUCCESS(status)) - { - TraceEvents(TRACE_LEVEL_ERROR, DBG_RW, - "ZwWriteFile failed with status 0x%x", - status); - } - - status = ioStatus.Status; - bytesWritten = ioStatus.Information; - } - } - - WdfRequestCompleteWithInformation(Request, status, bytesWritten); - -} - -VOID -FileEvtIoDeviceControl( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t OutputBufferLength, - IN size_t InputBufferLength, - IN ULONG IoControlCode - ) -/*++ -Routine Description: - - This event is called when the framework receives IRP_MJ_DEVICE_CONTROL - requests from the system. - -Arguments: - - Queue - Handle to the framework queue object that is associated - with the I/O request. - Request - Handle to a framework request object. - - OutputBufferLength - length of the request's output buffer, - if an output buffer is available. - InputBufferLength - length of the request's input buffer, - if an input buffer is available. - - IoControlCode - the driver-defined or system-defined I/O control code - (IOCTL) that is associated with the request. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS;// Assume success - PCHAR inBuf = NULL, outBuf = NULL; // pointer to Input and output buffer - PCHAR data = "this String is from Device Driver !!!"; - ULONG datalen = (ULONG) strlen(data)+1;//Length of data including null - PCHAR buffer = NULL; - PREQUEST_CONTEXT reqContext = NULL; - size_t bufSize; - - UNREFERENCED_PARAMETER( Queue ); - - PAGED_CODE(); - - if(!OutputBufferLength || !InputBufferLength) - { - WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); - return; - } - - // - // Determine which I/O control code was specified. - // - - switch (IoControlCode) - { - case IOCTL_NONPNP_METHOD_BUFFERED: - - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_BUFFERED\n"); - - // - // For bufffered ioctls WdfRequestRetrieveInputBuffer & - // WdfRequestRetrieveOutputBuffer return the same buffer - // pointer (Irp->AssociatedIrp.SystemBuffer), so read the - // content of the buffer before writing to it. - // - status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); - if(!NT_SUCCESS(status)) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - ASSERT(bufSize == InputBufferLength); - - // - // Read the input buffer content. - // We are using the following function to print characters instead - // TraceEvents with %s format because the string we get may or - // may not be null terminated. The buffer may contain non-printable - // characters also. - // - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", - log_xstr(inBuf, (USHORT)InputBufferLength))); - PrintChars(inBuf, InputBufferLength ); - - - status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize); - if(!NT_SUCCESS(status)) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - ASSERT(bufSize == OutputBufferLength); - - // - // Writing to the buffer over-writes the input buffer content - // - - RtlCopyMemory(outBuf, data, OutputBufferLength); - - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", - log_xstr(outBuf, (USHORT)datalen))); - PrintChars(outBuf, datalen ); - - // - // Assign the length of the data copied to IoStatus.Information - // of the request and complete the request. - // - WdfRequestSetInformation(Request, - OutputBufferLength < datalen? OutputBufferLength:datalen); - - // - // When the request is completed the content of the SystemBuffer - // is copied to the User output buffer and the SystemBuffer is - // is freed. - // - - break; - - - case IOCTL_NONPNP_METHOD_IN_DIRECT: - - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_IN_DIRECT\n"); - - // - // Get the Input buffer. WdfRequestRetrieveInputBuffer returns - // Irp->AssociatedIrp.SystemBuffer. - // - status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); - if(!NT_SUCCESS(status)) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - ASSERT(bufSize == InputBufferLength); - - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", - log_xstr(inBuf, (USHORT)InputBufferLength))); - PrintChars(inBuf, InputBufferLength); - - // - // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe - // on the Irp->MdlAddress and returns the system address. - // Oddity: For this method, this buffer is intended for transfering data - // from the application to the driver. - // - - status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize); - if(!NT_SUCCESS(status)) { - break; - } - - ASSERT(bufSize == OutputBufferLength); - - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User in OutputBuffer: %!HEXDUMP!\n", - log_xstr(buffer, (USHORT)OutputBufferLength))); - PrintChars(buffer, OutputBufferLength); - - // - // Return total bytes read from the output buffer. - // Note OutputBufferLength = MmGetMdlByteCount(Irp->MdlAddress) - // - - WdfRequestSetInformation(Request, OutputBufferLength); - - // - // NOTE: Changes made to the SystemBuffer are not copied - // to the user input buffer by the I/O manager - // - - break; - - case IOCTL_NONPNP_METHOD_OUT_DIRECT: - - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_OUT_DIRECT\n"); - - // - // Get the Input buffer. WdfRequestRetrieveInputBuffer returns - // Irp->AssociatedIrp.SystemBuffer. - // - status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); - if(!NT_SUCCESS(status)) { - status = STATUS_INSUFFICIENT_RESOURCES; - break; - } - - ASSERT(bufSize == InputBufferLength); - - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", - log_xstr(inBuf, (USHORT)InputBufferLength))); - PrintChars(inBuf, InputBufferLength); - - // - // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe - // on the Irp->MdlAddress and returns the system address. - // For this method, this buffer is intended for transfering data from the - // driver to the application. - // - status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize); - if(!NT_SUCCESS(status)) { - break; - } - - ASSERT(bufSize == OutputBufferLength); - - // - // Write data to be sent to the user in this buffer - // - RtlCopyMemory(buffer, data, OutputBufferLength); - - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", - log_xstr(buffer, (USHORT)datalen))); - PrintChars(buffer, datalen); - - WdfRequestSetInformation(Request, - OutputBufferLength < datalen? OutputBufferLength: datalen); - - // - // NOTE: Changes made to the SystemBuffer are not copied - // to the user input buffer by the I/O manager - // - - break; - - case IOCTL_NONPNP_METHOD_NEITHER: - { - size_t inBufLength, outBufLength; - - // - // The NonPnpEvtDeviceIoInCallerContext has already probe and locked the - // pages and mapped the user buffer into system address space and - // stored memory buffer pointers in the request context. We can get the - // buffer pointer by calling WdfMemoryGetBuffer. - // - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_NEITHER\n"); - - reqContext = GetRequestContext(Request); - - inBuf = WdfMemoryGetBuffer(reqContext->InputMemoryBuffer, &inBufLength); - outBuf = WdfMemoryGetBuffer(reqContext->OutputMemoryBuffer, &outBufLength); - - if(inBuf == NULL || outBuf == NULL) { - status = STATUS_INVALID_PARAMETER; - } - - ASSERT(inBufLength == InputBufferLength); - ASSERT(outBufLength == OutputBufferLength); - - // - // Now you can safely read the data from the buffer in any arbitrary - // context. - // - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", - log_xstr(inBuf, (USHORT)inBufLength))); - PrintChars(inBuf, inBufLength); - - // - // Write to the buffer in any arbitrary context. - // - RtlCopyMemory(outBuf, data, outBufLength); - - Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", - log_xstr(outBuf, (USHORT)datalen))); - PrintChars(outBuf, datalen); - - // - // Assign the length of the data copied to IoStatus.Information - // of the Irp and complete the Irp. - // - WdfRequestSetInformation(Request, - outBufLength < datalen? outBufLength:datalen); - - break; - } - default: - - // - // The specified I/O control code is unrecognized by this driver. - // - status = STATUS_INVALID_DEVICE_REQUEST; - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ERROR: unrecognized IOCTL %x\n", IoControlCode); - break; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Completing Request %p with status %X", - Request, status ); - - WdfRequestComplete( Request, status); - -} - -VOID -NonPnpEvtDeviceIoInCallerContext( - IN WDFDEVICE Device, - IN WDFREQUEST Request - ) -/*++ -Routine Description: - - This I/O in-process callback is called in the calling threads context/address - space before the request is subjected to any framework locking or queueing - scheme based on the device pnp/power or locking attributes set by the - driver. The process context of the calling app is guaranteed as long as - this driver is a top-level driver and no other filter driver is attached - to it. - - This callback is only required if you are handling method-neither IOCTLs, - or want to process requests in the context of the calling process. - - Driver developers should avoid defining neither IOCTLs and access user - buffers, and use much safer I/O tranfer methods such as buffered I/O - or direct I/O. - -Arguments: - - Device - Handle to a framework device object. - - Request - Handle to a framework request object. Framework calls - PreProcess callback only for Read/Write/ioctls and internal - ioctl requests. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PREQUEST_CONTEXT reqContext = NULL; - WDF_OBJECT_ATTRIBUTES attributes; - WDF_REQUEST_PARAMETERS params; - size_t inBufLen, outBufLen; - PVOID inBuf, outBuf; - - PAGED_CODE(); - - WDF_REQUEST_PARAMETERS_INIT(¶ms); - - WdfRequestGetParameters(Request, ¶ms ); - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Entered NonPnpEvtDeviceIoInCallerContext %p \n", - Request); - - // - // Check to see whether we have recevied a METHOD_NEITHER IOCTL. if not - // just send the request back to framework because we aren't doing - // any pre-processing in the context of the calling thread process. - // - if(!(params.Type == WdfRequestTypeDeviceControl && - params.Parameters.DeviceIoControl.IoControlCode == - IOCTL_NONPNP_METHOD_NEITHER)) { - // - // Forward it for processing by the I/O package - // - status = WdfDeviceEnqueueRequest(Device, Request); - if( !NT_SUCCESS(status) ) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error forwarding Request 0x%x", status); - goto End; - } - - return; - } - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess: received METHOD_NEITHER ioctl \n"); - - // - // In this type of transfer, the I/O manager assigns the user input - // to Type3InputBuffer and the output buffer to UserBuffer of the Irp. - // The I/O manager doesn't copy or map the buffers to the kernel - // buffers. - // - status = WdfRequestRetrieveUnsafeUserInputBuffer(Request, 0, &inBuf, &inBufLen); - if(!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error WdfRequestRetrieveUnsafeUserInputBuffer failed 0x%x", status); - goto End; - } - - status = WdfRequestRetrieveUnsafeUserOutputBuffer(Request, 0, &outBuf, &outBufLen); - if(!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error WdfRequestRetrieveUnsafeUserOutputBuffer failed 0x%x", status); - goto End; - } - - // - // Allocate a context for this request so that we can store the memory - // objects created for input and output buffer. - // - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); - - status = WdfObjectAllocateContext(Request, &attributes, &reqContext); - if(!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error WdfObjectAllocateContext failed 0x%x", status); - goto End; - } - - // - // WdfRequestProbleAndLockForRead/Write function checks to see - // whether the caller in the right thread context, creates an MDL, - // probe and locks the pages, and map the MDL to system address - // space and finally creates a WDFMEMORY object representing this - // system buffer address. This memory object is associated with the - // request. So it will be freed when the request is completed. If we - // are accessing this memory buffer else where, we should store these - // pointers in the request context. - // - - #pragma prefast(suppress:6387, "If inBuf==NULL at this point, then inBufLen==0") - status = WdfRequestProbeAndLockUserBufferForRead(Request, - inBuf, - inBufLen, - &reqContext->InputMemoryBuffer); - - if(!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error WdfRequestProbeAndLockUserBufferForRead failed 0x%x", status); - goto End; - } - - #pragma prefast(suppress:6387, "If outBuf==NULL at this point, then outBufLen==0") - status = WdfRequestProbeAndLockUserBufferForWrite(Request, - outBuf, - outBufLen, - &reqContext->OutputMemoryBuffer); - if(!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error WdfRequestProbeAndLockUserBufferForWrite failed 0x%x", status); - goto End; - } - - // - // Finally forward it for processing by the I/O package - // - status = WdfDeviceEnqueueRequest(Device, Request); - if(!NT_SUCCESS(status)) { - TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, - "Error WdfDeviceEnqueueRequest failed 0x%x", status); - goto End; - } - - return; - -End: - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess failed %x \n", status); - WdfRequestComplete(Request, status); - return; -} - -VOID -NonPnpShutdown( - WDFDEVICE Device - ) -/*++ - -Routine Description: - Callback invoked when the machine is shutting down. If you register for - a last chance shutdown notification you cannot do the following: - o Call any pageable routines - o Access pageable memory - o Perform any file I/O operations - - If you register for a normal shutdown notification, all of these are - available to you. - - This function implementation does nothing, but if you had any outstanding - file handles open, this is where you would close them. - -Arguments: - Device - The device which registered the notification during init - -Return Value: - None - - --*/ - -{ - UNREFERENCED_PARAMETER(Device); - return; -} - - -VOID -NonPnpEvtDriverUnload( - IN WDFDRIVER Driver - ) -/*++ -Routine Description: - - Called by the I/O subsystem just before unloading the driver. - You can free the resources created in the DriverEntry either - in this routine or in the EvtDriverContextCleanup callback. - -Arguments: - - Driver - Handle to a framework driver object created in DriverEntry - -Return Value: - - NTSTATUS - ---*/ -{ - UNREFERENCED_PARAMETER(Driver); - - PAGED_CODE(); - - TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "Entered NonPnpDriverUnload\n"); - - return; -} - -VOID -PrintChars( - _In_reads_(CountChars) PCHAR BufferAddress, - _In_ size_t CountChars - ) -{ - if (CountChars) { - - while (CountChars--) { - - if (*BufferAddress > 31 - && *BufferAddress != 127) { - - KdPrint (( "%c", *BufferAddress) ); - - } else { - - KdPrint(( ".") ); - - } - BufferAddress++; - } - KdPrint (("\n")); - } - return; -} - diff --git a/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.h b/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.h deleted file mode 100644 index c874e79d2..000000000 --- a/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.h +++ /dev/null @@ -1,90 +0,0 @@ -/*++ - -Copyright (c) 1997 Microsoft Corporation - -Module Name: - - nonpnp.h - -Abstract: - - Contains function prototypes and includes other neccessary header files. - -Environment: - - Kernel mode only. - ---*/ - -#include -#include - -#define NTSTRSAFE_LIB -#include -#include // for SDDLs -#include "public.h" // contains IOCTL definitions -#include "Trace.h" // contains macros for WPP tracing - -#define NTDEVICE_NAME_STRING L"\\Device\\NONPNP" -#define SYMBOLIC_NAME_STRING L"\\DosDevices\\NONPNP" -#define POOL_TAG 'ELIF' - -typedef struct _CONTROL_DEVICE_EXTENSION { - - HANDLE FileHandle; // Store your control data here - -} CONTROL_DEVICE_EXTENSION, *PCONTROL_DEVICE_EXTENSION; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CONTROL_DEVICE_EXTENSION, - ControlGetData) - -// -// Following request context is used only for the method-neither ioctl case. -// -typedef struct _REQUEST_CONTEXT { - - WDFMEMORY InputMemoryBuffer; - WDFMEMORY OutputMemoryBuffer; - -} REQUEST_CONTEXT, *PREQUEST_CONTEXT; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, GetRequestContext) - -// -// Device driver routine declarations. -// - -DRIVER_INITIALIZE DriverEntry; - -// -// Don't use EVT_WDF_DRIVER_DEVICE_ADD for NonPnpDeviceAdd even though -// the signature is same because this is not an event called by the -// framework. -// -NTSTATUS -NonPnpDeviceAdd( - IN WDFDRIVER Driver, - IN PWDFDEVICE_INIT DeviceInit - ); - -EVT_WDF_DRIVER_UNLOAD NonPnpEvtDriverUnload; - -EVT_WDF_DEVICE_CONTEXT_CLEANUP NonPnpEvtDriverContextCleanup; -EVT_WDF_DEVICE_SHUTDOWN_NOTIFICATION NonPnpShutdown; - -EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL FileEvtIoDeviceControl; -EVT_WDF_IO_QUEUE_IO_READ FileEvtIoRead; -EVT_WDF_IO_QUEUE_IO_WRITE FileEvtIoWrite; - -EVT_WDF_IO_IN_CALLER_CONTEXT NonPnpEvtDeviceIoInCallerContext; -EVT_WDF_DEVICE_FILE_CREATE NonPnpEvtDeviceFileCreate; -EVT_WDF_FILE_CLOSE NonPnpEvtFileClose; - -VOID -PrintChars( - _In_reads_(CountChars) PCHAR BufferAddress, - _In_ size_t CountChars - ); - -#pragma warning(disable:4127) - diff --git a/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.rc b/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.rc deleted file mode 100644 index cac68f7b2..000000000 --- a/tests/projects/wdk/kmdf/ioctl/driver/nonpnp.rc +++ /dev/null @@ -1,10 +0,0 @@ -#include - -#include - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_SYSTEM -#define VER_FILEDESCRIPTION_STR "Sample Non-PNP Driver using WDF" -#define VER_INTERNALNAME_STR "NONPNP.sys" - -#include "common.ver" diff --git a/tests/projects/wdk/kmdf/ioctl/driver/trace.h b/tests/projects/wdk/kmdf/ioctl/driver/trace.h deleted file mode 100644 index 089f213f0..000000000 --- a/tests/projects/wdk/kmdf/ioctl/driver/trace.h +++ /dev/null @@ -1,68 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - TRACE.h - -Abstract: - - Header file for the debug tracing related function defintions and macros. - -Environment: - - Kernel mode - ---*/ - -// -// If software tracing is defined in the sources file.. -// WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver. -// *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID *** -// WPP_DEFINE_BIT allows setting debug bit masks to selectively print. -// The names defined in the WPP_DEFINE_BIT call define the actual names -// that are used to control the level of tracing for the control guid -// specified. -// -// {71ae54db-0862-41bf-a24f-5330cec3c7f6} -// -#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings - -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID( FileIoTraceGuid, \ - (71ae54db,0862,41bf,a24f,5330cec3c7f6), \ - WPP_DEFINE_BIT(DBG_INIT) \ - WPP_DEFINE_BIT(DBG_RW) \ - WPP_DEFINE_BIT(DBG_IOCTL) \ - ) - -#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) -#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) - -#pragma warning(disable:4204) // C4204 nonstandard extension used : non-constant aggregate initializer - -// -// Define the 'xstr' structure for logging buffer and length pairs -// and the 'log_xstr' function which returns it to create one in-place. -// this enables logging of complex data types. -// -typedef struct xstr { char * _buf; short _len; } xstr_t; -__inline xstr_t log_xstr(void * p, short l) { xstr_t xs = {(char*)p,l}; return xs; } - -#pragma warning(default:4204) - -// -// Define the macro required for a hexdump use as: -// -// Hexdump((FLAG,"%!HEXDUMP!\n", log_xstr(buffersize,(char *)buffer) )); -// -// -#define WPP_LOGHEXDUMP(x) WPP_LOGPAIR(2, &((x)._len)) WPP_LOGPAIR((x)._len, (x)._buf) - - diff --git a/tests/projects/wdk/kmdf/ioctl/exe/install.c b/tests/projects/wdk/kmdf/ioctl/exe/install.c deleted file mode 100644 index 53d1f7678..000000000 --- a/tests/projects/wdk/kmdf/ioctl/exe/install.c +++ /dev/null @@ -1,812 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - install.c - -Abstract: - - Win32 routines to dynamically load and unload a Windows NT kernel-mode - driver using the Service Control Manager APIs. - -Environment: - - User mode only - ---*/ - - -#include -_Analysis_mode_(_Analysis_code_type_user_code_) - -#include -#include -#include -#include -#include -#include "public.h" - -#include - -#define ARRAY_SIZE(x) (sizeof(x) /sizeof(x[0])) - -extern -PCHAR -GetCoinstallerVersion( - VOID - ) ; - -BOOLEAN -InstallDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName, - IN LPCTSTR ServiceExe - ); - - -BOOLEAN -RemoveDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName - ); - -BOOLEAN -StartDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName - ); - -BOOLEAN -StopDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName - ); - -#define SYSTEM32_DRIVERS "\\System32\\Drivers\\" -#define NONPNP_INF_FILENAME L"\\nonpnp.inf" -#define WDF_SECTION_NAME L"nonpnp.NT.Wdf" - -//---------------------------------------------------------------------------- -// -//---------------------------------------------------------------------------- -PFN_WDFPREDEVICEINSTALLEX pfnWdfPreDeviceInstallEx; -PFN_WDFPOSTDEVICEINSTALL pfnWdfPostDeviceInstall; -PFN_WDFPREDEVICEREMOVE pfnWdfPreDeviceRemove; -PFN_WDFPOSTDEVICEREMOVE pfnWdfPostDeviceRemove; - -//----------------------------------------------------------------------------- -// 4127 -- Conditional Expression is Constant warning -//----------------------------------------------------------------------------- -#define WHILE(a) \ -__pragma(warning(suppress:4127)) while(a) - -LONG -GetPathToInf( - _Out_writes_(InfFilePathSize) PWCHAR InfFilePath, - IN ULONG InfFilePathSize - ) -{ - LONG error = ERROR_SUCCESS; - - if (GetCurrentDirectoryW(InfFilePathSize, InfFilePath) == 0) { - error = GetLastError(); - printf("InstallDriver failed! Error = %d \n", error); - return error; - } - if (FAILED( StringCchCatW(InfFilePath, - InfFilePathSize, - NONPNP_INF_FILENAME) )) { - error = ERROR_BUFFER_OVERFLOW; - return error; - } - return error; - -} - -//---------------------------------------------------------------------------- -// -//---------------------------------------------------------------------------- -BOOLEAN -InstallDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName, - IN LPCTSTR ServiceExe - ) -/*++ - -Routine Description: - -Arguments: - -Return Value: - ---*/ -{ - SC_HANDLE schService; - DWORD err; - WCHAR infPath[MAX_PATH]; - WDF_COINSTALLER_INSTALL_OPTIONS clientOptions; - - WDF_COINSTALLER_INSTALL_OPTIONS_INIT(&clientOptions); - - // - // NOTE: This creates an entry for a standalone driver. If this - // is modified for use with a driver that requires a Tag, - // Group, and/or Dependencies, it may be necessary to - // query the registry for existing driver information - // (in order to determine a unique Tag, etc.). - // - // - // PRE-INSTALL for WDF support - // - err = GetPathToInf(infPath, ARRAY_SIZE(infPath) ); - if (err != ERROR_SUCCESS) { - return FALSE; - } - err = pfnWdfPreDeviceInstallEx(infPath, WDF_SECTION_NAME, &clientOptions); - - if (err != ERROR_SUCCESS) { - if (err == ERROR_SUCCESS_REBOOT_REQUIRED) { - printf("System needs to be rebooted, before the driver installation can proceed.\n"); - } - - return FALSE; - } - - // - // Create a new a service object. - // - - schService = CreateService(SchSCManager, // handle of service control manager database - DriverName, // address of name of service to start - DriverName, // address of display name - SERVICE_ALL_ACCESS, // type of access to service - SERVICE_KERNEL_DRIVER, // type of service - SERVICE_DEMAND_START, // when to start service - SERVICE_ERROR_NORMAL, // severity if service fails to start - ServiceExe, // address of name of binary file - NULL, // service does not belong to a group - NULL, // no tag requested - NULL, // no dependency names - NULL, // use LocalSystem account - NULL // no password for service account - ); - - if (schService == NULL) { - - err = GetLastError(); - - if (err == ERROR_SERVICE_EXISTS) { - - // - // Ignore this error. - // - - return TRUE; - - } else { - - printf("CreateService failed! Error = %d \n", err ); - - // - // Indicate an error. - // - - return FALSE; - } - } - - // - // Close the service object. - // - CloseServiceHandle(schService); - - // - // POST-INSTALL for WDF support - // - err = pfnWdfPostDeviceInstall( infPath, WDF_SECTION_NAME ); - - if (err != ERROR_SUCCESS) { - return FALSE; - } - - // - // Indicate success. - // - - return TRUE; - -} // InstallDriver - -BOOLEAN -ManageDriver( - IN LPCTSTR DriverName, - IN LPCTSTR ServiceName, - IN USHORT Function - ) -{ - - SC_HANDLE schSCManager; - - BOOLEAN rCode = TRUE; - - // - // Insure (somewhat) that the driver and service names are valid. - // - - if (!DriverName || !ServiceName) { - - printf("Invalid Driver or Service provided to ManageDriver() \n"); - - return FALSE; - } - - // - // Connect to the Service Control Manager and open the Services database. - // - - schSCManager = OpenSCManager(NULL, // local machine - NULL, // local database - SC_MANAGER_ALL_ACCESS // access required - ); - - if (!schSCManager) { - - printf("Open SC Manager failed! Error = %d \n", GetLastError()); - - return FALSE; - } - - // - // Do the requested function. - // - - switch( Function ) { - - case DRIVER_FUNC_INSTALL: - - // - // Install the driver service. - // - - if (InstallDriver(schSCManager, - DriverName, - ServiceName - )) { - - // - // Start the driver service (i.e. start the driver). - // - - rCode = StartDriver(schSCManager, - DriverName - ); - - } else { - - // - // Indicate an error. - // - - rCode = FALSE; - } - - break; - - case DRIVER_FUNC_REMOVE: - - // - // Stop the driver. - // - - StopDriver(schSCManager, - DriverName - ); - - // - // Remove the driver service. - // - - RemoveDriver(schSCManager, - DriverName - ); - - // - // Ignore all errors. - // - - rCode = TRUE; - - break; - - default: - - printf("Unknown ManageDriver() function. \n"); - - rCode = FALSE; - - break; - } - - // - // Close handle to service control manager. - // - CloseServiceHandle(schSCManager); - - return rCode; - -} // ManageDriver - - -BOOLEAN -RemoveDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName - ) -{ - SC_HANDLE schService; - BOOLEAN rCode; - DWORD err; - WCHAR infPath[MAX_PATH]; - - err = GetPathToInf(infPath, ARRAY_SIZE(infPath) ); - if (err != ERROR_SUCCESS) { - return FALSE; - } - - // - // PRE-REMOVE of WDF support - // - err = pfnWdfPreDeviceRemove( infPath, WDF_SECTION_NAME ); - - if (err != ERROR_SUCCESS) { - return FALSE; - } - - // - // Open the handle to the existing service. - // - - schService = OpenService(SchSCManager, - DriverName, - SERVICE_ALL_ACCESS - ); - - if (schService == NULL) { - - printf("OpenService failed! Error = %d \n", GetLastError()); - - // - // Indicate error. - // - - return FALSE; - } - - // - // Mark the service for deletion from the service control manager database. - // - - if (DeleteService(schService)) { - - // - // Indicate success. - // - - rCode = TRUE; - - } else { - - printf("DeleteService failed! Error = %d \n", GetLastError()); - - // - // Indicate failure. Fall through to properly close the service handle. - // - - rCode = FALSE; - } - - // - // Close the service object. - // - CloseServiceHandle(schService); - - // - // POST-REMOVE of WDF support - // - err = pfnWdfPostDeviceRemove(infPath, WDF_SECTION_NAME ); - - if (err != ERROR_SUCCESS) { - rCode = FALSE; - } - - return rCode; - -} // RemoveDriver - - - -BOOLEAN -StartDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName - ) -{ - SC_HANDLE schService; - DWORD err; - BOOL ok; - - // - // Open the handle to the existing service. - // - schService = OpenService(SchSCManager, - DriverName, - SERVICE_ALL_ACCESS - ); - - if (schService == NULL) { - // - // Indicate failure. - // - printf("OpenService failed! Error = %d\n", GetLastError()); - return FALSE; - } - - // - // Start the execution of the service (i.e. start the driver). - // - ok = StartService( schService, 0, NULL ); - - if (!ok) { - - err = GetLastError(); - - if (err == ERROR_SERVICE_ALREADY_RUNNING) { - // - // Ignore this error. - // - return TRUE; - - } else { - // - // Indicate failure. - // Fall through to properly close the service handle. - // - printf("StartService failure! Error = %d\n", err ); - return FALSE; - } - } - - // - // Close the service object. - // - CloseServiceHandle(schService); - - return TRUE; - -} // StartDriver - - - -BOOLEAN -StopDriver( - IN SC_HANDLE SchSCManager, - IN LPCTSTR DriverName - ) -{ - BOOLEAN rCode = TRUE; - SC_HANDLE schService; - SERVICE_STATUS serviceStatus; - - // - // Open the handle to the existing service. - // - - schService = OpenService(SchSCManager, - DriverName, - SERVICE_ALL_ACCESS - ); - - if (schService == NULL) { - - printf("OpenService failed! Error = %d \n", GetLastError()); - - return FALSE; - } - - // - // Request that the service stop. - // - - if (ControlService(schService, - SERVICE_CONTROL_STOP, - &serviceStatus - )) { - - // - // Indicate success. - // - - rCode = TRUE; - - } else { - - printf("ControlService failed! Error = %d \n", GetLastError() ); - - // - // Indicate failure. Fall through to properly close the service handle. - // - - rCode = FALSE; - } - - // - // Close the service object. - // - CloseServiceHandle (schService); - - return rCode; - -} // StopDriver - - -// -// Caller must free returned pathname string. -// -PCHAR -BuildDriversDirPath( - _In_ PSTR DriverName - ) -{ - size_t remain; - size_t len; - PCHAR dir; - - if (!DriverName || strlen(DriverName) == 0) { - return NULL; - } - - remain = MAX_PATH; - - // - // Allocate string space - // - dir = (PCHAR) malloc( remain + 1 ); - - if (!dir) { - return NULL; - } - - // - // Get the base windows directory path. - // - len = GetWindowsDirectory( dir, (UINT) remain ); - - if (len == 0 || - (remain - len) < sizeof(SYSTEM32_DRIVERS)) { - free(dir); - return NULL; - } - remain -= len; - - // - // Build dir to have "%windir%\System32\Drivers\". - // - if (FAILED( StringCchCat(dir, remain, SYSTEM32_DRIVERS) )) { - free(dir); - return NULL; - } - - remain -= sizeof(SYSTEM32_DRIVERS); - len += sizeof(SYSTEM32_DRIVERS); - len += strlen(DriverName); - - if (remain < len) { - free(dir); - return NULL; - } - - if (FAILED( StringCchCat(dir, remain, DriverName) )) { - free(dir); - return NULL; - } - - dir[len] = '\0'; // keeps prefast happy - - return dir; -} - - -BOOLEAN -SetupDriverName( - _Inout_updates_all_(BufferLength) PCHAR DriverLocation, - _In_ ULONG BufferLength - ) -{ - HANDLE fileHandle; - DWORD driverLocLen = 0; - BOOL ok; - PCHAR driversDir; - - // - // Setup path name to driver file. - // - driverLocLen = - GetCurrentDirectory(BufferLength, DriverLocation); - - if (!driverLocLen) { - - printf("GetCurrentDirectory failed! Error = %d \n", - GetLastError()); - - return FALSE; - } - - if (FAILED( StringCchCat(DriverLocation, BufferLength, "\\" DRIVER_NAME ".sys") )) { - return FALSE; - } - - // - // Insure driver file is in the specified directory. - // - fileHandle = CreateFile( DriverLocation, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (fileHandle == INVALID_HANDLE_VALUE) { - // - // Indicate failure. - // - printf("Driver: %s.SYS is not in the %s directory. \n", - DRIVER_NAME, DriverLocation ); - return FALSE; - } - - // - // Build %windir%\System32\Drivers\ path. - // Copy the driver to %windir%\system32\drivers - // - driversDir = BuildDriversDirPath( DRIVER_NAME ".sys" ); - - if (!driversDir) { - printf("BuildDriversDirPath failed!\n"); - return FALSE; - } - - ok = CopyFile( DriverLocation, driversDir, FALSE ); - - if(!ok) { - printf("CopyFile failed: error(%d) - \"%s\"\n", - GetLastError(), driversDir ); - free(driversDir); - return FALSE; - } - - if (FAILED( StringCchCopy(DriverLocation, BufferLength, driversDir) )) { - free(driversDir); - return FALSE; - } - - free(driversDir); - - // - // Close open file handle. - // - if (fileHandle) { - CloseHandle(fileHandle); - } - - // - // Indicate success. - // - return TRUE; - -} // SetupDriverName - - -HMODULE -LoadWdfCoInstaller( - VOID - ) -{ - HMODULE library = NULL; - DWORD error = ERROR_SUCCESS; - CHAR szCurDir[MAX_PATH]; - CHAR tempCoinstallerName[MAX_PATH]; - PCHAR coinstallerVersion; - - do { - - if (GetCurrentDirectory(MAX_PATH, szCurDir) == 0) { - - printf("GetCurrentDirectory failed! Error = %d \n", GetLastError()); - break; - } - coinstallerVersion = GetCoinstallerVersion(); - if (FAILED( StringCchPrintf(tempCoinstallerName, - MAX_PATH, - "\\WdfCoInstaller%s.dll", - coinstallerVersion) )) { - break; - } - if (FAILED( StringCchCat(szCurDir, MAX_PATH, tempCoinstallerName) )) { - break; - } - - library = LoadLibrary(szCurDir); - - if (library == NULL) { - error = GetLastError(); - printf("LoadLibrary(%s) failed: %d\n", szCurDir, error); - break; - } - - pfnWdfPreDeviceInstallEx = - (PFN_WDFPREDEVICEINSTALLEX) GetProcAddress( library, "WdfPreDeviceInstallEx" ); - - if (pfnWdfPreDeviceInstallEx == NULL) { - error = GetLastError(); - printf("GetProcAddress(\"WdfPreDeviceInstallEx\") failed: %d\n", error); - return NULL; - } - - pfnWdfPostDeviceInstall = - (PFN_WDFPOSTDEVICEINSTALL) GetProcAddress( library, "WdfPostDeviceInstall" ); - - if (pfnWdfPostDeviceInstall == NULL) { - error = GetLastError(); - printf("GetProcAddress(\"WdfPostDeviceInstall\") failed: %d\n", error); - return NULL; - } - - pfnWdfPreDeviceRemove = - (PFN_WDFPREDEVICEREMOVE) GetProcAddress( library, "WdfPreDeviceRemove" ); - - if (pfnWdfPreDeviceRemove == NULL) { - error = GetLastError(); - printf("GetProcAddress(\"WdfPreDeviceRemove\") failed: %d\n", error); - return NULL; - } - - pfnWdfPostDeviceRemove = - (PFN_WDFPREDEVICEREMOVE) GetProcAddress( library, "WdfPostDeviceRemove" ); - - if (pfnWdfPostDeviceRemove == NULL) { - error = GetLastError(); - printf("GetProcAddress(\"WdfPostDeviceRemove\") failed: %d\n", error); - return NULL; - } - - } WHILE (0); - - if (error != ERROR_SUCCESS) { - if (library) { - FreeLibrary( library ); - } - library = NULL; - } - - return library; -} - - -VOID -UnloadWdfCoInstaller( - HMODULE Library - ) -{ - if (Library) { - FreeLibrary( Library ); - } -} - diff --git a/tests/projects/wdk/kmdf/ioctl/exe/nonpnp.inf b/tests/projects/wdk/kmdf/ioctl/exe/nonpnp.inf deleted file mode 100644 index b20a58b48..000000000 --- a/tests/projects/wdk/kmdf/ioctl/exe/nonpnp.inf +++ /dev/null @@ -1,8 +0,0 @@ -[Version] -Signature="$WINDOWS NT$" - -[nonpnp.NT.Wdf] -KmdfService = nonpnp, nonpnp_Service_kmdfInst - -[nonpnp_Service_kmdfInst] -KmdfLibraryVersion = 1.11 diff --git a/tests/projects/wdk/kmdf/ioctl/exe/testapp.c b/tests/projects/wdk/kmdf/ioctl/exe/testapp.c deleted file mode 100644 index c12f26073..000000000 --- a/tests/projects/wdk/kmdf/ioctl/exe/testapp.c +++ /dev/null @@ -1,643 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - - -Module Name: - - testapp.c - -Abstract: - - Purpose of this app to test the NONPNP sample driver. The app - makes four different ioctl calls to test all the buffer types, write - some random buffer content to a file created by the driver in \SystemRoot\Temp - directory, and reads the same file and matches the content. - If -l option is specified, it does the write and read operation in a loop - until the app is terminated by pressing ^C. - - Make sure you have the \SystemRoot\Temp directory exists before you run the test. - -Environment: - - Win32 console application. - ---*/ - - -#include -_Analysis_mode_(_Analysis_code_type_user_code_) - -#include - -#pragma warning(disable:4201) // nameless struct/union -#include -#pragma warning(default:4201) - -#include -#include -#include -#include -#include -#include "public.h" - - -BOOLEAN -ManageDriver( - IN LPCTSTR DriverName, - IN LPCTSTR ServiceName, - IN USHORT Function - ); - -HMODULE -LoadWdfCoInstaller( - VOID - ); - -VOID -UnloadWdfCoInstaller( - HMODULE Library - ); - -BOOLEAN -SetupDriverName( - _Inout_updates_all_(BufferLength) PCHAR DriverLocation, - _In_ ULONG BufferLength - ); - -BOOLEAN -DoFileReadWrite( - HANDLE HDevice - ); - -VOID -DoIoctls( - HANDLE hDevice - ); - -// for example, WDF 1.9 is "01009". the size 6 includes the ending NULL marker -// -#define MAX_VERSION_SIZE 6 - -CHAR G_coInstallerVersion[MAX_VERSION_SIZE] = {0}; -BOOLEAN G_fLoop = FALSE; -BOOL G_versionSpecified = FALSE; - - - -//----------------------------------------------------------------------------- -// 4127 -- Conditional Expression is Constant warning -//----------------------------------------------------------------------------- -#define WHILE(constant) \ -__pragma(warning(disable: 4127)) while(constant); __pragma(warning(default: 4127)) - - -#define USAGE \ -"Usage: nonpnpapp <-V version> <-l> \n" \ - " -V version {if no version is specified the version specified in the build environment will be used.}\n" \ - " The version is the version of the KMDF coinstaller to use \n" \ - " The format of version is MMmmm where MM -- major #, mmm - serial# \n" \ - " -l { option to continuously read & write to the file} \n" - -BOOL -ValidateCoinstallerVersion( - _In_ PSTR Version - ) -{ BOOL ok = FALSE; - INT i; - - for(i= 0; i 1 ) {// give usage if invoked with no parms - error = Parse(argc, argv); - if (error != ERROR_SUCCESS) { - return; - } - } - - if (!G_versionSpecified ) { - coinstallerVersion = GetCoinstallerVersion(); - - // - // if no version is specified or an invalid one is specified use default version - // - printf("No version specified. Using default version:%s\n", - coinstallerVersion); - - } else { - coinstallerVersion = (PCHAR)&G_coInstallerVersion; - } - - // - // open the device - // - hDevice = CreateFile(DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if(hDevice == INVALID_HANDLE_VALUE) { - - errNum = GetLastError(); - - if (!(errNum == ERROR_FILE_NOT_FOUND || - errNum == ERROR_PATH_NOT_FOUND)) { - - printf("CreateFile failed! ERROR_FILE_NOT_FOUND = %d\n", - errNum); - return ; - } - - // - // Load WdfCoInstaller.dll. - // - library = LoadWdfCoInstaller(); - - if (library == NULL) { - printf("The WdfCoInstaller%s.dll library needs to be " - "in same directory as nonpnpapp.exe\n", coinstallerVersion); - return; - } - - // - // The driver is not started yet so let us the install the driver. - // First setup full path to driver name. - // - ok = SetupDriverName( driverLocation, MAX_PATH ); - - if (!ok) { - return ; - } - - ok = ManageDriver( DRIVER_NAME, - driverLocation, - DRIVER_FUNC_INSTALL ); - - if (!ok) { - - printf("Unable to install driver. \n"); - - // - // Error - remove driver. - // - ManageDriver( DRIVER_NAME, - driverLocation, - DRIVER_FUNC_REMOVE ); - return; - } - - hDevice = CreateFile( DEVICE_NAME, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL ); - - if (hDevice == INVALID_HANDLE_VALUE) { - printf ( "Error: CreatFile Failed : %d\n", GetLastError()); - return; - } - } - - DoIoctls(hDevice); - - do { - - if(!DoFileReadWrite(hDevice)) { - break; - } - - if(!G_fLoop) { - break; - } - Sleep(1000); // sleep for 1 sec. - - } WHILE (TRUE); - - // - // Close the handle to the device before unloading the driver. - // - CloseHandle ( hDevice ); - - // - // Unload the driver. Ignore any errors. - // - ManageDriver( DRIVER_NAME, - driverLocation, - DRIVER_FUNC_REMOVE ); - - // - // Unload WdfCoInstaller.dll - // - if ( library ) { - UnloadWdfCoInstaller( library ); - } - return; -} - - -VOID -DoIoctls( - HANDLE hDevice - ) -{ - char OutputBuffer[100]; - char InputBuffer[200]; - BOOL bRc; - ULONG bytesReturned; - - // - // Printing Input & Output buffer pointers and size - // - - printf("InputBuffer Pointer = %p, BufLength = %Id\n", InputBuffer, - sizeof(InputBuffer)); - printf("OutputBuffer Pointer = %p BufLength = %Id\n", OutputBuffer, - sizeof(OutputBuffer)); - // - // Performing METHOD_BUFFERED - // - - if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), - "this String is from User Application; using METHOD_BUFFERED"))){ - return; - } - - printf("\nCalling DeviceIoControl METHOD_BUFFERED:\n"); - - memset(OutputBuffer, 0, sizeof(OutputBuffer)); - - bRc = DeviceIoControl ( hDevice, - (DWORD) IOCTL_NONPNP_METHOD_BUFFERED, - InputBuffer, - (DWORD) strlen( InputBuffer )+1, - OutputBuffer, - sizeof( OutputBuffer), - &bytesReturned, - NULL - ); - - if ( !bRc ) - { - printf ( "Error in DeviceIoControl : %d", GetLastError()); - return; - - } - printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer); - - - // - // Performing METHOD_NIETHER - // - - printf("\nCalling DeviceIoControl METHOD_NEITHER\n"); - - if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), - "this String is from User Application; using METHOD_NEITHER"))) { - return; - } - - memset(OutputBuffer, 0, sizeof(OutputBuffer)); - - bRc = DeviceIoControl ( hDevice, - (DWORD) IOCTL_NONPNP_METHOD_NEITHER, - InputBuffer, - (DWORD) strlen( InputBuffer )+1, - OutputBuffer, - sizeof( OutputBuffer), - &bytesReturned, - NULL - ); - - if ( !bRc ) - { - printf ( "Error in DeviceIoControl : %d\n", GetLastError()); - return; - - } - - printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer); - - // - // Performing METHOD_IN_DIRECT - // - - printf("\nCalling DeviceIoControl METHOD_IN_DIRECT\n"); - - if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), - "this String is from User Application; using METHOD_IN_DIRECT"))) { - return; - } - - if(FAILED(StringCchCopy(OutputBuffer, sizeof(OutputBuffer), - "This String is from User Application in OutBuffer; using METHOD_IN_DIRECT"))) { - return; - } - - bRc = DeviceIoControl ( hDevice, - (DWORD) IOCTL_NONPNP_METHOD_IN_DIRECT, - InputBuffer, - (DWORD) strlen( InputBuffer )+1, - OutputBuffer, - sizeof( OutputBuffer), - &bytesReturned, - NULL - ); - - if ( !bRc ) - { - printf ( "Error in DeviceIoControl : : %d", GetLastError()); - return; - } - - printf(" Number of bytes transfered from OutBuffer: %d\n", - bytesReturned); - - // - // Performing METHOD_OUT_DIRECT - // - - printf("\nCalling DeviceIoControl METHOD_OUT_DIRECT\n"); - if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), - "this String is from User Application; using METHOD_OUT_DIRECT"))){ - return; - } - - memset(OutputBuffer, 0, sizeof(OutputBuffer)); - - bRc = DeviceIoControl ( hDevice, - (DWORD) IOCTL_NONPNP_METHOD_OUT_DIRECT, - InputBuffer, - (DWORD) strlen( InputBuffer )+1, - OutputBuffer, - sizeof( OutputBuffer), - &bytesReturned, - NULL - ); - - if ( !bRc ) - { - printf ( "Error in DeviceIoControl : : %d", GetLastError()); - return; - } - - printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer); - - return; - -} - - -BOOLEAN -DoFileReadWrite( - HANDLE HDevice - ) -{ - ULONG bufLength, index; - PUCHAR readBuf = NULL; - PUCHAR writeBuf = NULL; - BOOLEAN ret; - ULONG bytesWritten, bytesRead; - - // - // Seed the random-number generator with current time so that - // the numbers will be different every time we run. - // - srand( (unsigned)time( NULL ) ); - - // - // rand function returns a pseudorandom integer in the range 0 to RAND_MAX - // (0x7fff) - // - bufLength = rand(); - // - // Try until the bufLength is not zero. - // - while(bufLength == 0) { - bufLength = rand(); - } - - // - // Allocate a buffer of that size to use for write operation. - // - writeBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufLength); - if(!writeBuf) { - ret = FALSE; - goto End; - } - // - // Fill the buffer with randon number less than UCHAR_MAX. - // - index = bufLength; - while(index){ - writeBuf[index-1] = (UCHAR) rand() % UCHAR_MAX; - index--; - } - - printf("Write %d bytes to file\n", bufLength); - - // - // Tell the driver to write the buffer content to the file from the - // begining of the file. - // - - if (!WriteFile(HDevice, - writeBuf, - bufLength, - &bytesWritten, - NULL)) { - - printf("ReadFile failed with error 0x%x\n", GetLastError()); - - ret = FALSE; - goto End; - - } - - // - // Allocate another buffer of same size. - // - readBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufLength); - if(!readBuf) { - - ret = FALSE; - goto End; - } - - printf("Read %d bytes from the same file\n", bufLength); - - // - // Tell the driver to read the file from the begining. - // - if (!ReadFile(HDevice, - readBuf, - bufLength, - &bytesRead, - NULL)) { - - printf("Error: ReadFile failed with error 0x%x\n", GetLastError()); - - ret = FALSE; - goto End; - - } - - // - // Now compare the readBuf and writeBuf content. They should be the same. - // - - if(bytesRead != bytesWritten) { - printf("bytesRead(%d) != bytesWritten(%d)\n", bytesRead, bytesWritten); - ret = FALSE; - goto End; - } - - if(memcmp(readBuf, writeBuf, bufLength) != 0){ - printf("Error: ReadBuf and WriteBuf contents are not the same\n"); - ret = FALSE; - goto End; - } - - ret = TRUE; - -End: - - if(readBuf){ - HeapFree (GetProcessHeap(), 0, readBuf); - } - - if(writeBuf){ - HeapFree (GetProcessHeap(), 0, writeBuf); - } - - return ret; - - -} - - diff --git a/tests/projects/wdk/kmdf/ioctl/localwpp.ini b/tests/projects/wdk/kmdf/ioctl/localwpp.ini deleted file mode 100644 index c290070a7..000000000 --- a/tests/projects/wdk/kmdf/ioctl/localwpp.ini +++ /dev/null @@ -1,17 +0,0 @@ -// -// This defines how to log a len/buffer pair. -// This function should be in trace.h -// - -DEFINE_CPLX_TYPE(HEXDUMP, WPP_LOGHEXDUMP, xstr_t, ItemHEXDump,"s", _HEX_, 0,2); - -// DEFINE_CPLX_TYPE( -// name, // i.e. HEXDUMP // %!HEXDUMP! -// macro, // i.e. WPP_LOGHEXDUMP // Marshalling macro, defined in trace.h -// structure, // i.e. xstr_t // Argument type (structure to be created by above macro) -// item type, // i.e. ItemHEXDump // MOF type that TracePrt can understand -// format specifier, // i.e. "s" // a format specifier that TracePrt can understand -// ???? // i.e. _HEX_ // Type signature (becomes a part of function name) -// ???? // i.e. 0 // Weight (0 is variable data length) -// ???? // i.e. 2 // Slots used by this entry (optional, 1 default) -// ) diff --git a/tests/projects/wdk/kmdf/ioctl/public.h b/tests/projects/wdk/kmdf/ioctl/public.h deleted file mode 100644 index 02e24be2e..000000000 --- a/tests/projects/wdk/kmdf/ioctl/public.h +++ /dev/null @@ -1,53 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - - -Module Name: - - PUBLIC.H - -Abstract: - - - Defines the IOCTL codes that will be used by this driver. The IOCTL code - contains a command identifier, plus other information about the device, - the type of access with which the file must have been opened, - and the type of buffering. - -Environment: - - Kernel mode only. - ---*/ - -// -// Device type -- in the "User Defined" range." -// -#define FILEIO_TYPE 40001 -// -// The IOCTL function codes from 0x800 to 0xFFF are for customer use. -// -#define IOCTL_NONPNP_METHOD_IN_DIRECT \ - CTL_CODE( FILEIO_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS ) - -#define IOCTL_NONPNP_METHOD_OUT_DIRECT \ - CTL_CODE( FILEIO_TYPE, 0x901, METHOD_OUT_DIRECT , FILE_ANY_ACCESS ) - -#define IOCTL_NONPNP_METHOD_BUFFERED \ - CTL_CODE( FILEIO_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS ) - -#define IOCTL_NONPNP_METHOD_NEITHER \ - CTL_CODE( FILEIO_TYPE, 0x903, METHOD_NEITHER , FILE_ANY_ACCESS ) - - -#define DRIVER_FUNC_INSTALL 0x01 -#define DRIVER_FUNC_REMOVE 0x02 - -#define DRIVER_NAME "NONPNP" -#define DEVICE_NAME "\\\\.\\NONPNP\\nonpnpsamp.log" diff --git a/tests/projects/wdk/kmdf/ioctl/xmake.lua b/tests/projects/wdk/kmdf/ioctl/xmake.lua deleted file mode 100644 index 9cbaf0b5f..000000000 --- a/tests/projects/wdk/kmdf/ioctl/xmake.lua +++ /dev/null @@ -1,15 +0,0 @@ -add_rules("mode.debug", "mode.release") - -add_includedirs(".") - -target("nonpnp") - add_rules("wdk.env.kmdf", "wdk.driver") - add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)", "-func:Hexdump((LEVEL,FLAGS,MSG,...))") - add_files("driver/*.c", {rule = "wdk.tracewpp"}) - add_files("driver/*.rc") - -target("app") - add_rules("wdk.env.kmdf", "wdk.binary") - add_files("exe/*.c") - add_files("exe/*.inf") - diff --git a/tests/projects/wdk/kmdf/serial/error.c b/tests/projects/wdk/kmdf/serial/error.c deleted file mode 100644 index 904e54b05..000000000 --- a/tests/projects/wdk/kmdf/serial/error.c +++ /dev/null @@ -1,67 +0,0 @@ -/*++ -Copyright (c) Microsoft Corporation - -Module Name: - - error.c - -Abstract: - - This module contains the code that is very specific to error - operations in the serial driver - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "error.tmh" -#endif - - -VOID -SerialCommError( - IN WDFDPC Dpc - ) -/*++ - -Routine Description: - - This routine is invoked at dpc level to in response to - a comm error. All comm errors complete all read and writes - -Arguments: - - -Return Value: - - None. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, - ">SerialCommError(%p)\n", Extension); - - SerialFlushRequests( - Extension->WriteQueue, - &Extension->CurrentWriteRequest - ); - - SerialFlushRequests( - Extension->ReadQueue, - &Extension->CurrentReadRequest - ); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, - "SerialFlush(%p, %p)\n", Device, Irp); - - PAGED_CODE(); - - WdfIoQueueStopSynchronously(extension->WriteQueue); - // - // Flush is done - restart the queue - // - WdfIoQueueStart(extension->WriteQueue); - - Irp->IoStatus.Information = 0L; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "CurrentImmediateRequest); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, ">SerialStartImmediate(%p)\n", - Extension); - - UseATimer = FALSE; - reqContext->Status = STATUS_PENDING; - - // - // Calculate the timeout value needed for the - // request. Note that the values stored in the - // timeout record are in milliseconds. Note that - // if the timeout values are zero then we won't start - // the timer. - // - - Timeouts = Extension->Timeouts; - - if (Timeouts.WriteTotalTimeoutConstant || - Timeouts.WriteTotalTimeoutMultiplier) { - - UseATimer = TRUE; - - // - // We have some timer values to calculate. - // - - TotalTime.QuadPart - = (LONGLONG)((ULONG)Timeouts.WriteTotalTimeoutMultiplier); - - TotalTime.QuadPart += Timeouts.WriteTotalTimeoutConstant; - - TotalTime.QuadPart *= -10000; - - } - - // - // As the request might be going to the isr, this is a good time - // to initialize the reference count. - // - - SERIAL_INIT_REFERENCE(reqContext); - - // - // We give the request to to the isr to write out. - // We set a cancel routine that knows how to - // grab the current write away from the isr. - // - SerialSetCancelRoutine(Extension->CurrentImmediateRequest, - SerialCancelImmediate); - - if (UseATimer) { - BOOLEAN result; - - result = SerialSetTimer( - Extension->ImmediateTotalTimer, - TotalTime - ); - - if(result == FALSE) { - // - // Since the timer knows about the request we increment - // the reference count. - // - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_TOTAL_TIMER - ); - } - } - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGiveImmediateToIsr, - Extension - ); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "SerialCompleteImmediate(%p)\n", - Extension); - - SerialTryToCompleteCurrent( - Extension, - NULL, - STATUS_SUCCESS, - &Extension->CurrentImmediateRequest, - NULL, - NULL, - Extension->ImmediateTotalTimer, - NULL, - SerialGetNextImmediate, - SERIAL_REF_ISR - ); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "SerialTimeoutImmediate(%p)\n", - Extension); - - SerialTryToCompleteCurrent( - Extension, - SerialGrabImmediateFromIsr, - STATUS_TIMEOUT, - &Extension->CurrentImmediateRequest, - NULL, - NULL, - Extension->ImmediateTotalTimer, - NULL, - SerialGetNextImmediate, - SERIAL_REF_TOTAL_TIMER - ); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "TotalCharsQueued >= 1); - Extension->TotalCharsQueued--; - - *CurrentOpRequest = NULL; - *NewRequest = NULL; - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialProcessEmptyTransmit, - Extension - ); - - SerialCompleteRequest(oldRequest, reqContext->Status, reqContext->Information); -} - -VOID -SerialCancelImmediate( - IN WDFREQUEST Request - ) - -/*++ - -Routine Description: - - This routine is used to cancel a request that is waiting on - a comm event. - -Arguments: - - Request - Pointer to the WDFREQUEST for the current request - -Return Value: - - None. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = NULL; - WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); - - UNREFERENCED_PARAMETER(Request); - - Extension = SerialGetDeviceExtension(device); - - SerialTryToCompleteCurrent( - Extension, - SerialGrabImmediateFromIsr, - STATUS_CANCELLED, - &Extension->CurrentImmediateRequest, - NULL, - NULL, - Extension->ImmediateTotalTimer, - NULL, - SerialGetNextImmediate, - SERIAL_REF_CANCEL - ); - -} - -BOOLEAN -SerialGiveImmediateToIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) -/*++ - -Routine Description: - - Try to start off the write by slipping it in behind - a transmit immediate char, or if that isn't available - and the transmit holding register is empty, "tickle" - the UART into interrupting with a transmit buffer - empty. - - NOTE: This routine is called by WdfInterruptSynchronize. - - NOTE: This routine assumes that it is called with the - cancel spin lock held. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION Extension = Context; - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentImmediateRequest); - - Extension->TransmitImmediate = TRUE; - Extension->ImmediateChar = *((UCHAR *) (reqContext->SystemBuffer)); - - // - // The isr now has a reference to the request. - // - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - // - // Check first to see if a write is going on. If - // there is then we'll just slip in during the write. - // - - if (!Extension->WriteLength) { - - // - // If there is no normal write transmitting then we - // will "re-enable" the transmit holding register empty - // interrupt. The 8250 family of devices will always - // signal a transmit holding register empty interrupt - // *ANY* time this bit is set to one. By doing things - // this way we can simply use the normal interrupt code - // to start off this write. - // - // We've been keeping track of whether the transmit holding - // register is empty so it we only need to do this - // if the register is empty. - // - - if (Extension->HoldingEmpty) { - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - - } - - } - - return FALSE; - -} - -BOOLEAN -SerialGrabImmediateFromIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - - This routine is used to grab the current request, which could be timing - out or canceling, from the ISR - - NOTE: This routine is being called from WdfInterruptSynchronize. - - NOTE: This routine assumes that the cancel spin lock is held - when this routine is called. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - Always false. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = Context; - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentImmediateRequest); - - if (Extension->TransmitImmediate) { - - Extension->TransmitImmediate = FALSE; - - // - // Since the isr no longer references this request, we can - // decrement it's reference count. - // - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - } - - return FALSE; - -} - - diff --git a/tests/projects/wdk/kmdf/serial/initunlo.c b/tests/projects/wdk/kmdf/serial/initunlo.c deleted file mode 100644 index 07e7fb003..000000000 --- a/tests/projects/wdk/kmdf/serial/initunlo.c +++ /dev/null @@ -1,197 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - initunlo.c - -Abstract: - - This module contains the code that is very specific to initialization - and unload operations in the serial driver - - WDF Version of serial sample doesn't support: - 1) Multiport Serial devices. - 2) Enumeration of Non PNP serial devices that are not detected by BIOS - (IO address range 0x2F0-0x2F7 using IRQ 9) -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "initunlo.tmh" -#endif - -static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; - -// -// We use this to query into the registry as to whether we -// should break at driver entry. -// - -SERIAL_FIRMWARE_DATA driverDefaults; - -// -// This is exported from the kernel. It is used to point -// to the address that the kernel debugger is using. -// -extern PUCHAR *KdComPortInUse; -// -// INIT - only needed during init and then can be disposed -// PAGESRP0 - always paged / never locked -// PAGESER - must be locked when a device is open, else paged -// -// -// INIT is used for DriverEntry() specific code -// -// PAGESRP0 is used for code that is not often called and has nothing -// to do with I/O performance. An example, passive-level PNP -// support functions -// -// PAGESER is used for code that needs to be locked after an open for both -// performance and IRQL reasons. -// - -ULONG DebugLevel = TRACE_LEVEL_INFORMATION; -ULONG DebugFlag = 0xf;//0x46;//0x4FF; //0x00000006; - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(INIT, DriverEntry) -#pragma alloc_text(PAGE, SerialEvtDriverContextCleanup) -#endif - - - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - - The entry point that the system point calls to initialize - any driver. - -Arguments: - - DriverObject - Just what it says, really of little use - to the driver itself, it is something that the IO system - cares more about. - - PathToRegistry - points to the entry for this driver - in the current control set of the registry. - -Return Value: - - Always STATUS_SUCCESS - ---*/ - -{ - WDF_DRIVER_CONFIG config; - WDFDRIVER hDriver; - NTSTATUS status; - WDF_OBJECT_ATTRIBUTES attributes; - - // - // Initialize WPP Tracing - // - WPP_INIT_TRACING( DriverObject, RegistryPath ); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, - "Serial Sample (WDF Version)\n"); - // - // Register a cleanup callback so that we can call WPP_CLEANUP when - // the framework driver object is deleted during driver unload. - // - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.EvtCleanupCallback = SerialEvtDriverContextCleanup; - - WDF_DRIVER_CONFIG_INIT(&config, SerialEvtDeviceAdd); - - status = WdfDriverCreate(DriverObject, - RegistryPath, - &attributes, - &config, - &hDriver); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_INIT, - "WdfDriverCreate failed with status 0x%x\n", - status); - // - // Cleanup tracing here because DriverContextCleanup will not be called - // as we have failed to create WDFDRIVER object itself. - // Please note that if your return failure from DriverEntry after the - // WDFDRIVER object is created successfully, you don't have to - // call WPP cleanup because in those cases DriverContextCleanup - // will be executed when the framework deletes the DriverObject. - // - WPP_CLEANUP(DriverObject); - return status; - } - - // - // Call to find out default values to use for all the devices that the - // driver controls, including whether or not to break on entry. - // - - SerialGetConfigDefaults(&driverDefaults, hDriver); - - // - // Break on entry if requested via registry - // - if (driverDefaults.ShouldBreakOnEntry) { - DbgBreakPoint(); - } - - - return status; -} - - -_Use_decl_annotations_ -VOID -SerialEvtDriverContextCleanup( - WDFOBJECT Driver - ) -/*++ -Routine Description: - - Free all the resources allocated in DriverEntry. - -Arguments: - - Driver - handle to a WDF Driver object. - -Return Value: - - VOID. - ---*/ -{ - UNREFERENCED_PARAMETER(Driver); - - PAGED_CODE (); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, - "--> SerialEvtDriverContextCleanup\n"); - - // - // Stop WPP Tracing - // - WPP_CLEANUP( WdfDriverWdmGetDriverObject(Driver) ); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, - "<-- SerialEvtDriverContextCleanup\n"); - -} - - - diff --git a/tests/projects/wdk/kmdf/serial/ioctl.c b/tests/projects/wdk/kmdf/serial/ioctl.c deleted file mode 100644 index 07ff2b147..000000000 --- a/tests/projects/wdk/kmdf/serial/ioctl.c +++ /dev/null @@ -1,2187 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - ioctl.c - -Abstract: - - This module contains the ioctl dispatcher as well as a couple - of routines that are generally just called in response to - ioctl calls. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "ioctl.tmh" -#endif - -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetModemUpdate; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetCommStatus; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetEscapeChar; - -PCHAR -SerialGetIoctlName( - IN ULONG IoControlCode - ) -/*++ - -Routine Description: - SerialGetIoctlName returns the name of the ioctl - ---*/ -{ - switch (IoControlCode) - { - case IOCTL_SERIAL_SET_BAUD_RATE : return "IOCTL_SERIAL_SET_BAUD_RATE"; - case IOCTL_SERIAL_GET_BAUD_RATE: return "IOCTL_SERIAL_GET_BAUD_RATE"; - case IOCTL_SERIAL_GET_MODEM_CONTROL: return "IOCTL_SERIAL_GET_MODEM_CONTROL"; - case IOCTL_SERIAL_SET_MODEM_CONTROL: return "IOCTL_SERIAL_SET_MODEM_CONTROL"; - case IOCTL_SERIAL_SET_FIFO_CONTROL: return "IOCTL_SERIAL_SET_FIFO_CONTROL"; - case IOCTL_SERIAL_SET_LINE_CONTROL: return "IOCTL_SERIAL_SET_LINE_CONTROL"; - case IOCTL_SERIAL_GET_LINE_CONTROL: return "IOCTL_SERIAL_GET_LINE_CONTROL"; - case IOCTL_SERIAL_SET_TIMEOUTS: return "IOCTL_SERIAL_SET_TIMEOUTS"; - case IOCTL_SERIAL_GET_TIMEOUTS: return "IOCTL_SERIAL_GET_TIMEOUTS"; - case IOCTL_SERIAL_SET_CHARS: return "IOCTL_SERIAL_SET_CHARS"; - case IOCTL_SERIAL_GET_CHARS: return "IOCTL_SERIAL_GET_CHARS"; - case IOCTL_SERIAL_SET_DTR: return "IOCTL_SERIAL_SET_DTR"; - case IOCTL_SERIAL_CLR_DTR: return "IOCTL_SERIAL_SET_DTR"; - case IOCTL_SERIAL_RESET_DEVICE: return "IOCTL_SERIAL_RESET_DEVICE"; - case IOCTL_SERIAL_SET_RTS: return "IOCTL_SERIAL_SET_RTS"; - case IOCTL_SERIAL_CLR_RTS: return "IOCTL_SERIAL_CLR_RTS"; - case IOCTL_SERIAL_SET_XOFF: return "IOCTL_SERIAL_SET_XOFF"; - case IOCTL_SERIAL_SET_XON: return "IOCTL_SERIAL_SET_XON"; - case IOCTL_SERIAL_SET_BREAK_ON: return "IOCTL_SERIAL_SET_BREAK_ON"; - case IOCTL_SERIAL_SET_BREAK_OFF: return "IOCTL_SERIAL_SET_BREAK_OFF"; - case IOCTL_SERIAL_SET_QUEUE_SIZE: return "IOCTL_SERIAL_SET_QUEUE_SIZE"; - case IOCTL_SERIAL_GET_WAIT_MASK: return "IOCTL_SERIAL_GET_WAIT_MASK"; - case IOCTL_SERIAL_SET_WAIT_MASK: return "IOCTL_SERIAL_SET_WAIT_MASK"; - case IOCTL_SERIAL_WAIT_ON_MASK: return "IOCTL_SERIAL_WAIT_ON_MASK"; - case IOCTL_SERIAL_IMMEDIATE_CHAR: return "IOCTL_SERIAL_IMMEDIATE_CHAR"; - case IOCTL_SERIAL_PURGE: return "IOCTL_SERIAL_PURGE"; - case IOCTL_SERIAL_GET_HANDFLOW: return "IOCTL_SERIAL_GET_HANDFLOW"; - case IOCTL_SERIAL_SET_HANDFLOW: return "IOCTL_SERIAL_SET_HANDFLOW"; - case IOCTL_SERIAL_GET_MODEMSTATUS: return "IOCTL_SERIAL_GET_MODEMSTATUS"; - case IOCTL_SERIAL_GET_DTRRTS: return "IOCTL_SERIAL_GET_DTRRTS"; - case IOCTL_SERIAL_GET_COMMSTATUS: return "IOCTL_SERIAL_GET_COMMSTATUS"; - case IOCTL_SERIAL_GET_PROPERTIES: return "IOCTL_SERIAL_GET_PROPERTIES"; - case IOCTL_SERIAL_XOFF_COUNTER: return "IOCTL_SERIAL_XOFF_COUNTER"; - case IOCTL_SERIAL_LSRMST_INSERT: return "IOCTL_SERIAL_LSRMST_INSERT"; - case IOCTL_SERIAL_CONFIG_SIZE: return "IOCTL_SERIAL_CONFIG_SIZE"; - case IOCTL_SERIAL_GET_STATS: return "IOCTL_SERIAL_GET_STATS"; - case IOCTL_SERIAL_CLEAR_STATS: return "IOCTL_SERIAL_CLEAR_STATS"; - default: return "UnKnown ioctl"; - } -} - - - -BOOLEAN -SerialGetStats( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - In sync with the interrpt service routine (which sets the perf stats) - return the perf stats to the caller. - - -Arguments: - - Context - Pointer to a the request. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PREQUEST_CONTEXT reqContext = (PREQUEST_CONTEXT)Context; - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(WdfInterruptGetDevice(Interrupt)); - PSERIALPERF_STATS sp = reqContext->SystemBuffer; - - UNREFERENCED_PARAMETER(Interrupt); - - *sp = extension->PerfStats; - return FALSE; - -} - - -BOOLEAN -SerialClearStats( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - In sync with the interrpt service routine (which sets the perf stats) - clear the perf stats. - - -Arguments: - - Context - Pointer to a the extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - UNREFERENCED_PARAMETER(Interrupt); - - RtlZeroMemory( - &((PSERIAL_DEVICE_EXTENSION)Context)->PerfStats, - sizeof(SERIALPERF_STATS) - ); - - RtlZeroMemory(&((PSERIAL_DEVICE_EXTENSION)Context)->WmiPerfData, - sizeof(SERIAL_WMI_PERF_DATA)); - - return FALSE; -} - - - -BOOLEAN -SerialSetChars( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to set the special characters for the - driver. - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a special characters - structure. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - UNREFERENCED_PARAMETER(Interrupt); - - ((PSERIAL_IOCTL_SYNC)Context)->Extension->SpecialChars = - *((PSERIAL_CHARS)(((PSERIAL_IOCTL_SYNC)Context)->Data)); - - return FALSE; -} - - -BOOLEAN -SerialSetBaud( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to set the baud rate of the device. - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and what should be the current - baud rate. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; - USHORT Appropriate = PtrToUshort(((PSERIAL_IOCTL_SYNC)Context)->Data); - - UNREFERENCED_PARAMETER(Interrupt); - - WRITE_DIVISOR_LATCH( - Extension, - Extension->Controller, - Appropriate - ); - - return FALSE; -} - - -BOOLEAN -SerialSetLineControl( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to set the buad rate of the device. - -Arguments: - - Context - Pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - WRITE_LINE_CONTROL(Extension, - Extension->Controller, - Extension->LineControl - ); - - return FALSE; -} - - -BOOLEAN -SerialGetModemUpdate( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is simply used to call the interrupt level routine - that handles modem status update. - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a ulong. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; - ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); - - UNREFERENCED_PARAMETER(Interrupt); - - *Result = SerialHandleModemUpdate( - Extension, - FALSE - ); - - return FALSE; -} - - - -BOOLEAN -SerialSetMCRContents( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) -/*++ - -Routine Description: - - This routine is simply used to set the contents of the MCR - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a ulong. - -Return Value: - - This routine always returns FALSE. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; - ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); - - UNREFERENCED_PARAMETER(Interrupt); - - // - // This is severe casting abuse!!! - // - WRITE_MODEM_CONTROL(Extension, Extension->Controller, (UCHAR)PtrToUlong(Result)); - - return FALSE; -} - - - - -BOOLEAN -SerialGetMCRContents( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is simply used to get the contents of the MCR - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a ulong. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; - ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); - - UNREFERENCED_PARAMETER(Interrupt); - - *Result = READ_MODEM_CONTROL(Extension, Extension->Controller); - - return FALSE; -} - - - - -BOOLEAN -SerialSetFCRContents( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) -/*++ - -Routine Description: - - This routine is simply used to set the contents of the FCR - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a ulong. - -Return Value: - - This routine always returns FALSE. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; - ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); - - UNREFERENCED_PARAMETER(Interrupt); - - // - // This is severe casting abuse!!! - // - WRITE_FIFO_CONTROL(Extension, Extension->Controller, (UCHAR)*Result); - - return FALSE; -} - - - -BOOLEAN -SerialGetCommStatus( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This is used to get the current state of the serial driver. - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a serial status - record. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; - PSERIAL_STATUS Stat = ((PSERIAL_IOCTL_SYNC)Context)->Data; - - UNREFERENCED_PARAMETER(Interrupt); - - Stat->Errors = Extension->ErrorWord; - Extension->ErrorWord = 0; - - // - // Eof isn't supported in binary mode - // - Stat->EofReceived = FALSE; - - Stat->AmountInInQueue = Extension->CharsInInterruptBuffer; - - Stat->AmountInOutQueue = Extension->TotalCharsQueued; - - if (Extension->WriteLength) { - - // - // By definition if we have a writelength the we have - // a current write request. - // - PREQUEST_CONTEXT reqContext = NULL; - - ASSERT(Extension->CurrentWriteRequest); - ASSERT(Stat->AmountInOutQueue >= Extension->WriteLength); - - reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); - Stat->AmountInOutQueue -= reqContext->Length - (Extension->WriteLength); - - } - - Stat->WaitForImmediate = Extension->TransmitImmediate; - - Stat->HoldReasons = 0; - if (Extension->TXHolding) { - - if (Extension->TXHolding & SERIAL_TX_CTS) { - - Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS; - - } - - if (Extension->TXHolding & SERIAL_TX_DSR) { - - Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR; - - } - - if (Extension->TXHolding & SERIAL_TX_DCD) { - - Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD; - - } - - if (Extension->TXHolding & SERIAL_TX_XOFF) { - - Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_XON; - - } - - if (Extension->TXHolding & SERIAL_TX_BREAK) { - - Stat->HoldReasons |= SERIAL_TX_WAITING_ON_BREAK; - - } - - } - - if (Extension->RXHolding & SERIAL_RX_DSR) { - - Stat->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR; - - } - - if (Extension->RXHolding & SERIAL_RX_XOFF) { - - Stat->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT; - - } - - return FALSE; -} - - -BOOLEAN -SerialSetEscapeChar( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This is used to set the character that will be used to escape - line status and modem status information when the application - has set up that line status and modem status should be passed - back in the data stream. - -Arguments: - - Context - Pointer to the request that is specify the escape character. - Implicitly - An escape character of 0 means no escaping - will occur. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PREQUEST_CONTEXT reqContext = (PREQUEST_CONTEXT)Context; - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(WdfInterruptGetDevice(Interrupt)); - - UNREFERENCED_PARAMETER(Interrupt); - - extension->EscapeChar = *(PUCHAR)reqContext->SystemBuffer; - - return FALSE; -} - -VOID -SerialEvtIoDeviceControl( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t OutputBufferLength, - IN size_t InputBufferLength, - IN ULONG IoControlCode - ) - -/*++ - -Routine Description: - - This routine provides the initial processing for all of the - Ioctrls for the serial device. - -Arguments: - - Request - Pointer to the WDFREQUEST for the current request - -Return Value: - - The function value is the final status of the call - ---*/ - -{ - // - // The status that gets returned to the caller and - // set in the Request. - // - NTSTATUS Status; - - // - // Just what it says. This is the serial specific device - // extension of the device object create for the serial driver. - // - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - PVOID buffer; - PREQUEST_CONTEXT reqContext; - size_t bufSize; - - UNREFERENCED_PARAMETER(OutputBufferLength); - UNREFERENCED_PARAMETER(InputBufferLength); - - reqContext = SerialGetRequestContext(Request); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "%s for: %p\n", - SerialGetIoctlName(IoControlCode), Request); - - Extension = SerialGetDeviceExtension(WdfIoQueueGetDevice(Queue)); - - // - // We expect to be open so all our pages are locked down. This is, after - // all, an IO operation, so the device should be open first. - // - - if (Extension->DeviceIsOpened != TRUE) { - SerialCompleteRequest(Request, STATUS_INVALID_DEVICE_REQUEST, 0); - return; - } - - - if (SerialCompleteIfError(Extension, Request) != STATUS_SUCCESS) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, - "Information = 0; - reqContext->Status = STATUS_SUCCESS; - reqContext->MajorFunction = IRP_MJ_DEVICE_CONTROL; - - - Status = STATUS_SUCCESS; - - switch (IoControlCode) { - - case IOCTL_SERIAL_SET_BAUD_RATE : { - - ULONG BaudRate; - // - // Will hold the value of the appropriate divisor for - // the requested baud rate. If the baudrate is invalid - // (because the device won't support that baud rate) then - // this value is undefined. - // - // Note: in one sense the concept of a valid baud rate - // is cloudy. We could allow the user to request any - // baud rate. We could then calculate the divisor needed - // for that baud rate. As long as the divisor wasn't less - // than one we would be "ok". (The percentage difference - // between the "true" divisor and the "rounded" value given - // to the hardware might make it unusable, but... ) It would - // really be up to the user to "Know" whether the baud rate - // is suitable. So much for theory, *We* only support a given - // set of baud rates. - // - SHORT AppropriateDivisor; - - Status = WdfRequestRetrieveInputBuffer (Request, sizeof(SERIAL_BAUD_RATE), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - BaudRate = ((PSERIAL_BAUD_RATE)(buffer))->BaudRate; - - - // - // Get the baud rate from the request. We pass it - // to a routine which will set the correct divisor. - // - - Status = SerialGetDivisorFromBaud( - Extension->ClockRate, - BaudRate, - &AppropriateDivisor - ); - - - if (NT_SUCCESS(Status)) { - - SERIAL_IOCTL_SYNC S; - - - Extension->CurrentBaud = BaudRate; - Extension->WmiCommData.BaudRate = BaudRate; - - S.Extension = Extension; - S.Data = (PVOID) (ULONG_PTR) AppropriateDivisor; - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetBaud, - &S - ); - - } - - break; - } - - case IOCTL_SERIAL_GET_BAUD_RATE: { - - PSERIAL_BAUD_RATE Br; - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_BAUD_RATE), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - Br = (PSERIAL_BAUD_RATE)buffer; - - Br->BaudRate = Extension->CurrentBaud; - - reqContext->Information = sizeof(SERIAL_BAUD_RATE); - - break; - - } - - case IOCTL_SERIAL_GET_MODEM_CONTROL: { - SERIAL_IOCTL_SYNC S; - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->Information = sizeof(ULONG); - - S.Extension = Extension; - S.Data = buffer; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGetMCRContents, - &S - ); - - break; - } - case IOCTL_SERIAL_SET_MODEM_CONTROL: { - SERIAL_IOCTL_SYNC S; - - Status = WdfRequestRetrieveInputBuffer (Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - S.Extension = Extension; - S.Data = buffer; - - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetMCRContents, - &S - ); - - break; - } - case IOCTL_SERIAL_SET_FIFO_CONTROL: { - SERIAL_IOCTL_SYNC S; - - Status = WdfRequestRetrieveInputBuffer (Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - S.Extension = Extension; - S.Data = buffer; - - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetFCRContents, - &S - ); - - break; - } - case IOCTL_SERIAL_SET_LINE_CONTROL: { - - PSERIAL_LINE_CONTROL Lc; - UCHAR LData; - UCHAR LStop; - UCHAR LParity; - UCHAR Mask = 0xff; - - Status = WdfRequestRetrieveInputBuffer (Request, sizeof(SERIAL_LINE_CONTROL), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - // - // Points to the line control record in the Request. - // - Lc = (PSERIAL_LINE_CONTROL)buffer; - - switch (Lc->WordLength) { - case 5: { - - LData = SERIAL_5_DATA; - Mask = 0x1f; - break; - - } - case 6: { - - LData = SERIAL_6_DATA; - Mask = 0x3f; - break; - - } - case 7: { - - LData = SERIAL_7_DATA; - Mask = 0x7f; - break; - - } - case 8: { - - LData = SERIAL_8_DATA; - break; - - } - default: { - - Status = STATUS_INVALID_PARAMETER; - goto DoneWithIoctl; - - } - - } - - Extension->WmiCommData.BitsPerByte = Lc->WordLength; - - switch (Lc->Parity) { - - case NO_PARITY: { - Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE; - LParity = SERIAL_NONE_PARITY; - break; - - } - case EVEN_PARITY: { - Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN; - LParity = SERIAL_EVEN_PARITY; - break; - - } - case ODD_PARITY: { - Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD; - LParity = SERIAL_ODD_PARITY; - break; - - } - case SPACE_PARITY: { - Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE; - LParity = SERIAL_SPACE_PARITY; - break; - - } - case MARK_PARITY: { - Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK; - LParity = SERIAL_MARK_PARITY; - break; - - } - default: { - - Status = STATUS_INVALID_PARAMETER; - goto DoneWithIoctl; - break; - } - - } - - switch (Lc->StopBits) { - - case STOP_BIT_1: { - Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1; - LStop = SERIAL_1_STOP; - break; - } - case STOP_BITS_1_5: { - - if (LData != SERIAL_5_DATA) { - - Status = STATUS_INVALID_PARAMETER; - goto DoneWithIoctl; - } - Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1_5; - LStop = SERIAL_1_5_STOP; - break; - - } - case STOP_BITS_2: { - - if (LData == SERIAL_5_DATA) { - - Status = STATUS_INVALID_PARAMETER; - goto DoneWithIoctl; - } - Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_2; - LStop = SERIAL_2_STOP; - break; - - } - default: { - - Status = STATUS_INVALID_PARAMETER; - goto DoneWithIoctl; - } - - } - - Extension->LineControl = - (UCHAR)((Extension->LineControl & SERIAL_LCR_BREAK) | - (LData | LParity | LStop)); - Extension->ValidDataMask = Mask; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetLineControl, - Extension - ); - - break; - } - case IOCTL_SERIAL_GET_LINE_CONTROL: { - - PSERIAL_LINE_CONTROL Lc; - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_LINE_CONTROL), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - Lc = (PSERIAL_LINE_CONTROL)buffer; - - RtlZeroMemory(buffer, OutputBufferLength); - - if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) { - Lc->WordLength = 5; - } else if ((Extension->LineControl & SERIAL_DATA_MASK) - == SERIAL_6_DATA) { - Lc->WordLength = 6; - } else if ((Extension->LineControl & SERIAL_DATA_MASK) - == SERIAL_7_DATA) { - Lc->WordLength = 7; - } else if ((Extension->LineControl & SERIAL_DATA_MASK) - == SERIAL_8_DATA) { - Lc->WordLength = 8; - } - - if ((Extension->LineControl & SERIAL_PARITY_MASK) - == SERIAL_NONE_PARITY) { - Lc->Parity = NO_PARITY; - } else if ((Extension->LineControl & SERIAL_PARITY_MASK) - == SERIAL_ODD_PARITY) { - Lc->Parity = ODD_PARITY; - } else if ((Extension->LineControl & SERIAL_PARITY_MASK) - == SERIAL_EVEN_PARITY) { - Lc->Parity = EVEN_PARITY; - } else if ((Extension->LineControl & SERIAL_PARITY_MASK) - == SERIAL_MARK_PARITY) { - Lc->Parity = MARK_PARITY; - } else if ((Extension->LineControl & SERIAL_PARITY_MASK) - == SERIAL_SPACE_PARITY) { - Lc->Parity = SPACE_PARITY; - } - - if (Extension->LineControl & SERIAL_2_STOP) { - if (Lc->WordLength == 5) { - Lc->StopBits = STOP_BITS_1_5; - } else { - Lc->StopBits = STOP_BITS_2; - } - } else { - Lc->StopBits = STOP_BIT_1; - } - - reqContext->Information = sizeof(SERIAL_LINE_CONTROL); - - break; - } - case IOCTL_SERIAL_SET_TIMEOUTS: { - - PSERIAL_TIMEOUTS NewTimeouts; - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_TIMEOUTS), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - NewTimeouts =(PSERIAL_TIMEOUTS)buffer; - - if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) && - (NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) && - (NewTimeouts->ReadTotalTimeoutConstant == MAXULONG)) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - - Extension->Timeouts.ReadIntervalTimeout = - NewTimeouts->ReadIntervalTimeout; - - Extension->Timeouts.ReadTotalTimeoutMultiplier = - NewTimeouts->ReadTotalTimeoutMultiplier; - - Extension->Timeouts.ReadTotalTimeoutConstant = - NewTimeouts->ReadTotalTimeoutConstant; - - Extension->Timeouts.WriteTotalTimeoutMultiplier = - NewTimeouts->WriteTotalTimeoutMultiplier; - - Extension->Timeouts.WriteTotalTimeoutConstant = - NewTimeouts->WriteTotalTimeoutConstant; - - break; - } - case IOCTL_SERIAL_GET_TIMEOUTS: { - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_TIMEOUTS), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - *((PSERIAL_TIMEOUTS)buffer) = Extension->Timeouts; - reqContext->Information = sizeof(SERIAL_TIMEOUTS); - - break; - } - case IOCTL_SERIAL_SET_CHARS: { - - SERIAL_IOCTL_SYNC S; - PSERIAL_CHARS NewChars; - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_CHARS), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - NewChars = (PSERIAL_CHARS)buffer; - - // - // The only thing that can be wrong with the chars - // is that the xon and xoff characters are the - // same. - // -#if 0 - if (NewChars->XonChar == NewChars->XoffChar) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } -#endif - - // - // We acquire the control lock so that only - // one request can GET or SET the characters - // at a time. The sets could be synchronized - // by the interrupt spinlock, but that wouldn't - // prevent multiple gets at the same time. - // - - S.Extension = Extension; - S.Data = NewChars; - - // - // Under the protection of the lock, make sure that - // the xon and xoff characters aren't the same as - // the escape character. - // - - if (Extension->EscapeChar) { - - if ((Extension->EscapeChar == NewChars->XonChar) || - (Extension->EscapeChar == NewChars->XoffChar)) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - } - - Extension->WmiCommData.XonCharacter = NewChars->XonChar; - Extension->WmiCommData.XoffCharacter = NewChars->XoffChar; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetChars, - &S - ); - - - break; - - } - case IOCTL_SERIAL_GET_CHARS: { - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_CHARS), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - *((PSERIAL_CHARS)buffer) = Extension->SpecialChars; - reqContext->Information = sizeof(SERIAL_CHARS); - - - break; - } - case IOCTL_SERIAL_SET_DTR: - case IOCTL_SERIAL_CLR_DTR: { - - - // - // We acquire the lock so that we can check whether - // automatic dtr flow control is enabled. If it is - // then we return an error since the app is not allowed - // to touch this if it is automatic. - // - - if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) - == SERIAL_DTR_HANDSHAKE) { - - Status = STATUS_INVALID_PARAMETER; - - } else { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - ((IoControlCode == - IOCTL_SERIAL_SET_DTR)? - (SerialSetDTR):(SerialClrDTR)), - Extension - ); - - } - - break; - } - case IOCTL_SERIAL_RESET_DEVICE: { - - break; - } - case IOCTL_SERIAL_SET_RTS: - case IOCTL_SERIAL_CLR_RTS: { - - // - // We acquire the lock so that we can check whether - // automatic rts flow control or transmit toggleing - // is enabled. If it is then we return an error since - // the app is not allowed to touch this if it is automatic - // or toggling. - // - - if (((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) - == SERIAL_RTS_HANDSHAKE) || - ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) - == SERIAL_TRANSMIT_TOGGLE)) { - - Status = STATUS_INVALID_PARAMETER; - - } else { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - ((IoControlCode == - IOCTL_SERIAL_SET_RTS)? - (SerialSetRTS):(SerialClrRTS)), - Extension - ); - - } - - break; - - } - case IOCTL_SERIAL_SET_XOFF: { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialPretendXoff, - Extension - ); - - break; - - } - case IOCTL_SERIAL_SET_XON: { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialPretendXon, - Extension - ); - - break; - - } - case IOCTL_SERIAL_SET_BREAK_ON: { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialTurnOnBreak, - Extension - ); - - break; - } - case IOCTL_SERIAL_SET_BREAK_OFF: { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialTurnOffBreak, - Extension - ); - - break; - } - case IOCTL_SERIAL_SET_QUEUE_SIZE: { - - // - // Type ahead buffer is fixed, so we just validate - // the the users request is not bigger that our - // own internal buffer size. - // - - PSERIAL_QUEUE_SIZE Rs; - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_QUEUE_SIZE), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - ASSERT(Extension->InterruptReadBuffer); - - Rs = (PSERIAL_QUEUE_SIZE)buffer; - - reqContext->SystemBuffer = buffer; - - // - // We have to allocate the memory for the new - // buffer while we're still in the context of the - // caller. We don't even try to protect this - // with a lock because the value could be stale - // as soon as we release the lock - The only time - // we will know for sure is when we actually try - // to do the resize. - // - - if (Rs->InSize <= Extension->BufferSize) { - - Status = STATUS_SUCCESS; - break; - - } - - reqContext->Type3InputBuffer = - ExAllocatePoolWithQuotaTag( - NonPagedPoolNx | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, - Rs->InSize, - POOL_TAG - ); - - if (!reqContext->Type3InputBuffer) { - - Status = STATUS_INSUFFICIENT_RESOURCES; - break; - - } - - // - // Well the data passed was big enough. Do the request. - // - // There are two reason we place it in the read queue: - // - // 1) We want to serialize these resize requests so that - // they don't contend with each other. - // - // 2) We want to serialize these requests with reads since - // we don't want reads and resizes contending over the - // read buffer. - // - - - SerialStartOrQueue( - Extension, - Request, - Extension->ReadQueue, - &Extension->CurrentReadRequest, - SerialStartRead - ); - - return; - } - case IOCTL_SERIAL_GET_WAIT_MASK: { - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - // - // Simple scalar read. No reason to acquire a lock. - // - - reqContext->Information = sizeof(ULONG); - - *((ULONG *)buffer) = Extension->IsrWaitMask; - - break; - - } - case IOCTL_SERIAL_SET_WAIT_MASK: { - - ULONG NewMask; - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "In Ioctl processing for set mask\n"); - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - NewMask = *((ULONG *)buffer); - reqContext->SystemBuffer = buffer; - - // - // Make sure that the mask only contains valid - // waitable events. - // - - if (NewMask & ~(SERIAL_EV_RXCHAR | - SERIAL_EV_RXFLAG | - SERIAL_EV_TXEMPTY | - SERIAL_EV_CTS | - SERIAL_EV_DSR | - SERIAL_EV_RLSD | - SERIAL_EV_BREAK | - SERIAL_EV_ERR | - SERIAL_EV_RING | - SERIAL_EV_PERR | - SERIAL_EV_RX80FULL | - SERIAL_EV_EVENT1 | - SERIAL_EV_EVENT2)) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Unknown mask %x\n", NewMask); - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - // - // Either start this request or put it on the - // queue. - // - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Starting or queuing set mask request %p" - "\n", Request); - - SerialStartOrQueue(Extension, Request, Extension->MaskQueue, - &Extension->CurrentMaskRequest, - SerialStartMask); - return; - - } - case IOCTL_SERIAL_WAIT_ON_MASK: { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "In Ioctl processing for wait mask\n"); - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->SystemBuffer = buffer; - - // - // Either start this request or put it on the - // queue. - // - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Starting or queuing wait mask request" - "%p\n", Request); - - SerialStartOrQueue( - Extension, - Request, - Extension->MaskQueue, - &Extension->CurrentMaskRequest, - SerialStartMask - ); - return; - } - case IOCTL_SERIAL_IMMEDIATE_CHAR: { - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(UCHAR), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->SystemBuffer = buffer; - - if (Extension->CurrentImmediateRequest) { - - Status = STATUS_INVALID_PARAMETER; - - } else { - - // - // We can queue the char. We need to set - // a cancel routine because flow control could - // keep the char from transmitting. Make sure - // that the request hasn't already been canceled. - // - - Extension->CurrentImmediateRequest = Request; - Extension->TotalCharsQueued++; - SerialStartImmediate(Extension); - return; - - } - - break; - - } - case IOCTL_SERIAL_PURGE: { - - ULONG Mask; - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - // - // Check to make sure that the mask only has - // 0 or the other appropriate values. - // - - Mask = *((ULONG *)(buffer)); - - if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT | - SERIAL_PURGE_RXABORT | - SERIAL_PURGE_TXCLEAR | - SERIAL_PURGE_RXCLEAR - ) - ) - )) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - reqContext->SystemBuffer = buffer; - - // - // Either start this request or put it on the - // queue. - // - - SerialStartOrQueue( - Extension, - Request, - Extension->PurgeQueue, - &Extension->CurrentPurgeRequest, - SerialStartPurge - ); - return; - } - case IOCTL_SERIAL_GET_HANDFLOW: { - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_HANDFLOW), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->Information = sizeof(SERIAL_HANDFLOW); - - *((PSERIAL_HANDFLOW)buffer) = Extension->HandFlow; - - break; - - } - case IOCTL_SERIAL_SET_HANDFLOW: { - - SERIAL_IOCTL_SYNC S; - PSERIAL_HANDFLOW HandFlow; - - // - // Make sure that the hand shake and control is the - // right size. - // - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_HANDFLOW), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - HandFlow = (PSERIAL_HANDFLOW)buffer; - - // - // Make sure that there are no invalid bits set in - // the control and handshake. - // - - if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - // - // Make sure that the app hasn't set an invlid DTR mode. - // - - if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) == - SERIAL_DTR_MASK) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - // - // Make sure that haven't set totally invalid xon/xoff - // limits. - // - - if ((HandFlow->XonLimit < 0) || - ((ULONG)HandFlow->XonLimit > Extension->BufferSize)) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - if ((HandFlow->XoffLimit < 0) || - ((ULONG)HandFlow->XoffLimit > Extension->BufferSize)) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - S.Extension = Extension; - S.Data = HandFlow; - - // - // Under the protection of the lock, make sure that - // we aren't turning on error replacement when we - // are doing line status/modem status insertion. - // - - if (Extension->EscapeChar) { - - if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - - } - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetHandFlow, - &S - ); - - break; - - } - case IOCTL_SERIAL_GET_MODEMSTATUS: { - - SERIAL_IOCTL_SYNC S; - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->Information = sizeof(ULONG); - - S.Extension = Extension; - S.Data = buffer; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGetModemUpdate, - &S - ); - - break; - - } - case IOCTL_SERIAL_GET_DTRRTS: { - - ULONG ModemControl; - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->Information = sizeof(ULONG); - reqContext->Status = STATUS_SUCCESS; - - // - // Reading this hardware has no effect on the device. - // - - ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); - - ModemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE; - - *(PULONG)buffer = ModemControl; - - break; - - } - case IOCTL_SERIAL_GET_COMMSTATUS: { - - SERIAL_IOCTL_SYNC S; - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_STATUS), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->Information = sizeof(SERIAL_STATUS); - - S.Extension = Extension; - S.Data = buffer; - - // - // Acquire the cancel spin lock so nothing much - // changes while were getting the state. - // - - //IoAcquireCancelSpinLock(&OldIrql); - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGetCommStatus, - &S - ); - - //IoReleaseCancelSpinLock(OldIrql); - - break; - - } - case IOCTL_SERIAL_GET_PROPERTIES: { - - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_COMMPROP), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - // - // No synchronization is required since this information - // is "static". - // - - SerialGetProperties( - Extension, - buffer - ); - - reqContext->Information = sizeof(SERIAL_COMMPROP); - reqContext->Status = STATUS_SUCCESS; - - break; - } - case IOCTL_SERIAL_XOFF_COUNTER: { - - PSERIAL_XOFF_COUNTER Xc; - - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_XOFF_COUNTER), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - Xc = (PSERIAL_XOFF_COUNTER)buffer; - - if (Xc->Counter <= 0) { - - Status = STATUS_INVALID_PARAMETER; - break; - - } - reqContext->SystemBuffer = buffer; - - // - // There is no output, so make that clear now - // - - reqContext->Information = 0; - - // - // So far so good. Put the request onto the write queue. - // - - SerialStartOrQueue( - Extension, - Request, - Extension->WriteQueue, - &Extension->CurrentWriteRequest, - SerialStartWrite - ); - return; - - } - case IOCTL_SERIAL_LSRMST_INSERT: { - - PUCHAR escapeChar; - SERIAL_IOCTL_SYNC S; - - // - // Make sure we get a byte. - // - Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(UCHAR), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->SystemBuffer = buffer; - - escapeChar = (PUCHAR)buffer; - - if (*escapeChar) { - - // - // We've got some escape work to do. We will make sure that - // the character is not the same as the Xon or Xoff character, - // or that we are already doing error replacement. - // - - if ((*escapeChar == Extension->SpecialChars.XoffChar) || - (*escapeChar == Extension->SpecialChars.XonChar) || - (Extension->HandFlow.FlowReplace & SERIAL_ERROR_CHAR)) { - - Status = STATUS_INVALID_PARAMETER; - - break; - - } - - } - - S.Extension = Extension; - S.Data = buffer; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialSetEscapeChar, - reqContext - ); - - break; - - } - case IOCTL_SERIAL_CONFIG_SIZE: { - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->Information = sizeof(ULONG); - reqContext->Status = STATUS_SUCCESS; - - *(PULONG)buffer = 0; - - break; - } - case IOCTL_SERIAL_GET_STATS: { - - Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIALPERF_STATS), &buffer, &bufSize ); - if( !NT_SUCCESS(Status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); - break; - } - - reqContext->SystemBuffer = buffer; - - reqContext->Information = sizeof(SERIALPERF_STATS); - reqContext->Status = STATUS_SUCCESS; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGetStats, - reqContext - ); - - break; - } - case IOCTL_SERIAL_CLEAR_STATS: { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialClearStats, - Extension - ); - break; - } - default: { - - Status = STATUS_INVALID_PARAMETER; - break; - } - } - -DoneWithIoctl:; - - reqContext->Status = Status; - - SerialCompleteRequest(Request, Status, reqContext->Information); - - return; - -} - - -VOID -SerialGetProperties( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN PSERIAL_COMMPROP Properties - ) - -/*++ - -Routine Description: - - This function returns the capabilities of this particular - serial device. - -Arguments: - - Extension - The serial device extension. - - Properties - The structure used to return the properties - -Return Value: - - None. - ---*/ - -{ - - - RtlZeroMemory( - Properties, - sizeof(SERIAL_COMMPROP) - ); - - Properties->PacketLength = sizeof(SERIAL_COMMPROP); - Properties->PacketVersion = 2; - Properties->ServiceMask = SERIAL_SP_SERIALCOMM; - Properties->MaxTxQueue = 0; - Properties->MaxRxQueue = 0; - - Properties->MaxBaud = SERIAL_BAUD_USER; - Properties->SettableBaud = Extension->SupportedBauds; - - Properties->ProvSubType = SERIAL_SP_RS232; - Properties->ProvCapabilities = SERIAL_PCF_DTRDSR | - SERIAL_PCF_RTSCTS | - SERIAL_PCF_CD | - SERIAL_PCF_PARITY_CHECK | - SERIAL_PCF_XONXOFF | - SERIAL_PCF_SETXCHAR | - SERIAL_PCF_TOTALTIMEOUTS | - SERIAL_PCF_INTTIMEOUTS; - Properties->SettableParams = SERIAL_SP_PARITY | - SERIAL_SP_BAUD | - SERIAL_SP_DATABITS | - SERIAL_SP_STOPBITS | - SERIAL_SP_HANDSHAKING | - SERIAL_SP_PARITY_CHECK | - SERIAL_SP_CARRIER_DETECT; - - - Properties->SettableData = SERIAL_DATABITS_5 | - SERIAL_DATABITS_6 | - SERIAL_DATABITS_7 | - SERIAL_DATABITS_8; - Properties->SettableStopParity = SERIAL_STOPBITS_10 | - SERIAL_STOPBITS_15 | - SERIAL_STOPBITS_20 | - SERIAL_PARITY_NONE | - SERIAL_PARITY_ODD | - SERIAL_PARITY_EVEN | - SERIAL_PARITY_MARK | - SERIAL_PARITY_SPACE; - Properties->CurrentTxQueue = 0; - Properties->CurrentRxQueue = Extension->BufferSize; - -} - -VOID -SerialEvtIoInternalDeviceControl( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t OutputBufferLength, - IN size_t InputBufferLength, - IN ULONG IoControlCode -) -/*++ - -Routine Description: - - This routine provides the initial processing for all of the - internal Ioctrls for the serial device. - -Arguments: - - PDevObj - Pointer to the device object for this device - - PIrp - Pointer to the WDFREQUEST for the current request - -Return Value: - - The function value is the final status of the call - ---*/ - -{ - NTSTATUS status; - PSERIAL_DEVICE_EXTENSION pDevExt = NULL; - PVOID buffer; - PREQUEST_CONTEXT reqContext; - WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; - size_t bufSize; - - UNREFERENCED_PARAMETER(OutputBufferLength); - UNREFERENCED_PARAMETER(InputBufferLength); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "SerialEvtIoInternalDeviceControl for: %p\n", Request); - - pDevExt = SerialGetDeviceExtension(WdfIoQueueGetDevice(Queue)); - - if (SerialCompleteIfError(pDevExt, Request) != STATUS_SUCCESS) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Information = 0; - reqContext->Status = STATUS_SUCCESS; - reqContext->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - - switch (IoControlCode) { - - case IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE: - // - // Init wait-wake policy structure. - // - WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings); - // - // Override the default settings from allow user control to do not allow. - // - wakeSettings.UserControlOfWakeSettings = IdleDoNotAllowUserControl; - status = WdfDeviceAssignSxWakeSettings(pDevExt->WdfDevice, &wakeSettings); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceAssignSxWakeSettings failed %x \n", status); - break; - } - - pDevExt->IsWakeEnabled = TRUE; - status = STATUS_SUCCESS; - break; - - case IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE: - - WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings); - // - // Override the default settings. - // - wakeSettings.Enabled = WdfFalse; // Disables wait-wake - wakeSettings.UserControlOfWakeSettings = IdleDoNotAllowUserControl; - status = WdfDeviceAssignSxWakeSettings(pDevExt->WdfDevice, &wakeSettings); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceAssignSxWakeSettings failed %x \n", status); - break; - } - - pDevExt->IsWakeEnabled = FALSE; - status = STATUS_SUCCESS; - break; - - - // - // Put the serial port in a "filter-driver" appropriate state - // - // WARNING: This code assumes it is being called by a trusted kernel - // entity and no checking is done on the validity of the settings - // passed to IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS - // - // If validity checking is desired, the regular ioctl's should be used - // - - case IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS: - case IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS: { - - SERIAL_BASIC_SETTINGS basic; - PSERIAL_BASIC_SETTINGS pBasic; - SERIAL_IOCTL_SYNC S; - - if (IoControlCode == IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS) { - - - // - // Check the buffer size - // - status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_BASIC_SETTINGS), &buffer, &bufSize ); - if( !NT_SUCCESS(status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", status); - break; - } - - reqContext->SystemBuffer = buffer; - - // - // Everything is 0 -- timeouts and flow control and fifos. If - // We add additional features, this zero memory method - // may not work. - // - - RtlZeroMemory(&basic, sizeof(SERIAL_BASIC_SETTINGS)); - - basic.TxFifo = 1; - basic.RxFifo = SERIAL_1_BYTE_HIGH_WATER; - - reqContext->Information = sizeof(SERIAL_BASIC_SETTINGS); - pBasic = (PSERIAL_BASIC_SETTINGS)buffer; - - // - // Save off the old settings - // - - RtlCopyMemory(&pBasic->Timeouts, &pDevExt->Timeouts, - sizeof(SERIAL_TIMEOUTS)); - - RtlCopyMemory(&pBasic->HandFlow, &pDevExt->HandFlow, - sizeof(SERIAL_HANDFLOW)); - - pBasic->RxFifo = pDevExt->RxFifoTrigger; - pBasic->TxFifo = pDevExt->TxFifoAmount; - - // - // Point to our new settings - // - - pBasic = &basic; - } else { // restoring settings - - status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_BASIC_SETTINGS), &buffer, &bufSize ); - if( !NT_SUCCESS(status) ) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", status); - break; - } - - pBasic = (PSERIAL_BASIC_SETTINGS)buffer; - } - - // - // Set the timeouts - // - - RtlCopyMemory(&pDevExt->Timeouts, &pBasic->Timeouts, - sizeof(SERIAL_TIMEOUTS)); - - // - // Set flowcontrol - // - - S.Extension = pDevExt; - S.Data = &pBasic->HandFlow; - WdfInterruptSynchronize(pDevExt->WdfInterrupt, SerialSetHandFlow, &S); - - if (pDevExt->FifoPresent) { - pDevExt->TxFifoAmount = pBasic->TxFifo; - pDevExt->RxFifoTrigger = (UCHAR)pBasic->RxFifo; - - WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, (UCHAR)0); - READ_RECEIVE_BUFFER(pDevExt, pDevExt->Controller); - WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, - (UCHAR)(SERIAL_FCR_ENABLE | pDevExt->RxFifoTrigger - | SERIAL_FCR_RCVR_RESET - | SERIAL_FCR_TXMT_RESET)); - } else { - pDevExt->TxFifoAmount = pDevExt->RxFifoTrigger = 0; - WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, (UCHAR)0); - } - - - break; - } - - default: - status = STATUS_INVALID_PARAMETER; - break; - - } - - reqContext->Status = status; - - SerialCompleteRequest(Request, reqContext->Status, reqContext->Information); - - return; -} - - - diff --git a/tests/projects/wdk/kmdf/serial/isr.c b/tests/projects/wdk/kmdf/serial/isr.c deleted file mode 100644 index 806164a61..000000000 --- a/tests/projects/wdk/kmdf/serial/isr.c +++ /dev/null @@ -1,1517 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - isr.c - -Abstract: - - This module contains the interrupt service routine for the - serial driver. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "isr.tmh" -#endif - - -NTSTATUS -SerialEvtInterruptEnable( - IN WDFINTERRUPT Interrupt, - IN WDFDEVICE AssociatedDevice - ) -/*++ - -Routine Description: - - This event is called when the Framework moves the device to D0, and after - EvtDeviceD0Entry. The driver should enable its interrupt here. - - This function will be called at the device's assigned interrupt - IRQL (DIRQL.) - -Arguments: - - Interrupt - Handle to a Framework interrupt object. - - AssociatedDevice - Handle to a Framework device object. - -Return Value: - - BOOLEAN - TRUE indicates that the interrupt was successfully enabled. - ---*/ -{ - UNREFERENCED_PARAMETER(Interrupt); - UNREFERENCED_PARAMETER(AssociatedDevice); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "--> SerialEvtInterruptEnable\n"); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- SerialEvtInterruptEnable\n"); - - return STATUS_SUCCESS; -} - -NTSTATUS -SerialEvtInterruptDisable( - IN WDFINTERRUPT Interrupt, - IN WDFDEVICE AssociatedDevice - ) -/*++ - -Routine Description: - - This event is called before the Framework moves the device to D1, D2 or D3 - and before EvtDeviceD0Exit. The driver should disable its interrupt here. - - This function will be called at the device's assigned interrupt - IRQL (DIRQL.) - -Arguments: - - Interrupt - Handle to a Framework interrupt object. - - AssociatedDevice - Handle to a Framework device object. - -Return Value: - - BOOLEAN - TRUE indicates that the interrupt was successfully disabled. - ---*/ -{ - UNREFERENCED_PARAMETER(Interrupt); - UNREFERENCED_PARAMETER(AssociatedDevice); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "--> SerialEvtInterruptDisable\n"); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- SerialEvtInterruptDisable\n"); - - return STATUS_SUCCESS; -} - -BOOLEAN -SerialISR( - IN WDFINTERRUPT Interrupt, - IN ULONG MessageID - ) - -/*++ - -Routine Description: - - This is the interrupt service routine for the serial port driver. - It will determine whether the serial port is the source of this - interrupt. If it is, then this routine will do the minimum of - processing to quiet the interrupt. It will store any information - necessary for later processing. - -Arguments: - - InterruptObject - Points to the interrupt object declared for this - device. We *do not* use this parameter. - - -Return Value: - - This function will return TRUE if the serial port is the source - of this interrupt, FALSE otherwise. - ---*/ - -{ - // - // Holds the information specific to handling this device. - // - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - // - // Holds the contents of the interrupt identification record. - // A low bit of zero in this register indicates that there is - // an interrupt pending on this device. - // - UCHAR InterruptIdReg; - - // - // Will hold whether we've serviced any interrupt causes in this - // routine. - // - BOOLEAN ServicedAnInterrupt; - - UCHAR tempLSR; - PREQUEST_CONTEXT reqContext = NULL; - - UNREFERENCED_PARAMETER(MessageID); - - Extension = SerialGetDeviceExtension(WdfInterruptGetDevice(Interrupt)); - - // - // Make sure we have an interrupt pending. If we do then - // we need to make sure that the device is open. If the - // device isn't open or powered down then quiet the device. Note that - // if the device isn't opened when we enter this routine - // it can't open while we're in it. - // - - InterruptIdReg = READ_INTERRUPT_ID_REG(Extension, Extension->Controller); - - if ((InterruptIdReg & SERIAL_IIR_NO_INTERRUPT_PENDING)) { - - ServicedAnInterrupt = FALSE; - - } else if (!Extension->DeviceIsOpened/* - || (Extension->PowerState != PowerDeviceD0)*/) { - - - // - // We got an interrupt with the device being closed or when the - // device is supposed to be powered down. This - // is not unlikely with a serial device. We just quietly - // keep servicing the causes until it calms down. - // - - ServicedAnInterrupt = TRUE; - do { - - InterruptIdReg &= (~SERIAL_IIR_FIFOS_ENABLED); - switch (InterruptIdReg) { - - case SERIAL_IIR_RLS: { - - READ_LINE_STATUS(Extension, Extension->Controller); - - break; - - } - - case SERIAL_IIR_RDA: - case SERIAL_IIR_CTI: { - - READ_RECEIVE_BUFFER(Extension, Extension->Controller); - - break; - - } - - case SERIAL_IIR_THR: { - - // - // Alread clear from reading the iir. - // - // We want to keep close track of whether - // the holding register is empty. - // - - Extension->HoldingEmpty = TRUE; - break; - - } - - case SERIAL_IIR_MS: { - - READ_MODEM_STATUS(Extension, Extension->Controller); - break; - - } - - default: { - - ASSERT(FALSE); - break; - - } - - } - - } while (!((InterruptIdReg = - READ_INTERRUPT_ID_REG(Extension, Extension->Controller)) - & SERIAL_IIR_NO_INTERRUPT_PENDING)); - - } else { - - ServicedAnInterrupt = TRUE; - do { - - // - // We only care about bits that can denote an interrupt. - // - - InterruptIdReg &= SERIAL_IIR_RLS | SERIAL_IIR_RDA | - SERIAL_IIR_CTI | SERIAL_IIR_THR | - SERIAL_IIR_MS; - - // - // We have an interrupt. We look for interrupt causes - // in priority order. The presence of a higher interrupt - // will mask out causes of a lower priority. When we service - // and quiet a higher priority interrupt we then need to check - // the interrupt causes to see if a new interrupt cause is - // present. - // - - switch (InterruptIdReg) { - - case SERIAL_IIR_RLS: { - - SerialProcessLSR(Extension); - - break; - - } - - case SERIAL_IIR_RDA: - case SERIAL_IIR_CTI: - - { - - // - // Reading the receive buffer will quiet this interrupt. - // - // It may also reveal a new interrupt cause. - // - UCHAR ReceivedChar; - - do { - - ReceivedChar = - READ_RECEIVE_BUFFER(Extension, Extension->Controller); - Extension->PerfStats.ReceivedCount++; - Extension->WmiPerfData.ReceivedCount++; - - ReceivedChar &= Extension->ValidDataMask; - - if (!ReceivedChar && - (Extension->HandFlow.FlowReplace & - SERIAL_NULL_STRIPPING)) { - - // - // If what we got is a null character - // and we're doing null stripping, then - // we simply act as if we didn't see it. - // - - goto ReceiveDoLineStatus; - - } - - if ((Extension->HandFlow.FlowReplace & - SERIAL_AUTO_TRANSMIT) && - ((ReceivedChar == - Extension->SpecialChars.XonChar) || - (ReceivedChar == - Extension->SpecialChars.XoffChar))) { - - // - // No matter what happens this character - // will never get seen by the app. - // - - if (ReceivedChar == - Extension->SpecialChars.XoffChar) { - - Extension->TXHolding |= SERIAL_TX_XOFF; - - if ((Extension->HandFlow.FlowReplace & - SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } - - - } else { - - if (Extension->TXHolding & SERIAL_TX_XOFF) { - - // - // We got the xon char **AND*** we - // were being held up on transmission - // by xoff. Clear that we are holding - // due to xoff. Transmission will - // automatically restart because of - // the code outside the main loop that - // catches problems chips like the - // SMC and the Winbond. - // - - Extension->TXHolding &= ~SERIAL_TX_XOFF; - - } - - } - - goto ReceiveDoLineStatus; - - } - - // - // Check to see if we should note - // the receive character or special - // character event. - // - - if (Extension->IsrWaitMask) { - - if (Extension->IsrWaitMask & - SERIAL_EV_RXCHAR) { - - Extension->HistoryMask |= SERIAL_EV_RXCHAR; - - } - - if ((Extension->IsrWaitMask & - SERIAL_EV_RXFLAG) && - (Extension->SpecialChars.EventChar == - ReceivedChar)) { - - Extension->HistoryMask |= SERIAL_EV_RXFLAG; - - } - - if (Extension->IrpMaskLocation && - Extension->HistoryMask) { - - *Extension->IrpMaskLocation = - Extension->HistoryMask; - Extension->IrpMaskLocation = NULL; - Extension->HistoryMask = 0; - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - reqContext->Information = sizeof(ULONG); - SerialInsertQueueDpc( - Extension->CommWaitDpc - ); - - } - - } - - SerialPutChar( - Extension, - ReceivedChar - ); - - // - // If we're doing line status and modem - // status insertion then we need to insert - // a zero following the character we just - // placed into the buffer to mark that this - // was reception of what we are using to - // escape. - // - - if (Extension->EscapeChar && - (Extension->EscapeChar == - ReceivedChar)) { - - SerialPutChar( - Extension, - SERIAL_LSRMST_ESCAPE - ); - - } - - -ReceiveDoLineStatus: ; - // - // This reads the interrupt ID register and detemines if bits are 0 - // If either of the reserved bits are 1, we stop servicing interrupts - // Since this detection method is not guarenteed this is enabled via - // a registry entry "UartDetectRemoval" and intialized on DriverEntry. - // This is disabled by default and will only be enabled on Stratus systems - // that allow hot replacement of serial cards - // - if(Extension->UartRemovalDetect) - { - UCHAR DetectRemoval; - - DetectRemoval = READ_INTERRUPT_ID_REG(Extension, Extension->Controller); - - if(DetectRemoval & SERIAL_IIR_MUST_BE_ZERO) - { - // break out of this loop and stop processing interrupts - break; - } - } - - if (!((tempLSR = SerialProcessLSR(Extension)) & - SERIAL_LSR_DR)) { - - // - // No more characters, get out of the - // loop. - // - - break; - - } - - if ((tempLSR & ~(SERIAL_LSR_THRE | SERIAL_LSR_TEMT | - SERIAL_LSR_DR)) && - Extension->EscapeChar) { - - // - // An error was indicated and inserted into the - // stream, get out of the loop. - // - - break; - } - - } WHILE (TRUE); - - break; - - } - - case SERIAL_IIR_THR: { - -doTrasmitStuff:; - Extension->HoldingEmpty = TRUE; - - if (Extension->WriteLength || - Extension->TransmitImmediate || - Extension->SendXoffChar || - Extension->SendXonChar) { - - // - // Even though all of the characters being - // sent haven't all been sent, this variable - // will be checked when the transmit queue is - // empty. If it is still true and there is a - // wait on the transmit queue being empty then - // we know we finished transmitting all characters - // following the initiation of the wait since - // the code that initiates the wait will set - // this variable to false. - // - // One reason it could be false is that - // the writes were cancelled before they - // actually started, or that the writes - // failed due to timeouts. This variable - // basically says a character was written - // by the isr at some point following the - // initiation of the wait. - // - - Extension->EmptiedTransmit = TRUE; - - // - // If we have output flow control based on - // the modem status lines, then we have to do - // all the modem work before we output each - // character. (Otherwise we might miss a - // status line change.) - // - - if (Extension->HandFlow.ControlHandShake & - SERIAL_OUT_HANDSHAKEMASK) { - - SerialHandleModemUpdate( - Extension, - TRUE - ); - - } - - // - // We can only send the xon character if - // the only reason we are holding is because - // of the xoff. (Hardware flow control or - // sending break preclude putting a new character - // on the wire.) - // - - if (Extension->SendXonChar && - !(Extension->TXHolding & ~SERIAL_TX_XOFF)) { - - if ((Extension->HandFlow.FlowReplace & - SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - // - // We have to raise if we're sending - // this character. - // - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - - WRITE_TRANSMIT_HOLDING(Extension, Extension->Controller, - Extension->SpecialChars.XonChar); - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - - } else { - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - Extension->SpecialChars.XonChar); - } - - - Extension->SendXonChar = FALSE; - Extension->HoldingEmpty = FALSE; - - // - // If we send an xon, by definition we - // can't be holding by Xoff. - // - - Extension->TXHolding &= ~SERIAL_TX_XOFF; - - // - // If we are sending an xon char then - // by definition we can't be "holding" - // up reception by Xoff. - // - - Extension->RXHolding &= ~SERIAL_RX_XOFF; - - } else if (Extension->SendXoffChar && - !Extension->TXHolding) { - - if ((Extension->HandFlow.FlowReplace & - SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - // - // We have to raise if we're sending - // this character. - // - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - Extension->SpecialChars.XoffChar); - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } else { - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - Extension->SpecialChars.XoffChar); - - } - - // - // We can't be sending an Xoff character - // if the transmission is already held - // up because of Xoff. Therefore, if we - // are holding then we can't send the char. - // - - // - // If the application has set xoff continue - // mode then we don't actually stop sending - // characters if we send an xoff to the other - // side. - // - - if (!(Extension->HandFlow.FlowReplace & - SERIAL_XOFF_CONTINUE)) { - - Extension->TXHolding |= SERIAL_TX_XOFF; - - if ((Extension->HandFlow.FlowReplace & - SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } - - } - - Extension->SendXoffChar = FALSE; - Extension->HoldingEmpty = FALSE; - - // - // Even if transmission is being held - // up, we should still transmit an immediate - // character if all that is holding us - // up is xon/xoff (OS/2 rules). - // - - } else if (Extension->TransmitImmediate && - (!Extension->TXHolding || - (Extension->TXHolding == SERIAL_TX_XOFF) - )) { - - Extension->TransmitImmediate = FALSE; - - if ((Extension->HandFlow.FlowReplace & - SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - // - // We have to raise if we're sending - // this character. - // - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - Extension->ImmediateChar); - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } else { - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - Extension->ImmediateChar); - - } - - Extension->HoldingEmpty = FALSE; - - SerialInsertQueueDpc( - Extension->CompleteImmediateDpc - ); - - } else if (!Extension->TXHolding) { - - ULONG amountToWrite; - - if (Extension->FifoPresent) { - - amountToWrite = (Extension->TxFifoAmount < - Extension->WriteLength)? - Extension->TxFifoAmount: - Extension->WriteLength; - - } else { - - amountToWrite = 1; - - } - if ((Extension->HandFlow.FlowReplace & - SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - // - // We have to raise if we're sending - // this character. - // - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - if (amountToWrite == 1) { - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - *(Extension->WriteCurrentChar)); - - } else { - - Extension->PerfStats.TransmittedCount += - amountToWrite; - Extension->WmiPerfData.TransmittedCount += - amountToWrite; - WRITE_TRANSMIT_FIFO_HOLDING(Extension, - Extension->Controller, - Extension->WriteCurrentChar, - amountToWrite); - } - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } else { - - if (amountToWrite == 1) { - - Extension->PerfStats.TransmittedCount++; - Extension->WmiPerfData.TransmittedCount++; - WRITE_TRANSMIT_HOLDING(Extension, - Extension->Controller, - *(Extension->WriteCurrentChar)); - - } else { - - Extension->PerfStats.TransmittedCount += - amountToWrite; - Extension->WmiPerfData.TransmittedCount += - amountToWrite; - WRITE_TRANSMIT_FIFO_HOLDING(Extension, - Extension->Controller, - Extension->WriteCurrentChar, - amountToWrite); - - } - - } - - Extension->HoldingEmpty = FALSE; - Extension->WriteCurrentChar += amountToWrite; - Extension->WriteLength -= amountToWrite; - - if (!Extension->WriteLength) { - - // - // No More characters left. This - // write is complete. Take care - // when updating the information field, - // we could have an xoff counter masquerading - // as a write request. - // - reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); - - reqContext->Information = - (reqContext->MajorFunction == IRP_MJ_WRITE)? - (reqContext->Length): (1); - - SerialInsertQueueDpc( - Extension->CompleteWriteDpc - ); - - } - - } - - } - - break; - - } - - case SERIAL_IIR_MS: { - - SerialHandleModemUpdate( - Extension, - FALSE - ); - - break; - - } - - } - - } while (!((InterruptIdReg = - READ_INTERRUPT_ID_REG(Extension, Extension->Controller)) - & SERIAL_IIR_NO_INTERRUPT_PENDING)); - - // - // Besides catching the WINBOND and SMC chip problems this - // will also cause transmission to restart incase of an xon - // char being received. Don't remove. - // - - if (SerialProcessLSR(Extension) & SERIAL_LSR_THRE) { - - if (!Extension->TXHolding && - (Extension->WriteLength || - Extension->TransmitImmediate)) { - - goto doTrasmitStuff; - - } - - } - - } - - return ServicedAnInterrupt; - -} - -VOID -SerialPutChar( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN UCHAR CharToPut - ) - -/*++ - -Routine Description: - - This routine, which only runs at device level, takes care of - placing a character into the typeahead (receive) buffer. - -Arguments: - - Extension - The serial device extension. - -Return Value: - - None. - ---*/ - -{ - PREQUEST_CONTEXT reqContext = NULL; - - // - // If we have dsr sensitivity enabled then - // we need to check the modem status register - // to see if it has changed. - // - - if (Extension->HandFlow.ControlHandShake & - SERIAL_DSR_SENSITIVITY) { - - SerialHandleModemUpdate( - Extension, - FALSE - ); - - if (Extension->RXHolding & SERIAL_RX_DSR) { - - // - // We simply act as if we haven't - // seen the character if we have dsr - // sensitivity and the dsr line is low. - // - - return; - - } - - } - - // - // If the xoff counter is non-zero then decrement it. - // If the counter then goes to zero, complete that request. - // - - if (Extension->CountSinceXoff) { - - Extension->CountSinceXoff--; - - if (!Extension->CountSinceXoff) { - reqContext = SerialGetRequestContext(Extension->CurrentXoffRequest); - reqContext->Status = STATUS_SUCCESS; - reqContext->Information = 0; - SerialInsertQueueDpc( - Extension->XoffCountCompleteDpc - ); - - } - - } - - // - // Check to see if we are copying into the - // users buffer or into the interrupt buffer. - // - // If we are copying into the user buffer - // then we know there is always room for one more. - // (We know this because if there wasn't room - // then that read would have completed and we - // would be using the interrupt buffer.) - // - // If we are copying into the interrupt buffer - // then we will need to check if we have enough - // room. - // - - if (Extension->ReadBufferBase != - Extension->InterruptReadBuffer) { - - // - // Increment the following value so - // that the interval timer (if one exists - // for this read) can know that a character - // has been read. - // - - Extension->ReadByIsr++; - - // - // We are in the user buffer. Place the - // character into the buffer. See if the - // read is complete. - // - - *Extension->CurrentCharSlot = CharToPut; - - if (Extension->CurrentCharSlot == - Extension->LastCharSlot) { - - // - // We've filled up the users buffer. - // Switch back to the interrupt buffer - // and send off a DPC to Complete the read. - // - // It is inherent that when we were using - // a user buffer that the interrupt buffer - // was empty. - // - - Extension->ReadBufferBase = - Extension->InterruptReadBuffer; - Extension->CurrentCharSlot = - Extension->InterruptReadBuffer; - Extension->FirstReadableChar = - Extension->InterruptReadBuffer; - Extension->LastCharSlot = - Extension->InterruptReadBuffer + - (Extension->BufferSize - 1); - Extension->CharsInInterruptBuffer = 0; - reqContext = SerialGetRequestContext(Extension->CurrentReadRequest); - reqContext->Information = reqContext->Length; - - SerialInsertQueueDpc( - Extension->CompleteReadDpc - ); - - } else { - - // - // Not done with the users read. - // - - Extension->CurrentCharSlot++; - - } - - } else { - - // - // We need to see if we reached our flow - // control threshold. If we have then - // we turn on whatever flow control the - // owner has specified. If no flow - // control was specified, well..., we keep - // trying to receive characters and hope that - // we have enough room. Note that no matter - // what flow control protocol we are using, it - // will not prevent us from reading whatever - // characters are available. - // - - if ((Extension->HandFlow.ControlHandShake - & SERIAL_DTR_MASK) == - SERIAL_DTR_HANDSHAKE) { - - // - // If we are already doing a - // dtr hold then we don't have - // to do anything else. - // - - if (!(Extension->RXHolding & - SERIAL_RX_DTR)) { - - if ((Extension->BufferSize - - Extension->HandFlow.XoffLimit) - <= (Extension->CharsInInterruptBuffer+1)) { - - Extension->RXHolding |= SERIAL_RX_DTR; - - SerialClrDTR(Extension->WdfInterrupt, Extension); - - } - - } - - } - - if ((Extension->HandFlow.FlowReplace - & SERIAL_RTS_MASK) == - SERIAL_RTS_HANDSHAKE) { - - // - // If we are already doing a - // rts hold then we don't have - // to do anything else. - // - - if (!(Extension->RXHolding & - SERIAL_RX_RTS)) { - - if ((Extension->BufferSize - - Extension->HandFlow.XoffLimit) - <= (Extension->CharsInInterruptBuffer+1)) { - - Extension->RXHolding |= SERIAL_RX_RTS; - - SerialClrRTS(Extension->WdfInterrupt, Extension); - - } - - } - - } - - if (Extension->HandFlow.FlowReplace & - SERIAL_AUTO_RECEIVE) { - - // - // If we are already doing a - // xoff hold then we don't have - // to do anything else. - // - - if (!(Extension->RXHolding & - SERIAL_RX_XOFF)) { - - if ((Extension->BufferSize - - Extension->HandFlow.XoffLimit) - <= (Extension->CharsInInterruptBuffer+1)) { - - Extension->RXHolding |= SERIAL_RX_XOFF; - - // - // If necessary cause an - // off to be sent. - // - - SerialProdXonXoff( - Extension, - FALSE - ); - - } - - } - - } - - if (Extension->CharsInInterruptBuffer < - Extension->BufferSize) { - - *Extension->CurrentCharSlot = CharToPut; - Extension->CharsInInterruptBuffer++; - - // - // If we've become 80% full on this character - // and this is an interesting event, note it. - // - - if (Extension->CharsInInterruptBuffer == - Extension->BufferSizePt8) { - - if (Extension->IsrWaitMask & - SERIAL_EV_RX80FULL) { - - Extension->HistoryMask |= SERIAL_EV_RX80FULL; - - if (Extension->IrpMaskLocation) { - - *Extension->IrpMaskLocation = - Extension->HistoryMask; - Extension->IrpMaskLocation = NULL; - Extension->HistoryMask = 0; - - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - reqContext->Information = sizeof(ULONG); - SerialInsertQueueDpc( - Extension->CommWaitDpc - ); - - } - - } - - } - - // - // Point to the next available space - // for a received character. Make sure - // that we wrap around to the beginning - // of the buffer if this last character - // received was placed at the last slot - // in the buffer. - // - - if (Extension->CurrentCharSlot == - Extension->LastCharSlot) { - - Extension->CurrentCharSlot = - Extension->InterruptReadBuffer; - - } else { - - Extension->CurrentCharSlot++; - - } - - } else { - - // - // We have a new character but no room for it. - // - - Extension->PerfStats.BufferOverrunErrorCount++; - Extension->WmiPerfData.BufferOverrunErrorCount++; - Extension->ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN; - - if (Extension->HandFlow.FlowReplace & - SERIAL_ERROR_CHAR) { - - // - // Place the error character into the last - // valid place for a character. Be careful!, - // that place might not be the previous location! - // - - if (Extension->CurrentCharSlot == - Extension->InterruptReadBuffer) { - - *(Extension->InterruptReadBuffer+ - (Extension->BufferSize-1)) = - Extension->SpecialChars.ErrorChar; - - } else { - - *(Extension->CurrentCharSlot-1) = - Extension->SpecialChars.ErrorChar; - - } - - } - - // - // If the application has requested it, abort all reads - // and writes on an error. - // - - if (Extension->HandFlow.ControlHandShake & - SERIAL_ERROR_ABORT) { - - SerialInsertQueueDpc( - Extension->CommErrorDpc - ); - - } - - } - - } - -} - -UCHAR -SerialProcessLSR( - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - This routine, which only runs at device level, reads the - ISR and totally processes everything that might have - changed. - -Arguments: - - Extension - The serial device extension. - -Return Value: - - The value of the line status register. - ---*/ - -{ - PREQUEST_CONTEXT reqContext = NULL; - - UCHAR LineStatus = READ_LINE_STATUS(Extension, Extension->Controller); - - - Extension->HoldingEmpty = (LineStatus & SERIAL_LSR_THRE) ? TRUE : FALSE; - - // - // If the line status register is just the fact that - // the trasmit registers are empty or a character is - // received then we want to reread the interrupt - // identification register so that we just pick up that. - // - - if (LineStatus & ~(SERIAL_LSR_THRE | SERIAL_LSR_TEMT - | SERIAL_LSR_DR)) { - - // - // We have some sort of data problem in the receive. - // For any of these errors we may abort all current - // reads and writes. - // - // - // If we are inserting the value of the line status - // into the data stream then we should put the escape - // character in now. - // - - if (Extension->EscapeChar) { - - SerialPutChar( - Extension, - Extension->EscapeChar - ); - - SerialPutChar( - Extension, - (UCHAR)((LineStatus & SERIAL_LSR_DR)? - (SERIAL_LSRMST_LSR_DATA):(SERIAL_LSRMST_LSR_NODATA)) - ); - - SerialPutChar( - Extension, - LineStatus - ); - - if (LineStatus & SERIAL_LSR_DR) { - - Extension->PerfStats.ReceivedCount++; - Extension->WmiPerfData.ReceivedCount++; - SerialPutChar( - Extension, - READ_RECEIVE_BUFFER(Extension, Extension->Controller) - ); - - } - - } - - if (LineStatus & SERIAL_LSR_OE) { - - Extension->PerfStats.SerialOverrunErrorCount++; - Extension->WmiPerfData.SerialOverrunErrorCount++; - Extension->ErrorWord |= SERIAL_ERROR_OVERRUN; - - if (Extension->HandFlow.FlowReplace & - SERIAL_ERROR_CHAR) { - - SerialPutChar( - Extension, - Extension->SpecialChars.ErrorChar - ); - - if (LineStatus & SERIAL_LSR_DR) { - - Extension->PerfStats.ReceivedCount++; - Extension->WmiPerfData.ReceivedCount++; - READ_RECEIVE_BUFFER(Extension, Extension->Controller); - - } - - } else { - - if (LineStatus & SERIAL_LSR_DR) { - - Extension->PerfStats.ReceivedCount++; - Extension->WmiPerfData.ReceivedCount++; - SerialPutChar( - Extension, - READ_RECEIVE_BUFFER(Extension, - Extension->Controller - ) - ); - - } - - } - - } - - if (LineStatus & SERIAL_LSR_BI) { - - Extension->ErrorWord |= SERIAL_ERROR_BREAK; - - if (Extension->HandFlow.FlowReplace & - SERIAL_BREAK_CHAR) { - - SerialPutChar( - Extension, - Extension->SpecialChars.BreakChar - ); - - } - - } else { - - // - // Framing errors only count if they - // occur exclusive of a break being - // received. - // - - if (LineStatus & SERIAL_LSR_PE) { - - Extension->PerfStats.ParityErrorCount++; - Extension->WmiPerfData.ParityErrorCount++; - Extension->ErrorWord |= SERIAL_ERROR_PARITY; - - if (Extension->HandFlow.FlowReplace & - SERIAL_ERROR_CHAR) { - - SerialPutChar( - Extension, - Extension->SpecialChars.ErrorChar - ); - - if (LineStatus & SERIAL_LSR_DR) { - - Extension->PerfStats.ReceivedCount++; - Extension->WmiPerfData.ReceivedCount++; - READ_RECEIVE_BUFFER(Extension, Extension->Controller); - - } - - } - - } - - if (LineStatus & SERIAL_LSR_FE) { - - Extension->PerfStats.FrameErrorCount++; - Extension->WmiPerfData.FrameErrorCount++; - Extension->ErrorWord |= SERIAL_ERROR_FRAMING; - - if (Extension->HandFlow.FlowReplace & - SERIAL_ERROR_CHAR) { - - SerialPutChar( - Extension, - Extension->SpecialChars.ErrorChar - ); - if (LineStatus & SERIAL_LSR_DR) { - - Extension->PerfStats.ReceivedCount++; - Extension->WmiPerfData.ReceivedCount++; - READ_RECEIVE_BUFFER(Extension, Extension->Controller); - - } - - } - - } - - } - - // - // If the application has requested it, - // abort all the reads and writes - // on an error. - // - - if (Extension->HandFlow.ControlHandShake & - SERIAL_ERROR_ABORT) { - - SerialInsertQueueDpc( - Extension->CommErrorDpc - ); - - } - - // - // Check to see if we have a wait - // pending on the comm error events. If we - // do then we schedule a dpc to satisfy - // that wait. - // - - if (Extension->IsrWaitMask) { - - if ((Extension->IsrWaitMask & SERIAL_EV_ERR) && - (LineStatus & (SERIAL_LSR_OE | - SERIAL_LSR_PE | - SERIAL_LSR_FE))) { - - Extension->HistoryMask |= SERIAL_EV_ERR; - - } - - if ((Extension->IsrWaitMask & SERIAL_EV_BREAK) && - (LineStatus & SERIAL_LSR_BI)) { - - Extension->HistoryMask |= SERIAL_EV_BREAK; - - } - - if (Extension->IrpMaskLocation && - Extension->HistoryMask) { - - *Extension->IrpMaskLocation = - Extension->HistoryMask; - Extension->IrpMaskLocation = NULL; - Extension->HistoryMask = 0; - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - reqContext->Information = sizeof(ULONG); - SerialInsertQueueDpc( - Extension->CommWaitDpc - ); - - } - - } - - if (LineStatus & SERIAL_LSR_THRE) { - - // - // There is a hardware bug in some versions - // of the 16450 and 550. If THRE interrupt - // is pending, but a higher interrupt comes - // in it will only return the higher and - // *forget* about the THRE. - // - // A suitable workaround - whenever we - // are *all* done reading line status - // of the device we check to see if the - // transmit holding register is empty. If it is - // AND we are currently transmitting data - // enable the interrupts which should cause - // an interrupt indication which we quiet - // when we read the interrupt id register. - // - - if (Extension->WriteLength | - Extension->TransmitImmediate) { - - DISABLE_ALL_INTERRUPTS(Extension, - Extension->Controller - ); - ENABLE_ALL_INTERRUPTS(Extension, - Extension->Controller - ); - } - - } - - } - - return LineStatus; -} - - diff --git a/tests/projects/wdk/kmdf/serial/log.c b/tests/projects/wdk/kmdf/serial/log.c deleted file mode 100644 index 285c8b2f8..000000000 --- a/tests/projects/wdk/kmdf/serial/log.c +++ /dev/null @@ -1,97 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - log.c - -Abstract: - - Debug log Code for serial. - -Environment: - - kernel mode only - ---*/ - -#include "precomp.h" - -extern ULONG DebugLevel; -extern ULONG DebugFlag; - -#if !defined(EVENT_TRACING) - -VOID -SerialDbgPrintEx ( - IN ULONG TraceEventsLevel, - IN ULONG TraceEventsFlag, - IN PCCHAR DebugMessage, - ... - ) - -/*++ - -Routine Description: - - Debug print for the sample driver. - -Arguments: - - TraceEventsLevel - print level between 0 and 3, with 3 the most verbose - -Return Value: - - None. - - --*/ - { -#if DBG - -#define TEMP_BUFFER_SIZE 1024 - - va_list list; - CHAR debugMessageBuffer [TEMP_BUFFER_SIZE]; - NTSTATUS status; - - va_start(list, DebugMessage); - - if (DebugMessage) { - - // - // Using new safe string functions instead of _vsnprintf. - // This function takes care of NULL terminating if the message - // is longer than the buffer. - // - status = RtlStringCbVPrintfA( debugMessageBuffer, - sizeof(debugMessageBuffer), - DebugMessage, - list ); - if(!NT_SUCCESS(status)) { - - KdPrint((_DRIVER_NAME_": RtlStringCbVPrintfA failed %x\n", status)); - return; - } - if (TraceEventsLevel < TRACE_LEVEL_INFORMATION || - (TraceEventsLevel <= DebugLevel && - ((TraceEventsFlag & DebugFlag) == TraceEventsFlag))) { - - KdPrint((debugMessageBuffer)); - } - } - va_end(list); - - return; - -#else - - UNREFERENCED_PARAMETER(TraceEventsLevel); - UNREFERENCED_PARAMETER(TraceEventsFlag); - UNREFERENCED_PARAMETER(DebugMessage); - -#endif -} - -#endif - diff --git a/tests/projects/wdk/kmdf/serial/log.h b/tests/projects/wdk/kmdf/serial/log.h deleted file mode 100644 index eedcd08f3..000000000 --- a/tests/projects/wdk/kmdf/serial/log.h +++ /dev/null @@ -1,37 +0,0 @@ -/*++ - -Copyright (c) 1993 Microsoft Corporation -:ts=4 - -Module Name: - - log.h - -Abstract: - - debug macros - -Environment: - - Kernel & user mode - ---*/ - -#ifndef __LOG_H__ -#define __LOG_H__ - -#if !defined(EVENT_TRACING) - -VOID -SerialDbgPrintEx ( - IN ULONG DebugPrintLevel, - IN ULONG DebugPrintFlag, - IN PCCHAR DebugMessage, - ... - ); - -#endif - -#endif // __LOG_H__ - - diff --git a/tests/projects/wdk/kmdf/serial/modmflow.c b/tests/projects/wdk/kmdf/serial/modmflow.c deleted file mode 100644 index 1c71ae3fd..000000000 --- a/tests/projects/wdk/kmdf/serial/modmflow.c +++ /dev/null @@ -1,1714 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - modmflow.c - -Abstract: - - This module contains *MOST* of the code used to manipulate - the modem control and status registers. The vast majority - of the remainder of flow control is concentrated in the - Interrupt service routine. A very small amount resides - in the read code that pull characters out of the interrupt - buffer. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "modmflow.tmh" -#endif - - -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialDecrementRTSCounter; - -BOOLEAN -SerialSetDTR( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine which is only called at interrupt level is used - to set the DTR in the modem control register. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = Context; - UCHAR ModemControl; - - UNREFERENCED_PARAMETER(Interrupt); - - ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); - - ModemControl |= SERIAL_MCR_DTR; - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, - "Setting DTR for %p\n", Extension->Controller); - - WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); - - return FALSE; - -} - -BOOLEAN -SerialClrDTR( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine which is only called at interrupt level is used - to clear the DTR in the modem control register. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - UCHAR ModemControl; - - UNREFERENCED_PARAMETER(Interrupt); - - ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); - - ModemControl &= ~SERIAL_MCR_DTR; - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing DTR for %p\n", Extension->Controller); - - WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); - - return FALSE; - -} - -BOOLEAN -SerialSetRTS( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine which is only called at interrupt level is used - to set the RTS in the modem control register. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - UCHAR ModemControl; - - UNREFERENCED_PARAMETER(Interrupt); - - ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); - - ModemControl |= SERIAL_MCR_RTS; - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Setting Rts for %p\n", Extension->Controller); - - WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); - - return FALSE; - -} - -BOOLEAN -SerialClrRTS( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine which is only called at interrupt level is used - to clear the RTS in the modem control register. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - UCHAR ModemControl; - - UNREFERENCED_PARAMETER(Interrupt); - - ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); - - ModemControl &= ~SERIAL_MCR_RTS; - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing Rts for %p\n", Extension->Controller); - - WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); - - return FALSE; - -} - -BOOLEAN -SerialSetupNewHandFlow( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN PSERIAL_HANDFLOW NewHandFlow - ) - -/*++ - -Routine Description: - - This routine adjusts the flow control based on new - control flow. - -Arguments: - - Extension - A pointer to the serial device extension. - - NewHandFlow - A pointer to a serial handflow structure - that is to become the new setup for flow - control. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - SERIAL_HANDFLOW New = *NewHandFlow; - - // - // If the Extension->DeviceIsOpened is FALSE that means - // we are entering this routine in response to an open request. - // If that is so, then we always proceed with the work regardless - // of whether things have changed. - // - - // - // First we take care of the DTR flow control. We only - // do work if something has changed. - // - - if ((!Extension->DeviceIsOpened) || - ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) != - (New.ControlHandShake & SERIAL_DTR_MASK))) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Processing DTR flow for %p\n", - Extension->Controller); - - if (New.ControlHandShake & SERIAL_DTR_MASK) { - - // - // Well we might want to set DTR. - // - // Before we do, we need to check whether we are doing - // dtr flow control. If we are then we need to check - // if then number of characters in the interrupt buffer - // exceeds the XoffLimit. If it does then we don't - // enable DTR AND we set the RXHolding to record that - // we are holding because of the dtr. - // - - if ((New.ControlHandShake & SERIAL_DTR_MASK) - == SERIAL_DTR_HANDSHAKE) { - - if ((Extension->BufferSize - New.XoffLimit) > - Extension->CharsInInterruptBuffer) { - - // - // However if we are already holding we don't want - // to turn it back on unless we exceed the Xon - // limit. - // - - if (Extension->RXHolding & SERIAL_RX_DTR) { - - // - // We can assume that its DTR line is already low. - // - - if (Extension->CharsInInterruptBuffer > - (ULONG)New.XonLimit) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Removing DTR block on " - "reception for %p\n", - Extension->Controller); - - Extension->RXHolding &= ~SERIAL_RX_DTR; - SerialSetDTR(Extension->WdfInterrupt, Extension); - - } - - } else { - - SerialSetDTR(Extension->WdfInterrupt, Extension); - - } - - } else { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Setting DTR block on reception " - "for %p\n", Extension->Controller); - Extension->RXHolding |= SERIAL_RX_DTR; - SerialClrDTR(Extension->WdfInterrupt, Extension); - - } - - } else { - - // - // Note that if we aren't currently doing dtr flow control then - // we MIGHT have been. So even if we aren't currently doing - // DTR flow control, we should still check if RX is holding - // because of DTR. If it is, then we should clear the holding - // of this bit. - // - - if (Extension->RXHolding & SERIAL_RX_DTR) { - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Removing dtr block of reception " - "for %p\n", Extension->Controller); - Extension->RXHolding &= ~SERIAL_RX_DTR; - } - - SerialSetDTR(Extension->WdfInterrupt, Extension); - - } - - } else { - - // - // The end result here will be that DTR is cleared. - // - // We first need to check whether reception is being held - // up because of previous DTR flow control. If it is then - // we should clear that reason in the RXHolding mask. - // - - if (Extension->RXHolding & SERIAL_RX_DTR) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "removing dtr block of reception for" - " %p\n", Extension->Controller); - Extension->RXHolding &= ~SERIAL_RX_DTR; - - } - - SerialClrDTR(Extension->WdfInterrupt, Extension); - - } - - } - - // - // Time to take care of the RTS Flow control. - // - // First we only do work if something has changed. - // - - if ((!Extension->DeviceIsOpened) || - ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) != - (New.FlowReplace & SERIAL_RTS_MASK))) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Processing RTS flow %p\n", - Extension->Controller); - - if ((New.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_RTS_HANDSHAKE) { - - // - // Well we might want to set RTS. - // - // Before we do, we need to check whether we are doing - // rts flow control. If we are then we need to check - // if then number of characters in the interrupt buffer - // exceeds the XoffLimit. If it does then we don't - // enable RTS AND we set the RXHolding to record that - // we are holding because of the rts. - // - - if ((Extension->BufferSize - New.XoffLimit) > - Extension->CharsInInterruptBuffer) { - - // - // However if we are already holding we don't want - // to turn it back on unless we exceed the Xon - // limit. - // - - if (Extension->RXHolding & SERIAL_RX_RTS) { - - // - // We can assume that its RTS line is already low. - // - - if (Extension->CharsInInterruptBuffer > - (ULONG)New.XonLimit) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Removing rts block of " - "reception for %p\n", - Extension->Controller); - Extension->RXHolding &= ~SERIAL_RX_RTS; - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } - - } else { - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } - - } else { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Setting rts block of reception for " - "%p\n", Extension->Controller); - Extension->RXHolding |= SERIAL_RX_RTS; - SerialClrRTS(Extension->WdfInterrupt, Extension); - - } - - } else if ((New.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_RTS_CONTROL) { - - // - // Note that if we aren't currently doing rts flow control then - // we MIGHT have been. So even if we aren't currently doing - // RTS flow control, we should still check if RX is holding - // because of RTS. If it is, then we should clear the holding - // of this bit. - // - - if (Extension->RXHolding & SERIAL_RX_RTS) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing rts block of reception for " - "%p\n", Extension->Controller); - Extension->RXHolding &= ~SERIAL_RX_RTS; - - } - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } else if ((New.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - // - // We first need to check whether reception is being held - // up because of previous RTS flow control. If it is then - // we should clear that reason in the RXHolding mask. - // - - if (Extension->RXHolding & SERIAL_RX_RTS) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "TOGGLE Clearing rts block of " - "reception for %p\n", Extension->Controller); - Extension->RXHolding &= ~SERIAL_RX_RTS; - - } - - // - // We have to place the rts value into the Extension - // now so that the code that tests whether the - // rts line should be lowered will find that we - // are "still" doing transmit toggling. The code - // for lowering can be invoked later by a timer so - // it has to test whether it still needs to do its - // work. - // - - Extension->HandFlow.FlowReplace &= ~SERIAL_RTS_MASK; - Extension->HandFlow.FlowReplace |= SERIAL_TRANSMIT_TOGGLE; - - // - // The order of the tests is very important below. - // - // If there is a break then we should turn on the RTS. - // - // If there isn't a break but there are characters in - // the hardware, then turn on the RTS. - // - // If there are writes pending that aren't being held - // up, then turn on the RTS. - // - - if ((Extension->TXHolding & SERIAL_TX_BREAK) || - ((SerialProcessLSR(Extension) & (SERIAL_LSR_THRE | - SERIAL_LSR_TEMT)) != - (SERIAL_LSR_THRE | - SERIAL_LSR_TEMT)) || - (Extension->CurrentWriteRequest || Extension->TransmitImmediate || - (!IsQueueEmpty(Extension->WriteQueue)) && - (!Extension->TXHolding))) { - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } else { - - // - // This routine will check to see if it is time - // to lower the RTS because of transmit toggle - // being on. If it is ok to lower it, it will, - // if it isn't ok, it will schedule things so - // that it will get lowered later. - // - - Extension->CountOfTryingToLowerRTS++; - SerialPerhapsLowerRTS(Extension->WdfInterrupt, Extension); - - } - - } else { - - // - // The end result here will be that RTS is cleared. - // - // We first need to check whether reception is being held - // up because of previous RTS flow control. If it is then - // we should clear that reason in the RXHolding mask. - // - - if (Extension->RXHolding & SERIAL_RX_RTS) { - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing rts block of reception for" - " %p\n", Extension->Controller); - Extension->RXHolding &= ~SERIAL_RX_RTS; - - } - - SerialClrRTS(Extension->WdfInterrupt, Extension); - - } - - } - - // - // We now take care of automatic receive flow control. - // We only do work if things have changed. - // - - if ((!Extension->DeviceIsOpened) || - ((Extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) != - (New.FlowReplace & SERIAL_AUTO_RECEIVE))) { - - if (New.FlowReplace & SERIAL_AUTO_RECEIVE) { - - // - // We wouldn't be here if it had been on before. - // - // We should check to see whether we exceed the turn - // off limits. - // - // Note that since we are following the OS/2 flow - // control rules we will never send an xon if - // when enabling xon/xoff flow control we discover that - // we could receive characters but we are held up do - // to a previous Xoff. - // - - if ((Extension->BufferSize - New.XoffLimit) <= - Extension->CharsInInterruptBuffer) { - - // - // Cause the Xoff to be sent. - // - - Extension->RXHolding |= SERIAL_RX_XOFF; - - SerialProdXonXoff( - Extension, - FALSE - ); - - } - - } else { - - // - // The app has disabled automatic receive flow control. - // - // If transmission was being held up because of - // an automatic receive Xoff, then we should - // cause an Xon to be sent. - // - - if (Extension->RXHolding & SERIAL_RX_XOFF) { - - Extension->RXHolding &= ~SERIAL_RX_XOFF; - - // - // Cause the Xon to be sent. - // - - SerialProdXonXoff( - Extension, - TRUE - ); - - } - - } - - } - - // - // We now take care of automatic transmit flow control. - // We only do work if things have changed. - // - - if ((!Extension->DeviceIsOpened) || - ((Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT) != - (New.FlowReplace & SERIAL_AUTO_TRANSMIT))) { - - if (New.FlowReplace & SERIAL_AUTO_TRANSMIT) { - - // - // We wouldn't be here if it had been on before. - // - // There is some belief that if autotransmit - // was just enabled, I should go look in what we - // already received, and if we find the xoff character - // then we should stop transmitting. I think this - // is an application bug. For now we just care about - // what we see in the future. - // - - ; - - } else { - - // - // The app has disabled automatic transmit flow control. - // - // If transmission was being held up because of - // an automatic transmit Xoff, then we should - // cause an Xon to be sent. - // - - if (Extension->TXHolding & SERIAL_TX_XOFF) { - - Extension->TXHolding &= ~SERIAL_TX_XOFF; - - // - // Cause the Xon to be sent. - // - - SerialProdXonXoff( - Extension, - TRUE - ); - - } - - } - - } - - // - // At this point we can simply make sure that entire - // handflow structure in the extension is updated. - // - - Extension->HandFlow = New; - - return FALSE; - -} - -BOOLEAN -SerialSetHandFlow( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to set the handshake and control - flow in the device extension. - -Arguments: - - Context - Pointer to a structure that contains a pointer to - the device extension and a pointer to a handflow - structure.. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_IOCTL_SYNC S = Context; - PSERIAL_DEVICE_EXTENSION Extension = S->Extension; - PSERIAL_HANDFLOW HandFlow = S->Data; - - UNREFERENCED_PARAMETER(Interrupt); - - SerialSetupNewHandFlow( - Extension, - HandFlow - ); - - SerialHandleModemUpdate( - Extension, - FALSE - ); - - return FALSE; - -} - -BOOLEAN -SerialTurnOnBreak( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine will turn on break in the hardware and - record the fact the break is on, in the extension variable - that holds reasons that transmission is stopped. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UCHAR OldLineControl; - - UNREFERENCED_PARAMETER(Interrupt); - - if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } - - OldLineControl = READ_LINE_CONTROL(Extension, Extension->Controller); - - OldLineControl |= SERIAL_LCR_BREAK; - - WRITE_LINE_CONTROL(Extension, - Extension->Controller, - OldLineControl - ); - - Extension->TXHolding |= SERIAL_TX_BREAK; - - return FALSE; - -} - -BOOLEAN -SerialTurnOffBreak( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine will turn off break in the hardware and - record the fact the break is off, in the extension variable - that holds reasons that transmission is stopped. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UCHAR OldLineControl; - - UNREFERENCED_PARAMETER(Interrupt); - - if (Extension->TXHolding & SERIAL_TX_BREAK) { - - // - // We actually have a good reason for testing if transmission - // is holding instead of blindly clearing the bit. - // - // If transmission actually was holding and the result of - // clearing the bit is that we should restart transmission - // then we will poke the interrupt enable bit, which will - // cause an actual interrupt and transmission will then - // restart on its own. - // - // If transmission wasn't holding and we poked the bit - // then we would interrupt before a character actually made - // it out and we could end up over writing a character in - // the transmission hardware. - - OldLineControl = READ_LINE_CONTROL(Extension, Extension->Controller); - - OldLineControl &= ~SERIAL_LCR_BREAK; - - WRITE_LINE_CONTROL(Extension, - Extension->Controller, - OldLineControl - ); - - Extension->TXHolding &= ~SERIAL_TX_BREAK; - - if (!Extension->TXHolding && - (Extension->TransmitImmediate || - Extension->WriteLength) && - Extension->HoldingEmpty) { - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - - } else { - - // - // The following routine will lower the rts if we - // are doing transmit toggleing and there is no - // reason to keep it up. - // - - Extension->CountOfTryingToLowerRTS++; - SerialPerhapsLowerRTS(Extension->WdfInterrupt, Extension); - - } - - } - - return FALSE; - -} - -BOOLEAN -SerialPretendXoff( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to process the Ioctl that request the - driver to act as if an Xoff was received. Even if the - driver does not have automatic Xoff/Xon flowcontrol - This - still will stop the transmission. This is the OS/2 behavior - and is not well specified for Windows. Therefore we adopt - the OS/2 behavior. - - Note: If the driver does not have automatic Xoff/Xon enabled - then the only way to restart transmission is for the - application to request we "act" as if we saw the xon. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - Extension->TXHolding |= SERIAL_TX_XOFF; - - if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } - - return FALSE; - -} - -BOOLEAN -SerialPretendXon( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to process the Ioctl that request the - driver to act as if an Xon was received. - - Note: If the driver does not have automatic Xoff/Xon enabled - then the only way to restart transmission is for the - application to request we "act" as if we saw the xon. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - if (Extension->TXHolding) { - - // - // We actually have a good reason for testing if transmission - // is holding instead of blindly clearing the bit. - // - // If transmission actually was holding and the result of - // clearing the bit is that we should restart transmission - // then we will poke the interrupt enable bit, which will - // cause an actual interrupt and transmission will then - // restart on its own. - // - // If transmission wasn't holding and we poked the bit - // then we would interrupt before a character actually made - // it out and we could end up over writing a character in - // the transmission hardware. - - Extension->TXHolding &= ~SERIAL_TX_XOFF; - - if (!Extension->TXHolding && - (Extension->TransmitImmediate || - Extension->WriteLength) && - Extension->HoldingEmpty) { - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - - } - - } - - return FALSE; - -} - -VOID -SerialHandleReducedIntBuffer( - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - This routine is called to handle a reduction in the number - of characters in the interrupt (typeahead) buffer. It - will check the current output flow control and re-enable transmission - as needed. - - NOTE: This routine assumes that it is working at interrupt level. - -Arguments: - - Extension - A pointer to the device extension. - -Return Value: - - None. - ---*/ - -{ - - - // - // If we are doing receive side flow control and we are - // currently "holding" then because we've emptied out - // some characters from the interrupt buffer we need to - // see if we can "re-enable" reception. - // - - if (Extension->RXHolding) { - - if (Extension->CharsInInterruptBuffer <= - (ULONG)Extension->HandFlow.XonLimit) { - - if (Extension->RXHolding & SERIAL_RX_DTR) { - - Extension->RXHolding &= ~SERIAL_RX_DTR; - SerialSetDTR(Extension->WdfInterrupt, Extension); - - } - - if (Extension->RXHolding & SERIAL_RX_RTS) { - - Extension->RXHolding &= ~SERIAL_RX_RTS; - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } - - if (Extension->RXHolding & SERIAL_RX_XOFF) { - - // - // Prod the transmit code to send xon. - // - - SerialProdXonXoff( - Extension, - TRUE - ); - - } - - } - - } - -} - -VOID -SerialProdXonXoff( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN BOOLEAN SendXon - ) - -/*++ - -Routine Description: - - This routine will set up the SendXxxxChar variables if - necessary and determine if we are going to be interrupting - because of current transmission state. It will cause an - interrupt to occur if neccessary, to send the xon/xoff char. - - NOTE: This routine assumes that it is called at interrupt - level. - -Arguments: - - Extension - A pointer to the serial device extension. - - SendXon - If a character is to be send, this indicates whether - it should be an Xon or an Xoff. - -Return Value: - - None. - ---*/ - -{ - - // - // We assume that if the prodding is called more than - // once that the last prod has set things up appropriately. - // - // We could get called before the character is sent out - // because the send of the character was blocked because - // of hardware flow control (or break). - // - - if (!Extension->SendXonChar && !Extension->SendXoffChar - && Extension->HoldingEmpty) { - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - - } - - if (SendXon) { - - Extension->SendXonChar = TRUE; - Extension->SendXoffChar = FALSE; - - } else { - - Extension->SendXonChar = FALSE; - Extension->SendXoffChar = TRUE; - - } - -} - -ULONG -SerialHandleModemUpdate( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN BOOLEAN DoingTX - ) - -/*++ - -Routine Description: - - This routine will be to check on the modem status, and - handle any appropriate event notification as well as - any flow control appropriate to modem status lines. - - NOTE: This routine assumes that it is called at interrupt - level. - -Arguments: - - Extension - A pointer to the serial device extension. - - DoingTX - This boolean is used to indicate that this call - came from the transmit processing code. If this - is true then there is no need to cause a new interrupt - since the code will be trying to send the next - character as soon as this call finishes. - -Return Value: - - This returns the old value of the modem status register - (extended into a ULONG). - ---*/ - -{ - - // - // We keep this local so that after we are done - // examining the modem status and we've updated - // the transmission holding value, we know whether - // we've changed from needing to hold up transmission - // to transmission being able to proceed. - // - ULONG OldTXHolding = Extension->TXHolding; - - // - // Holds the value in the mode status register. - // - UCHAR ModemStatus; - PREQUEST_CONTEXT reqContext; - - ModemStatus = - READ_MODEM_STATUS(Extension, Extension->Controller); - - - // - // If we are placeing the modem status into the data stream - // on every change, we should do it now. - // - - if (Extension->EscapeChar) { - - if (ModemStatus & (SERIAL_MSR_DCTS | - SERIAL_MSR_DDSR | - SERIAL_MSR_TERI | - SERIAL_MSR_DDCD)) { - - SerialPutChar( - Extension, - Extension->EscapeChar - ); - SerialPutChar( - Extension, - SERIAL_LSRMST_MST - ); - SerialPutChar( - Extension, - ModemStatus - ); - - } - - } - - - // - // Take care of input flow control based on sensitivity - // to the DSR. This is done so that the application won't - // see spurious data generated by odd devices. - // - // Basically, if we are doing dsr sensitivity then the - // driver should only accept data when the dsr bit is - // set. - // - - if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) { - - if (ModemStatus & SERIAL_MSR_DSR) { - - // - // The line is high. Simply make sure that - // RXHolding does't have the DSR bit. - // - - Extension->RXHolding &= ~SERIAL_RX_DSR; - - } else { - - Extension->RXHolding |= SERIAL_RX_DSR; - - } - - } else { - - // - // We don't have sensitivity due to DSR. Make sure we - // arn't holding. (We might have been, but the app just - // asked that we don't hold for this reason any more.) - // - - Extension->RXHolding &= ~SERIAL_RX_DSR; - - } - - // - // Check to see if we have a wait - // pending on the modem status events. If we - // do then we schedule a dpc to satisfy - // that wait. - // - - if (Extension->IsrWaitMask) { - - if ((Extension->IsrWaitMask & SERIAL_EV_CTS) && - (ModemStatus & SERIAL_MSR_DCTS)) { - - Extension->HistoryMask |= SERIAL_EV_CTS; - - } - - if ((Extension->IsrWaitMask & SERIAL_EV_DSR) && - (ModemStatus & SERIAL_MSR_DDSR)) { - - Extension->HistoryMask |= SERIAL_EV_DSR; - - } - - if ((Extension->IsrWaitMask & SERIAL_EV_RING) && - (ModemStatus & SERIAL_MSR_TERI)) { - - Extension->HistoryMask |= SERIAL_EV_RING; - - } - - if ((Extension->IsrWaitMask & SERIAL_EV_RLSD) && - (ModemStatus & SERIAL_MSR_DDCD)) { - - Extension->HistoryMask |= SERIAL_EV_RLSD; - - } - - if (Extension->IrpMaskLocation && - Extension->HistoryMask) { - - *Extension->IrpMaskLocation = - Extension->HistoryMask; - Extension->IrpMaskLocation = NULL; - Extension->HistoryMask = 0; - - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - reqContext->Information = sizeof(ULONG); - SerialInsertQueueDpc( - Extension->CommWaitDpc - ); - - } - - } - - // - // If the app has modem line flow control then - // we check to see if we have to hold up transmission. - // - - if (Extension->HandFlow.ControlHandShake & - SERIAL_OUT_HANDSHAKEMASK) { - - if (Extension->HandFlow.ControlHandShake & - SERIAL_CTS_HANDSHAKE) { - - if (ModemStatus & SERIAL_MSR_CTS) { - - Extension->TXHolding &= ~SERIAL_TX_CTS; - - } else { - - Extension->TXHolding |= SERIAL_TX_CTS; - - } - - } else { - - Extension->TXHolding &= ~SERIAL_TX_CTS; - - } - - if (Extension->HandFlow.ControlHandShake & - SERIAL_DSR_HANDSHAKE) { - - if (ModemStatus & SERIAL_MSR_DSR) { - - Extension->TXHolding &= ~SERIAL_TX_DSR; - - } else { - - Extension->TXHolding |= SERIAL_TX_DSR; - - } - - } else { - - Extension->TXHolding &= ~SERIAL_TX_DSR; - - } - - if (Extension->HandFlow.ControlHandShake & - SERIAL_DCD_HANDSHAKE) { - - if (ModemStatus & SERIAL_MSR_DCD) { - - Extension->TXHolding &= ~SERIAL_TX_DCD; - - } else { - - Extension->TXHolding |= SERIAL_TX_DCD; - - } - - } else { - - Extension->TXHolding &= ~SERIAL_TX_DCD; - - } - - // - // If we hadn't been holding, and now we are then - // queue off a dpc that will lower the RTS line - // if we are doing transmit toggling. - // - - if (!OldTXHolding && Extension->TXHolding && - ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE)) { - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - } - - // - // We've done any adjusting that needed to be - // done to the holding mask given updates - // to the modem status. If the Holding mask - // is clear (and it wasn't clear to start) - // and we have "write" work to do set things - // up so that the transmission code gets invoked. - // - - if (!DoingTX && OldTXHolding && !Extension->TXHolding) { - - if (!Extension->TXHolding && - (Extension->TransmitImmediate || - Extension->WriteLength) && - Extension->HoldingEmpty) { - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - } - - } - - } else { - - // - // We need to check if transmission is holding - // up because of modem status lines. What - // could have occured is that for some strange - // reason, the app has asked that we no longer - // stop doing output flow control based on - // the modem status lines. If however, we - // *had* been held up because of the status lines - // then we need to clear up those reasons. - // - - if (Extension->TXHolding & (SERIAL_TX_DCD | - SERIAL_TX_DSR | - SERIAL_TX_CTS)) { - - Extension->TXHolding &= ~(SERIAL_TX_DCD | - SERIAL_TX_DSR | - SERIAL_TX_CTS); - - - if (!DoingTX && OldTXHolding && !Extension->TXHolding) { - - if (!Extension->TXHolding && - (Extension->TransmitImmediate || - Extension->WriteLength) && - Extension->HoldingEmpty) { - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - } - - } - - } - - } - - return ((ULONG)ModemStatus); -} - -BOOLEAN -SerialPerhapsLowerRTS( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine checks that the software reasons for lowering - the RTS lines are present. If so, it will then cause the - line status register to be read (and any needed processing - implied by the status register to be done), and if the - shift register is empty it will lower the line. If the - shift register isn't empty, this routine will queue off - a dpc that will start a timer, that will basically call - us back to try again. - - NOTE: This routine assumes that it is called at interrupt - level. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - // - // We first need to test if we are actually still doing - // transmit toggle flow control. If we aren't then - // we have no reason to try be here. - // - - if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - // - // The order of the tests is very important below. - // - // If there is a break then we should leave on the RTS, - // because when the break is turned off, it will submit - // the code to shut down the RTS. - // - // If there are writes pending that aren't being held - // up, then leave on the RTS, because the end of the write - // code will cause this code to be reinvoked. If the writes - // are being held up, its ok to lower the RTS because the - // upon trying to write the first character after transmission - // is restarted, we will raise the RTS line. - // - - if ((Extension->TXHolding & SERIAL_TX_BREAK) || - (Extension->CurrentWriteRequest || Extension->TransmitImmediate || - (!IsQueueEmpty(Extension->WriteQueue)) && - (!Extension->TXHolding))) { - - NOTHING; - - } else { - - // - // Looks good so far. Call the line status check and processing - // code, it will return the "current" line status value. If - // the holding and shift register are clear, lower the RTS line, - // if they aren't clear, queue of a dpc that will cause a timer - // to reinvoke us later. We do this code here because no one - // but this routine cares about the characters in the hardware, - // so no routine by this routine will bother invoking to test - // if the hardware is empty. - // - - if ((SerialProcessLSR(Extension) & - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) != - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { - - // - // Well it's not empty, try again later. - // - - SerialInsertQueueDpc( - Extension->StartTimerLowerRTSDpc - )?Extension->CountOfTryingToLowerRTS++:0; - - - } else { - - // - // Nothing in the hardware, Lower the RTS. - // - - SerialClrRTS(Extension->WdfInterrupt, Extension); - - - } - - } - - } - - // - // We decement the counter to indicate that we've reached - // the end of the execution path that is trying to push - // down the RTS line. - // - - Extension->CountOfTryingToLowerRTS--; - - return FALSE; -} - -VOID -SerialStartTimerLowerRTS( - IN WDFDPC Dpc - ) - -/*++ - -Routine Description: - - This routine starts a timer that when it expires will start - a dpc that will check if it can lower the rts line because - there are no characters in the hardware. - -Arguments: - - Dpc - Not Used. - - DeferredContext - Really points to the device extension. - - SystemContext1 - Not Used. - - SystemContext2 - Not Used. - -Return Value: - - None. - ---*/ - -{ - LARGE_INTEGER CharTime; - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); - - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, ">SerialStartTimerLowerRTS(%p)\n", - Extension); - - - // - // Since all the callbacks into the driver are serialized, we don't have - // synchronize the access to any of the Extension variables. - // - - CharTime = SerialGetCharTime(Extension); - - CharTime.QuadPart = -CharTime.QuadPart; - - if (SerialSetTimer( - Extension->LowerRTSTimer, - CharTime - )) { - - // - // The timer was already in the timer queue. This implies - // that one path of execution that was trying to lower - // the RTS has "died". Synchronize with the ISR so that - // we can lower the count. - // - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialDecrementRTSCounter, - Extension - ); - - } - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "WdfInterrupt, - SerialPerhapsLowerRTS, - Extension - ); - -} - -BOOLEAN -SerialDecrementRTSCounter( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine checks that the software reasons for lowering - the RTS lines are present. If so, it will then cause the - line status register to be read (and any needed processing - implied by the status register to be done), and if the - shift register is empty it will lower the line. If the - shift register isn't empty, this routine will queue off - a dpc that will start a timer, that will basically call - us back to try again. - - NOTE: This routine assumes that it is called at interrupt - level. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - Extension->CountOfTryingToLowerRTS--; - - return FALSE; - -} - - diff --git a/tests/projects/wdk/kmdf/serial/openclos.c b/tests/projects/wdk/kmdf/serial/openclos.c deleted file mode 100644 index 477f07ac1..000000000 --- a/tests/projects/wdk/kmdf/serial/openclos.c +++ /dev/null @@ -1,850 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - openclos.c - -Abstract: - - This module contains the code that is very specific to - opening, closing, and cleaning up in the serial driver. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "openclos.tmh" -#endif - - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGESER,SerialGetCharTime) -#pragma alloc_text(PAGESER,SerialEvtFileClose) -#pragma alloc_text(PAGESER,SerialDrainUART) -#pragma alloc_text(PAGESRP0,SerialEvtDeviceFileCreate) -#pragma alloc_text(PAGESRP0,SerialCreateTimersAndDpcs) -#endif // ALLOC_PRAGMA - - - -VOID -SerialEvtDeviceFileCreate ( - IN WDFDEVICE Device, - IN WDFREQUEST Request, - IN WDFFILEOBJECT FileObject - ) -/*++ - -Routine Description: - - The framework calls a driver's EvtDeviceFileCreate callback - when the framework receives an IRP_MJ_CREATE request. - The system sends this request when a user application opens the - device to perform an I/O operation, such as reading or writing a file. - This callback is called synchronously, in the context of the thread - that created the IRP_MJ_CREATE request. - -Arguments: - - Device - Handle to a framework device object. - FileObject - Pointer to fileobject that represents the open handle. - CreateParams - Copy of the Create IO_STACK_LOCATION - -Return Value: - - VOID. - ---*/ -{ - NTSTATUS status; - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); - - UNREFERENCED_PARAMETER(FileObject); - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, - "SerialEvtDeviceFileCreate %wZ\n", &extension->DeviceName); - - status = SerialDeviceFileCreateWorker(Device); - - // - // Complete the WDF request. - // - WdfRequestComplete(Request, status); - - return; - -} - - -NTSTATUS -SerialWdmDeviceFileCreate ( - IN WDFDEVICE Device, - IN PIRP Irp - ) -/*++ - -Routine Description: - - This is the dispatch routine for IRP_MJ_CREATE. The system sends this - request when a user application opens the device to perform an I/O - operation, such as reading or writing a file. - -Arguments: - - DeviceObject - Pointer to the device object for this device - Irp - Pointer to the IRP for the current request - -Return Value: - - NT status code - ---*/ -{ - NTSTATUS status; - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, - "SerialWdmDeviceFileCreate %wZ\n", &extension->DeviceName); - - status = SerialDeviceFileCreateWorker(Device); - - // - // Complete the WDM request. - // - Irp->IoStatus.Information = 0L; - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - - -NTSTATUS -SerialDeviceFileCreateWorker ( - IN WDFDEVICE Device - ) -{ - NTSTATUS status; - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); - - // - // Create a buffer for the RX data when no reads are outstanding. - // - - extension->InterruptReadBuffer = NULL; - extension->BufferSize = 0; - - switch (MmQuerySystemSize()) { - - case MmLargeSystem: { - - extension->BufferSize = 4096; - extension->InterruptReadBuffer = ExAllocatePoolWithTag( - NonPagedPoolNx, - extension->BufferSize, - POOL_TAG - ); - - if (extension->InterruptReadBuffer) { - break; - } - - } - - case MmMediumSystem: { - - extension->BufferSize = 1024; - extension->InterruptReadBuffer = ExAllocatePoolWithTag( - NonPagedPoolNx, - extension->BufferSize, - POOL_TAG - ); - - if (extension->InterruptReadBuffer) { - break; - } - - } - - case MmSmallSystem: { - - extension->BufferSize = 128; - extension->InterruptReadBuffer = ExAllocatePoolWithTag( - NonPagedPoolNx, - extension->BufferSize, - POOL_TAG - ); - - } - - } - - if (!extension->InterruptReadBuffer) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // By taking a power reference by calling WdfDeviceStopIdle, we prevent the - // framework from powering down our device due to idle timeout when there - // is an open handle. Power reference also moves the device to D0 if we are - // idled out. If you fail create anywhere later in this routine, do make sure - // drop the reference. - // - status = WdfDeviceStopIdle(Device, TRUE); - if (!NT_SUCCESS(status)) { - return status; - } - - // - // wakeup is not currently enabled - // - - extension->IsWakeEnabled = FALSE; - - // - // On a new open we "flush" the read queue by initializing the - // count of characters. - // - - extension->CharsInInterruptBuffer = 0; - extension->LastCharSlot = extension->InterruptReadBuffer + - (extension->BufferSize - 1); - - extension->ReadBufferBase = extension->InterruptReadBuffer; - extension->CurrentCharSlot = extension->InterruptReadBuffer; - extension->FirstReadableChar = extension->InterruptReadBuffer; - - extension->TotalCharsQueued = 0; - - // - // We set up the default xon/xoff limits. - // - - extension->HandFlow.XoffLimit = extension->BufferSize >> 3; - extension->HandFlow.XonLimit = extension->BufferSize >> 1; - - extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit; - extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit; - - extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+ - (extension->BufferSize>>4)); - - // - // Mark the device as busy for WMI - // - - extension->WmiCommData.IsBusy = TRUE; - - extension->IrpMaskLocation = NULL; - extension->HistoryMask = 0; - extension->IsrWaitMask = 0; - - extension->SendXonChar = FALSE; - extension->SendXoffChar = FALSE; - -#if !DBG - // - // Clear out the statistics. - // - - WdfInterruptSynchronize( - extension->WdfInterrupt, - SerialClearStats, - extension - ); -#endif - - // - // The escape char replacement must be reset upon every open. - // - - extension->EscapeChar = 0; - - // - // We don't want the device to be removed or stopped when there is an handle - // - // Note to anyone copying this sample as a starting point: - // - // This works in this driver simply because this driver supports exactly - // one open handle at a time. If it supported more, then it would need - // counting logic to determine when all the reasons for failing Stop/Remove - // were gone. - // - WdfDeviceSetStaticStopRemove(Device, FALSE); - - // - // Synchronize with the ISR and let it know that the device - // has been successfully opened. - // - - WdfInterruptSynchronize( - extension->WdfInterrupt, - SerialMarkOpen, - extension - ); - - return STATUS_SUCCESS; - -} - - -VOID -SerialEvtFileClose( - IN WDFFILEOBJECT FileObject - ) - -/*++ - - EvtFileClose is called when all the handles represented by the FileObject - is closed and all the references to FileObject is removed. This callback - may get called in an arbitrary thread context instead of the thread that - called CloseHandle. If you want to delete any per FileObject context that - must be done in the context of the user thread that made the Create call, - you should do that in the EvtDeviceCleanp callback. - -Arguments: - - FileObject - Pointer to fileobject that represents the open handle. - -Return Value: - - VOID - ---*/ - -{ - PAGED_CODE(); - - SerialFileCloseWorker(WdfFileObjectGetDevice(FileObject)); - return; -} - - -NTSTATUS -SerialWdmFileClose ( - IN WDFDEVICE Device, - IN PIRP Irp - ) -/*++ - -Routine Description: - - This is the dispatch routine for IRP_MJ_CLOSE. This is called when all the - handles represented by the FileObject is closed and all the references to - the FileObject is removed. - -Arguments: - - DeviceObject - Pointer to the device object for this device - Irp - Pointer to the IRP for the current request - -Return Value: - - NT status code - ---*/ -{ - SerialFileCloseWorker(Device); - - Irp->IoStatus.Information = 0L; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_SUCCESS; -} - - -VOID -SerialFileCloseWorker( - IN WDFDEVICE Device - ) -{ - ULONG flushCount; - - // - // This "timer value" is used to wait 10 character times - // after the hardware is empty before we actually "run down" - // all of the flow control/break junk. - // - LARGE_INTEGER tenCharDelay; - - // - // Holds a character time. - // - LARGE_INTEGER charTime; - - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(Device); - PSERIAL_INTERRUPT_CONTEXT interruptContext = SerialGetInterruptContext(extension->WdfInterrupt); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "In SerialEvtFileClose %wZ\n", - &extension->DeviceName); - - // - // Acquire the interrupt state lock. - // - WdfWaitLockAcquire(interruptContext->InterruptStateLock, NULL); - - // - // If the Interrupts are connected, then the hardware state has to be - // cleaned up now. Note that the EvtFileClose callback gets called for - // an open file object even though the interrupts have been disabled - // possibly due to a Surprise Remove PNP event. In such a case, the - // Interrupt object should not be used. - // - if (interruptContext->IsInterruptConnected) { - - charTime.QuadPart = -SerialGetCharTime(extension).QuadPart; - - // - // Do this now so that if the isr gets called it won't do anything - // to cause more chars to get sent. We want to run down the hardware. - // - - SetDeviceIsOpened(extension, FALSE, FALSE); - - // - // Synchronize with the isr to turn off break if it - // is already on. - // - - WdfInterruptSynchronize( - extension->WdfInterrupt, - SerialTurnOffBreak, - extension - ); - - // - // Wait a reasonable amount of time (20 * fifodepth) until all characters - // have been emptied out of the hardware. - // - - for (flushCount = (20 * 16); flushCount != 0; flushCount--) { - if ((READ_LINE_STATUS(extension, extension->Controller) & - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) != - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { - - KeDelayExecutionThread(KernelMode, FALSE, &charTime); - } else { - break; - } - } - - if (flushCount == 0) { - SerialMarkHardwareBroken(extension); - } - - // - // Synchronize with the ISR to let it know that interrupts are - // no longer important. - // - - WdfInterruptSynchronize( - extension->WdfInterrupt, - SerialMarkClose, - extension - ); - - - // - // If the driver has automatically transmitted an Xoff in - // the context of automatic receive flow control then we - // should transmit an Xon. - // - - if (extension->RXHolding & SERIAL_RX_XOFF) { - - // - // Loop until the holding register is empty. - // - while (!(READ_LINE_STATUS(extension, extension->Controller) & - SERIAL_LSR_THRE)) { - KeDelayExecutionThread( - KernelMode, - FALSE, - &charTime - ); - - } - - WRITE_TRANSMIT_HOLDING(extension, - extension->Controller, - extension->SpecialChars.XonChar - ); - - // - // Wait a reasonable amount of time for the characters - // to be emptied out of the hardware. - // - - for (flushCount = (20 * 16); flushCount != 0; flushCount--) { - if ((READ_LINE_STATUS(extension, extension->Controller) & - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) != - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { - KeDelayExecutionThread(KernelMode, FALSE, &charTime); - } else { - break; - } - } - - if (flushCount == 0) { - SerialMarkHardwareBroken(extension); - } - } - - - // - // The hardware is empty. Delay 10 character times before - // shut down all the flow control. - // - - tenCharDelay.QuadPart = charTime.QuadPart * 10; - - KeDelayExecutionThread( - KernelMode, - TRUE, - &tenCharDelay - ); - -#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "This warning is because we are calling interrupt synchronize routine directly.") - SerialClrDTR(extension->WdfInterrupt, extension); - - // - // We have to be very careful how we clear the RTS line. - // Transmit toggling might have been on at some point. - // - // We know that there is nothing left that could start - // out the "polling" execution path. We need to - // check the counter that indicates that the execution - // path is active. If it is then we loop delaying one - // character time. After each delay we check to see if - // the counter has gone to zero. When it has we know that - // the execution path should be just about finished. We - // make sure that we still aren't in the routine that - // synchronized execution with the ISR by synchronizing - // ourselve with the ISR. - // - - if (extension->CountOfTryingToLowerRTS) { - - do { -#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_HIGH, "This warning is due to suppressing the previous one.") - KeDelayExecutionThread( - KernelMode, - FALSE, - &charTime - ); - - } while (extension->CountOfTryingToLowerRTS); - - // - // The execution path should no longer exist that - // is trying to push down the RTS. Well just - // make sure it's down by falling through to - // code that forces it down. - // - - } - -#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "This warning is because we are calling interrupt synchronize routine directly.") - SerialClrRTS(extension->WdfInterrupt, extension); - - // - // Clean out the holding reasons (since we are closed). - // - - extension->RXHolding = 0; - extension->TXHolding = 0; - - // - // Mark device as not busy for WMI - // - - extension->WmiCommData.IsBusy = FALSE; - - } - - // - // Release the Interrupt state lock. - // - WdfWaitLockRelease(interruptContext->InterruptStateLock); - - // - // All is done. The port has been disabled from interrupting - // so there is no point in keeping the memory around. - // - - extension->BufferSize = 0; - if (extension->InterruptReadBuffer != NULL) { - ExFreePool(extension->InterruptReadBuffer); - } - extension->InterruptReadBuffer = NULL; - - // - // Make sure the wake is disabled. - // - ASSERT(!extension->IsWakeEnabled); - - SerialDrainTimersAndDpcs(extension); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_CREATE_CLOSE, "DPC's drained:\n"); - - // - // It's fine for the device to be powered off if there are no open handles. - // - WdfDeviceResumeIdle(Device); - - // - // It's okay to allow the device to be stopped or removed. - // - // Note to anyone copying this sample as a starting point: - // - // This works in this driver simply because this driver supports exactly - // one open handle at a time. If it supported more, then it would need - // counting logic to determine when all the reasons for failing Stop/Remove - // were gone. - // - WdfDeviceSetStaticStopRemove(Device, TRUE); - - return; - -} - -BOOLEAN -SerialMarkOpen( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine merely sets a boolean to true to mark the fact that - somebody opened the device and its worthwhile to pay attention - to interrupts. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - SerialReset(extension->WdfInterrupt, extension); - - // - // Prepare for the opening by re-enabling interrupts. - // - // We do this my modifying the OUT2 line in the modem control. - // In PC's this bit is "anded" with the interrupt line. - // - - WRITE_MODEM_CONTROL(extension, - extension->Controller, - (UCHAR)(READ_MODEM_CONTROL(extension, extension->Controller) | SERIAL_MCR_OUT2) - ); - - extension->DeviceIsOpened = TRUE; - extension->ErrorWord = 0; - - return FALSE; - -} - -VOID -SerialDrainUART(IN PSERIAL_DEVICE_EXTENSION PDevExt, - IN PLARGE_INTEGER PDrainTime) -{ - PAGED_CODE(); - - // - // Wait until all characters have been emptied out of the hardware. - // - - while ((READ_LINE_STATUS(PDevExt, PDevExt->Controller) & - (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) - != (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { - KeDelayExecutionThread(KernelMode, FALSE, PDrainTime); - } -} - -VOID -SerialDisableUART(IN PVOID Context) - -/*++ - -Routine Description: - - This routine disables the UART and puts it in a "safe" state when - not in use (like a close or powerdown). - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION extension = Context; - - // - // Prepare for the closing by stopping interrupts. - // - // We do this by adjusting the OUT2 line in the modem control. - // In PC's this bit is "anded" with the interrupt line. - // - - WRITE_MODEM_CONTROL(extension, extension->Controller, - (UCHAR)(READ_MODEM_CONTROL(extension, extension->Controller) - & ~SERIAL_MCR_OUT2)); - - if (extension->FifoPresent) { - WRITE_FIFO_CONTROL(extension, extension->Controller, (UCHAR)0); - } -} - - - -BOOLEAN -SerialMarkClose( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine merely sets a boolean to false to mark the fact that - somebody closed the device and it's no longer worthwhile to pay attention - to interrupts. It also disables the UART. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - SerialDisableUART(Context); - extension->DeviceIsOpened = FALSE; - extension->DeviceState.Reopen = FALSE; - - return FALSE; - -} - -LARGE_INTEGER -SerialGetCharTime( - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - This function will return the number of 100 nanosecond intervals - there are in one character time (based on the present form - of flow control. - -Arguments: - - Extension - Just what it says. - -Return Value: - - 100 nanosecond intervals in a character time. - ---*/ - -{ - ULONG dataSize = 0; - ULONG paritySize; - ULONG stopSize; - ULONG charTime; - ULONG bitTime; - LARGE_INTEGER tmp; - - PAGED_CODE(); - - if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) { - dataSize = 5; - } else if ((Extension->LineControl & SERIAL_DATA_MASK) - == SERIAL_6_DATA) { - dataSize = 6; - } else if ((Extension->LineControl & SERIAL_DATA_MASK) - == SERIAL_7_DATA) { - dataSize = 7; - } else if ((Extension->LineControl & SERIAL_DATA_MASK) - == SERIAL_8_DATA) { - dataSize = 8; - } - - paritySize = 1; - if ((Extension->LineControl & SERIAL_PARITY_MASK) - == SERIAL_NONE_PARITY) { - - paritySize = 0; - - } - - if (Extension->LineControl & SERIAL_2_STOP) { - - // - // Even if it is 1.5, for sanities sake were going - // to say 2. - // - - stopSize = 2; - - } else { - - stopSize = 1; - - } - - // - // First we calculate the number of 100 nanosecond intervals - // are in a single bit time (Approximately). - // - - bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud; - charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime); - - tmp.QuadPart = charTime; - return tmp; - -} - - diff --git a/tests/projects/wdk/kmdf/serial/pnp.c b/tests/projects/wdk/kmdf/serial/pnp.c deleted file mode 100644 index 8773f30ac..000000000 --- a/tests/projects/wdk/kmdf/serial/pnp.c +++ /dev/null @@ -1,2804 +0,0 @@ -/*++ - -Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation - -Module Name: - - pnp.c - -Abstract: - - This module contains the code that handles the plug and play - IRPs for the serial driver. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" -#include -#include -#include - -#if defined(EVENT_TRACING) -#include "pnp.tmh" -#endif - -static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; -static const SUPPORTED_BAUD_RATES SupportedBaudRates[] = { - {75, SERIAL_BAUD_075}, - {110, SERIAL_BAUD_110}, - {135, SERIAL_BAUD_134_5}, - {150, SERIAL_BAUD_150}, - {300, SERIAL_BAUD_300}, - {600, SERIAL_BAUD_600}, - {1200, SERIAL_BAUD_1200}, - {1800, SERIAL_BAUD_1800}, - {2400, SERIAL_BAUD_2400}, - {4800, SERIAL_BAUD_4800}, - {7200, SERIAL_BAUD_7200}, - {9600, SERIAL_BAUD_9600}, - {14400, SERIAL_BAUD_14400}, - {19200, SERIAL_BAUD_19200}, - {38400, SERIAL_BAUD_38400}, - {56000, SERIAL_BAUD_56K}, - {57600, SERIAL_BAUD_57600}, - {115200, SERIAL_BAUD_115200}, - {128000, SERIAL_BAUD_128K}, - {SERIAL_BAUD_INVALID, SERIAL_BAUD_USER} - }; - - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGESRP0, SerialEvtDeviceAdd) -#pragma alloc_text(PAGESRP0, SerialEvtPrepareHardware) -#pragma alloc_text(PAGESRP0, SerialEvtReleaseHardware) -#pragma alloc_text(PAGESRP0, SerialEvtDeviceD0ExitPreInterruptsDisabled) -#pragma alloc_text(PAGESRP0, SerialMapHWResources) -#pragma alloc_text(PAGESRP0, SerialUnmapHWResources) -#pragma alloc_text(PAGESRP0, SerialEvtDeviceContextCleanup) -#pragma alloc_text(PAGESRP0, SerialDoExternalNaming) -#pragma alloc_text(PAGESRP0, SerialReportMaxBaudRate) -#pragma alloc_text(PAGESRP0, SerialUndoExternalNaming) -#pragma alloc_text(PAGESRP0, SerialInitController) -#pragma alloc_text(PAGESRP0, SerialGetMappedAddress) -#pragma alloc_text(PAGESRP0, SerialSetPowerPolicy) -#pragma alloc_text(PAGESRP0, SerialReadSymName) - -#endif // ALLOC_PRAGMA - -PVOID LocalMmMapIoSpace( - _In_ PHYSICAL_ADDRESS PhysicalAddress, - _In_ SIZE_T NumberOfBytes - ) -{ - typedef - PVOID - (*PFN_MM_MAP_IO_SPACE_EX) ( - _In_ PHYSICAL_ADDRESS PhysicalAddress, - _In_ SIZE_T NumberOfBytes, - _In_ ULONG Protect - ); - - UNICODE_STRING name; - PFN_MM_MAP_IO_SPACE_EX pMmMapIoSpaceEx; - - RtlInitUnicodeString(&name, L"MmMapIoSpaceEx"); - pMmMapIoSpaceEx = (PFN_MM_MAP_IO_SPACE_EX) (ULONG_PTR)MmGetSystemRoutineAddress(&name); - - if (pMmMapIoSpaceEx != NULL){ - // - // Call WIN10 API if available - // - return pMmMapIoSpaceEx(PhysicalAddress, - NumberOfBytes, - PAGE_READWRITE | PAGE_NOCACHE); - } - - // - // Supress warning that MmMapIoSpace allocates executable memory. - // This function is only used if the preferred API, MmMapIoSpaceEx - // is not present. MmMapIoSpaceEx is available starting in WIN10. - // - #pragma warning(suppress: 30029) - return MmMapIoSpace(PhysicalAddress, NumberOfBytes, MmNonCached); -} - -NTSTATUS -SerialEvtDeviceAdd( - IN WDFDRIVER Driver, - IN PWDFDEVICE_INIT DeviceInit - ) -/*++ - -Routine Description: - - EvtDeviceAdd is called by the framework in response to AddDevice - call from the PnP manager. - - -Arguments: - - Driver - Handle to a framework driver object created in DriverEntry - - DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. - -Return Value: - - NTSTATUS - ---*/ - -{ - NTSTATUS status; - PSERIAL_DEVICE_EXTENSION pDevExt; - static ULONG currentInstance = 0; - WDF_FILEOBJECT_CONFIG fileobjectConfig; - WDFDEVICE device; - WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; - WDF_OBJECT_ATTRIBUTES attributes; - WDF_IO_QUEUE_CONFIG queueConfig; - WDFQUEUE defaultqueue; - ULONG isMulti; - PULONG countSoFar; - WDF_INTERRUPT_CONFIG interruptConfig; - PSERIAL_INTERRUPT_CONTEXT interruptContext; - ULONG relinquishPowerPolicy; - - DECLARE_UNICODE_STRING_SIZE(deviceName, DEVICE_OBJECT_NAME_LENGTH); - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "-->SerialEvtDeviceAdd\n"); - - status = RtlUnicodeStringPrintf(&deviceName, L"%ws%u", - L"\\Device\\Serial", - currentInstance++); - - - if (!NT_SUCCESS(status)) { - return status; - } - - status = WdfDeviceInitAssignName(DeviceInit,& deviceName); - if (!NT_SUCCESS(status)) { - return status; - } - - WdfDeviceInitSetExclusive(DeviceInit, TRUE); - WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SERIAL_PORT); - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); - - WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes); - - // - // Zero out the PnpPowerCallbacks structure. - // - WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); - - // - // Set Callbacks for any of the functions we are interested in. - // If no callback is set, Framework will take the default action - // by itself. These next two callbacks set up and tear down hardware state, - // specifically that which only has to be done once. - // - - pnpPowerCallbacks.EvtDevicePrepareHardware = SerialEvtPrepareHardware; - pnpPowerCallbacks.EvtDeviceReleaseHardware = SerialEvtReleaseHardware; - - // - // These two callbacks set up and tear down hardware state that must be - // done every time the device moves in and out of the D0-working state. - // - - pnpPowerCallbacks.EvtDeviceD0Entry = SerialEvtDeviceD0Entry; - pnpPowerCallbacks.EvtDeviceD0Exit = SerialEvtDeviceD0Exit; - - // - // Specify the callback for monitoring when the device's interrupt are - // enabled or about to be disabled. - // - - pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = SerialEvtDeviceD0EntryPostInterruptsEnabled; - pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = SerialEvtDeviceD0ExitPreInterruptsDisabled; - - // - // Register the PnP and power callbacks. - // - WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); - - if ( !NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n", - status); - return status; - } - - // - // Find out if we own power policy - // - SerialGetFdoRegistryKeyValue( DeviceInit, - L"SerialRelinquishPowerPolicy", - &relinquishPowerPolicy ); - - if(relinquishPowerPolicy) { - // - // FDO's are assumed to be power policy owner by default. So tell - // the framework explicitly to relinquish the power policy ownership. - // - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "RelinquishPowerPolicy due to registry settings\n"); - - WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); - } - - // - // For Windows XP and below, we will register for the WDM Preprocess callback - // for IRP_MJ_CREATE. This is done because, the Serenum filter doesn't handle - // creates that are marked pending. Since framework always marks the IRP pending, - // we are registering this WDM preprocess handler so that we can bypass the - // framework and handle the create and close ourself. This workaround is need - // only if you intend to install the Serenum as an upper filter. - // - if (RtlIsNtDdiVersionAvailable(NTDDI_VISTA) == FALSE) { - - status = WdfDeviceInitAssignWdmIrpPreprocessCallback( - DeviceInit, - SerialWdmDeviceFileCreate, - IRP_MJ_CREATE, - NULL, // pointer minor function table - 0); // number of entries in the table - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", - status); - return status; - } - - status = WdfDeviceInitAssignWdmIrpPreprocessCallback( - DeviceInit, - SerialWdmFileClose, - IRP_MJ_CLOSE, - NULL, // pointer minor function table - 0); // number of entries in the table - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", - status); - return status; - } - - } else { - - // - // FileEvents can opt for Device level synchronization only if the ExecutionLevel - // of the Device is passive. Since we can't choose passive execution-level for - // device because we have chose to synchronize timers & dpcs with the device, - // we will opt out of synchonization with the device for fileobjects. - // Note: If the driver has to synchronize Create with the other I/O events, - // it can create a queue and configure-dispatch create requests to the queue. - // - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.SynchronizationScope = WdfSynchronizationScopeNone; - - // - // Set Entry points for Create and Close.. - // - WDF_FILEOBJECT_CONFIG_INIT( - &fileobjectConfig, - SerialEvtDeviceFileCreate, - SerialEvtFileClose, - WDF_NO_EVENT_CALLBACK // Cleanup - ); - - WdfDeviceInitSetFileObjectConfig( - DeviceInit, - &fileobjectConfig, - &attributes - ); - } - - - // - // Since framework queues doesn't handle IRP_MJ_FLUSH_BUFFERS, - // IRP_MJ_QUERY_INFORMATION and IRP_MJ_SET_INFORMATION requests, - // we will register a preprocess callback to handle them. - // - status = WdfDeviceInitAssignWdmIrpPreprocessCallback( - DeviceInit, - SerialFlush, - IRP_MJ_FLUSH_BUFFERS, - NULL, // pointer minor function table - 0); // number of entries in the table - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", - status); - return status; - } - - status = WdfDeviceInitAssignWdmIrpPreprocessCallback( - DeviceInit, - SerialQueryInformationFile, - IRP_MJ_QUERY_INFORMATION, - NULL, // pointer minor function table - 0); // number of entries in the table - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", - status); - return status; - } - status = WdfDeviceInitAssignWdmIrpPreprocessCallback( - DeviceInit, - SerialSetInformationFile, - IRP_MJ_SET_INFORMATION, - NULL, // pointer minor function table - 0); // number of entries in the table - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", - status); - return status; - } - - - // - // Create a device - // - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&attributes, - SERIAL_DEVICE_EXTENSION); - // - // Provide a callback to cleanup the context. This will be called - // when the device is removed. - // - attributes.EvtCleanupCallback = SerialEvtDeviceContextCleanup; - // - // By opting for SynchronizationScopeDevice, we tell the framework to - // synchronize callbacks events of all the objects directly associated - // with the device. In this driver, we will associate queues, dpcs, - // and timers. By doing that we don't have to worrry about synchronizing - // access to device-context by Io Events, cancel-routine, timer and dpc - // callbacks. - // - attributes.SynchronizationScope = WdfSynchronizationScopeDevice; - - status = WdfDeviceCreate(&DeviceInit, &attributes, &device); - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "SerialAddDevice - WdfDeviceCreate failed %!STATUS!\n", - status); - return status; - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "Created device (%p) %wZ\n", device, &deviceName); - - pDevExt = SerialGetDeviceExtension (device); - - pDevExt->DriverObject = WdfDriverWdmGetDriverObject(Driver); - - // - // This sample doesn't support multiport serial devices. - // Multiport devices allow other pseudo-serial devices with extra - // resources to specify another range of I/O ports. - // - if(!SerialGetRegistryKeyValue(device, L"MultiportDevice", &isMulti)) { - isMulti = 0; - } - - if(isMulti) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "This sample doesn't support multiport devices\n"); - return STATUS_DEVICE_CONFIGURATION_ERROR; - } - - // - // Set up the device extension. - // - - pDevExt = SerialGetDeviceExtension (device); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "AddDevice PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", - WdfDeviceWdmGetPhysicalDevice (device), - WdfDeviceWdmGetDeviceObject (device), - WdfDeviceWdmGetAttachedDevice(device), - pDevExt); - - pDevExt->DeviceIsOpened = FALSE; - pDevExt->DeviceObject = WdfDeviceWdmGetDeviceObject(device); - pDevExt->WdfDevice = device; - - pDevExt->TxFifoAmount = driverDefaults.TxFIFODefault; - pDevExt->UartRemovalDetect = driverDefaults.UartRemovalDetect; - pDevExt->CreatedSymbolicLink = FALSE; - pDevExt->OwnsPowerPolicy = relinquishPowerPolicy ? FALSE : TRUE; - - status = SerialSetPowerPolicy(pDevExt); - if(!NT_SUCCESS(status)){ - return status; - } - - // - // We create four manual queues below. - // Read Queue..(how about using serial queue for read). Since requests - // jump from queue to queue, we cannot configure the queues to receive a - // particular type of request. For example, some of the IOCTLs end up - // in read and write queue. - // - WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, - WdfIoQueueDispatchManual); - - queueConfig.EvtIoStop = SerialEvtIoStop; - queueConfig.EvtIoResume = SerialEvtIoResume; - queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; - - status = WdfIoQueueCreate (device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &pDevExt->ReadQueue - ); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Read failed %!STATUS!\n", status); - return status; - } - - // - // Write Queue.. - // - WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, - WdfIoQueueDispatchManual); - - queueConfig.EvtIoStop = SerialEvtIoStop; - queueConfig.EvtIoResume = SerialEvtIoResume; - queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; - - status = WdfIoQueueCreate (device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &pDevExt->WriteQueue - ); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Write failed %!STATUS!\n", status); - return status; - } - - // - // Mask Queue... - // - WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, - WdfIoQueueDispatchManual - ); - - queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; - - queueConfig.EvtIoStop = SerialEvtIoStop; - queueConfig.EvtIoResume = SerialEvtIoResume; - - status = WdfIoQueueCreate (device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &pDevExt->MaskQueue - ); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Mask failed %!STATUS!\n", status); - return status; - } - - // - // Purge Queue.. - // - WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, - WdfIoQueueDispatchManual - ); - - queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; - - queueConfig.EvtIoStop = SerialEvtIoStop; - queueConfig.EvtIoResume = SerialEvtIoResume; - - status = WdfIoQueueCreate (device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &pDevExt->PurgeQueue - ); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Purge failed %!STATUS!\n", status); - return status; - } - - // - // All the incoming I/O requests are routed to the default queue and dispatch to the - // appropriate callback events. These callback event will check to see if another - // request is currently active. If so then it will forward it to other manual queues. - // All the queues are auto managed by the framework in response to the PNP - // and Power events. - // - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( - &queueConfig, - WdfIoQueueDispatchParallel - ); - queueConfig.EvtIoRead = SerialEvtIoRead; - queueConfig.EvtIoWrite = SerialEvtIoWrite; - queueConfig.EvtIoDeviceControl = SerialEvtIoDeviceControl; - queueConfig.EvtIoInternalDeviceControl = SerialEvtIoInternalDeviceControl; - queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; - - queueConfig.EvtIoStop = SerialEvtIoStop; - queueConfig.EvtIoResume = SerialEvtIoResume; - - status = WdfIoQueueCreate(device, - &queueConfig, - WDF_NO_OBJECT_ATTRIBUTES, - &defaultqueue - ); - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", status); - return status; - } - - // - // Create WDFINTERRUPT object. Let us leave the ShareVector to default value and - // let the framework decide whether to share the interrupt or not based on the - // ShareDisposition provided by the bus driver in the resource descriptor. - // - - WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, - SerialISR, - NULL); - - interruptConfig.EvtInterruptDisable = SerialEvtInterruptDisable; - interruptConfig.EvtInterruptEnable = SerialEvtInterruptEnable; - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SERIAL_INTERRUPT_CONTEXT); - - status = WdfInterruptCreate(device, - &interruptConfig, - &attributes, - &pDevExt->WdfInterrupt); - - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't create interrupt for %wZ\n", - &pDevExt->DeviceName); - return status; - } - - // - // Interrupt state wait lock... - // - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = pDevExt->WdfInterrupt; - - interruptContext = SerialGetInterruptContext(pDevExt->WdfInterrupt); - - status = WdfWaitLockCreate(&attributes, - &interruptContext->InterruptStateLock - ); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfWaitLockCreate for InterruptStateLock failed %!STATUS!\n", status); - return status; - } - - // - // Set interrupt policy - // - SerialSetInterruptPolicy(pDevExt->WdfInterrupt); - - // - // Timers and DPCs... - // - status = SerialCreateTimersAndDpcs(pDevExt); - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "SerialCreateTimersAndDpcs failed %x\n", status); - return status; - } - - // - // Register with WMI. - // - status = SerialWmiRegistration(device); - if(!NT_SUCCESS (status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "SerialWmiRegistration failed %!STATUS!\n", status); - return status; - - } - - // - // Upto this point, if we fail, we don't have to worry about freeing any resource because - // framework will free all the objects. - // - // - // Do the external naming. - // - - status = SerialDoExternalNaming(pDevExt); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "External Naming Failed - Status %!STATUS!\n", - status); - return status; - } - - // - // Finally increment the global system configuration that keeps track of number of serial ports. - // - countSoFar = &IoGetConfigurationInformation()->SerialCount; - (*countSoFar)++; - pDevExt->IsSystemConfigInfoUpdated = TRUE; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<--SerialEvtDeviceAdd\n"); - - return status; - -} -#pragma warning(push) -#pragma warning(disable:28118) // this callback will run at IRQL=PASSIVE_LEVEL -_Use_decl_annotations_ -VOID -SerialEvtDeviceContextCleanup ( - WDFOBJECT Device - ) -/*++ - -Routine Description: - - EvtDeviceContextCleanup event callback cleans up anything done in - EvtDeviceAdd, except those things that are automatically cleaned - up by the Framework. - - In a driver derived from this sample, it's quite likely that this function could - be deleted. - -Arguments: - - Device - Handle to a framework device object. - -Return Value: - - VOID - ---*/ -{ - PSERIAL_DEVICE_EXTENSION deviceExtension; - PULONG countSoFar; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialDeviceContextCleanup\n"); - - PAGED_CODE(); - - deviceExtension = SerialGetDeviceExtension (Device); - - if (deviceExtension->InterruptReadBuffer != NULL) { - ExFreePool(deviceExtension->InterruptReadBuffer); - deviceExtension->InterruptReadBuffer = NULL; - } - - // - // Update the global configuration count for serial device. - // - if(deviceExtension->IsSystemConfigInfoUpdated) { - countSoFar = &IoGetConfigurationInformation()->SerialCount; - (*countSoFar)--; - } - - SerialUndoExternalNaming(deviceExtension); - - return; -} -#pragma warning(pop) // enable 28118 again - -NTSTATUS -SerialEvtPrepareHardware( - WDFDEVICE Device, - WDFCMRESLIST Resources, - WDFCMRESLIST ResourcesTranslated - ) -/*++ - -Routine Description: - - SerialEvtPrepareHardware event callback performs operations that are necessary - to make the device operational. The framework calls the driver's - SerialEvtPrepareHardware callback when the PnP manager sends an IRP_MN_START_DEVICE - request to the driver stack. - -Arguments: - - Device - Handle to a framework device object. - - Resources - Handle to a collection of framework resource objects. - This collection identifies the raw (bus-relative) hardware - resources that have been assigned to the device. - - ResourcesTranslated - Handle to a collection of framework resource objects. - This collection identifies the translated (system-physical) - hardware resources that have been assigned to the device. - The resources appear from the CPU's point of view. - Use this list of resources to map I/O space and - device-accessible memory into virtual address space - -Return Value: - - WDF status code - ---*/ -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - NTSTATUS status; - CONFIG_DATA config; - PCONFIG_DATA pConfig = &config; - ULONG defaultClockRate = 1843200; - - PAGED_CODE(); - - SerialDbgPrintEx (TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialEvtPrepareHardware\n"); - // - // Get the Device Extension.. - // - pDevExt = SerialGetDeviceExtension (Device); - - RtlZeroMemory(pConfig, sizeof(CONFIG_DATA)); - - // - // Initialize a config data structure with default values for those that - // may not already be initialized. - // - - pConfig->LogFifo = driverDefaults.LogFifoDefault; - - - // - // Get the hw resources for the device. - // - - status = SerialMapHWResources(Device, Resources, ResourcesTranslated, pConfig); - - if (!NT_SUCCESS(status)) { - goto End; - } - - // - // Open the "Device Parameters" section of registry for this device and get parameters. - // - - if(!SerialGetRegistryKeyValue (Device, - L"DisablePort", - &pConfig->DisablePort)){ - pConfig->DisablePort = 0; - } - - if(!SerialGetRegistryKeyValue (Device, - L"ForceFifoEnable", - &pConfig->ForceFifoEnable)){ - pConfig->ForceFifoEnable = driverDefaults.ForceFifoEnableDefault; - } - - if(!SerialGetRegistryKeyValue (Device, - L"RxFIFO", - &pConfig->RxFIFO)){ - pConfig->RxFIFO = driverDefaults.RxFIFODefault; - } - - if(!SerialGetRegistryKeyValue (Device, - L"TxFIFO", - &pConfig->TxFIFO)){ - pConfig->TxFIFO = driverDefaults.TxFIFODefault; - } - - if(!SerialGetRegistryKeyValue (Device, - L"Share System Interrupt", - &pConfig->PermitShare)){ - pConfig->PermitShare = driverDefaults.PermitShareDefault; - } - - if(!SerialGetRegistryKeyValue (Device, - L"ClockRate", - &pConfig->ClockRate)) { - pConfig->ClockRate = defaultClockRate; - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Com Port ClockRate: %x\n", - pConfig->ClockRate); - - if(!SerialGetRegistryKeyValue(Device, - L"TL16C550C Auto Flow Control", - &pConfig->TL16C550CAFC)){ - pConfig->TL16C550CAFC = 0; - } - - status = SerialInitController(pDevExt, pConfig); - - if (NT_SUCCESS(status)) { - } -End: - - SerialDbgPrintEx (TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialEvtPrepareHardware 0x%x\n", status); - - return status; -} - -NTSTATUS -SerialEvtReleaseHardware( - IN WDFDEVICE Device, - IN WDFCMRESLIST ResourcesTranslated - ) -/*++ - -Routine Description: - - EvtDeviceReleaseHardware is called by the framework whenever the PnP manager - is revoking ownership of our resources. This may be in response to either - IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. The callback is made before - passing down the IRP to the lower driver. - - In this callback, do anything necessary to free those resources. - In this driver, we will not receive this callback when there is open handle to - the device. We explicitly tell the framework (WdfDeviceSetStaticStopRemove) to - fail stop and query-remove when handle is open. - -Arguments: - - Device - Handle to a framework device object. - - ResourcesTranslated - Handle to a collection of framework resource objects. - This collection identifies the translated (system-physical) - hardware resources that have been assigned to the device. - The resources appear from the CPU's point of view. - Use this list of resources to map I/O space and - device-accessible memory into virtual address space - -Return Value: - - NTSTATUS - Failures will be logged, but not acted on. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - - UNREFERENCED_PARAMETER(ResourcesTranslated); - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "--> SerialEvtReleaseHardware\n"); - - pDevExt = SerialGetDeviceExtension (Device); - - // - // Reset and put the device into a known initial state before releasing the hw resources. - // In this driver we can recieve this callback only when there is no handle open because - // we tell the framework to disable stop by calling WdfDeviceSetStaticStopRemove. - // Since we have already reset the device in our close handler, we don't have to - // do anything other than unmapping the I/O resources. - // - - // - // Unmap any Memory-Mapped registers. Disconnecting from the interrupt will - // be done automatically by the framework. - // - SerialUnmapHWResources(pDevExt); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "<-- SerialEvtReleaseHardware\n"); - - return STATUS_SUCCESS; -} - - -NTSTATUS -SerialEvtDeviceD0EntryPostInterruptsEnabled( - IN WDFDEVICE Device, - IN WDF_POWER_DEVICE_STATE PreviousState - ) -/*++ - -Routine Description: - - EvtDeviceD0EntryPostInterruptsEnabled is called by the framework after the - driver has enabled the device's hardware interrupts. - - This function is not marked pageable because this function is in the - device power up path. When a function is marked pagable and the code - section is paged out, it will generate a page fault which could impact - the fast resume behavior because the client driver will have to wait - until the system drivers can service this page fault. - -Arguments: - - Device - Handle to a framework device object. - - PreviousState - A WDF_POWER_DEVICE_STATE-typed enumerator that identifies - the previous device power state. - -Return Value: - - NTSTATUS - Failures will be logged, but not acted on. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(Device); - PSERIAL_INTERRUPT_CONTEXT interruptContext = SerialGetInterruptContext(extension->WdfInterrupt); - WDF_INTERRUPT_INFO info; - - UNREFERENCED_PARAMETER(PreviousState); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "--> SerialEvtDeviceD0EntryPostInterruptsEnabled\n"); - // - // The following lines of code show how to call WdfInterruptGetInfo. - // - WDF_INTERRUPT_INFO_INIT(&info); - WdfInterruptGetInfo(extension->WdfInterrupt, &info); - - WdfWaitLockAcquire(interruptContext->InterruptStateLock, NULL); - interruptContext->IsInterruptConnected = TRUE; - WdfWaitLockRelease(interruptContext->InterruptStateLock); - - return STATUS_SUCCESS; -} - - -NTSTATUS -SerialEvtDeviceD0ExitPreInterruptsDisabled( - IN WDFDEVICE Device, - IN WDF_POWER_DEVICE_STATE TargetState - ) -/*++ - -Routine Description: - - EvtDeviceD0ExitPreInterruptsDisabled is called by the framework before the - driver disables the device's hardware interrupts. - -Arguments: - - Device - Handle to a framework device object. - - TargetState - A WDF_POWER_DEVICE_STATE-typed enumerator that identifies the - device power state that the device is about to enter. - -Return Value: - - NTSTATUS - Failures will be logged, but not acted on. - ---*/ -{ - PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(Device); - PSERIAL_INTERRUPT_CONTEXT interruptContext = SerialGetInterruptContext(extension->WdfInterrupt); - - UNREFERENCED_PARAMETER(TargetState); - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "--> SerialEvtDeviceD0ExitPreInterruptsDisabled\n"); - - WdfWaitLockAcquire(interruptContext->InterruptStateLock, NULL); - interruptContext->IsInterruptConnected = FALSE; - WdfWaitLockRelease(interruptContext->InterruptStateLock); - - return STATUS_SUCCESS; -} - - -NTSTATUS -SerialSetPowerPolicy( - IN PSERIAL_DEVICE_EXTENSION DeviceExtension - ) -{ - WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; - //WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks; - NTSTATUS status = STATUS_SUCCESS; - WDFDEVICE hDevice = DeviceExtension->WdfDevice; - ULONG powerOnClose; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "--> SerialSetPowerPolicy\n"); - - PAGED_CODE(); - - // - // Find out whether we want to power down the device when there no handles open. - // - SerialGetRegistryKeyValue(hDevice, L"EnablePowerManagement", &powerOnClose); - DeviceExtension->RetainPowerOnClose = powerOnClose ? TRUE : FALSE; - - // - // In some drivers, the device must be specifically programmed to enable - // wake signals. UARTs were designed long, long before such a concept. So - // this driver, which just drives UARTs, doesn't register wake arm/disarm - // callbacks. Arming or disarming for UARTs has to be handled by side-band - // code that controls hardware designed more recently. In this case, ACPI - // is handling it. If one were to write a driver which implemented a more - // modern serial device, one might need to use these callbacks. - // - - // - // Init the power policy callbacks - // - //WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks); - - // - // This group of three callbacks allows this sample driver to manage - // arming the device for wake from the S0 state. - // - - //powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = SerialEvtDeviceWakeArmS0; - //powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = SerialEvtDeviceWakeDisarmS0; - //powerPolicyCallbacks.EvtDeviceWakeFromS0Triggered = SerialEvtDeviceWakeTriggeredS0; - - // - // This group of three callbacks allows the device to be armed for wake - // from Sx (S1, S2, S3 or S4.) Networking devices can optionally be put - // into a state where a packet sent to them will cause the device's wake - // signal to be triggered, which causes the machine to wake, moving back - // into the S0 state. - // - - //powerPolicyCallbacks.EvtDeviceArmWakeFromSx = SerialEvtDeviceWakeArmSx; - //powerPolicyCallbacks.EvtDeviceDisarmWakeFromSx = SerialEvtDeviceWakeDisarmSx; - //powerPolicyCallbacks.EvtDeviceWakeFromSxTriggered = SerialEvtDeviceWakeTriggeredSx; - - // - // Register the power policy callbacks. - // - //WdfDeviceSetPowerPolicyEventCallbacks(hDevice, &powerPolicyCallbacks); - - // - // Init the idle policy structure. By setting IdleCannotWakeFromS0 we tell the framework - // to power down the device without arming for wake. The only way the device can come - // back to D0 is when we call WdfDeviceStopIdle in SerialEvtDeviceFileCreate. - // We can't choose IdleCanWakeFromS0 by default is because onboard serial ports typically - // don't have wake capability. If the driver is used for plugin boards that does support - // wait-wake, you can update the settings to match that. If MS provided modem driver - // is used on ports that does support wake on ring, then it will update the settings - // by sending an internal ioctl to us. - // - WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); - if(DeviceExtension->OwnsPowerPolicy && !DeviceExtension->RetainPowerOnClose) { - // - // Since we don't have to retain power when there are no open handles, we - // register for idle power management to save power. Check the use of - // WdfDeviceStopIdle in SerialEvtDeviceFileCreate. - // - idleSettings.UserControlOfIdleSettings = IdleAllowUserControl; - - status = WdfDeviceAssignS0IdleSettings(hDevice, &idleSettings); - if ( !NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x \n", status); - return status; - } - } - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialSetPowerPolicy\n"); - - return status; -} - -UINT32 -SerialReportMaxBaudRate(ULONG Bauds) -/*++ - -Routine Description: - - This routine returns the max baud rate given a selection of rates - -Arguments: - - Bauds - Bit-encoded list of supported bauds - - - Return Value: - - The max baud rate listed in Bauds - ---*/ -{ - int i; - - PAGED_CODE(); - - for(i=0; SupportedBaudRates[i].BaudRate != SERIAL_BAUD_INVALID; i++) { - - if(Bauds & SupportedBaudRates[i].Mask) { - return SupportedBaudRates[i].BaudRate; - } - } - - // - // We're in bad shape - // - - return 0; -} - -NTSTATUS -SerialInitController( - IN PSERIAL_DEVICE_EXTENSION pDevExt, - IN PCONFIG_DATA PConfigData - ) -/*++ - -Routine Description: - - Really too many things to mention here. In general initializes - kernel synchronization structures, allocates the typeahead buffer, - sets up defaults, etc. - -Arguments: - - PDevObj - Device object for the device to be started - - PConfigData - Pointer to a record for a single port. - -Return Value: - - STATUS_SUCCCESS if everything went ok. A !NT_SUCCESS status - otherwise. - ---*/ - -{ - NTSTATUS status = STATUS_SUCCESS; - SHORT junk; - int i; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialInitController for %wZ\n", - &pDevExt->DeviceName); - - // - // Save the value of clock input to the part. We use this to calculate - // the divisor latch value. The value is in Hertz. - // - - pDevExt->ClockRate = PConfigData->ClockRate; - - - // - // Save if we have to enable TI's auto flow control - // - - - pDevExt->TL16C550CAFC = PConfigData->TL16C550CAFC; - - - // - // Map the memory for the control registers for the serial device - // into virtual memory. - // - pDevExt->Controller = - SerialGetMappedAddress(PConfigData->TrController, - PConfigData->SpanOfController, - (BOOLEAN)PConfigData->AddressSpace, - &pDevExt->UnMapRegisters); - - - if (!pDevExt->Controller) { - - SerialLogError( - pDevExt->DriverObject, - pDevExt->DeviceObject, - PConfigData->TrController, - SerialPhysicalZero, - 0, - 0, - 0, - 7, - STATUS_SUCCESS, - SERIAL_REGISTERS_NOT_MAPPED, - pDevExt->DeviceName.Length+sizeof(WCHAR), - pDevExt->DeviceName.Buffer, - 0, - NULL - ); - - SerialDbgPrintEx(TRACE_LEVEL_WARNING, DBG_PNP, "Could not map memory for device " - "registers for %wZ\n", &pDevExt->DeviceName); - - pDevExt->UnMapRegisters = FALSE; - status = STATUS_NONE_MAPPED; - goto ExtensionCleanup; - - } - - pDevExt->AddressSpace = PConfigData->AddressSpace; - pDevExt->SpanOfController = PConfigData->SpanOfController; - - // - // Save off the interface type and the bus number. - // - - pDevExt->Vector = PConfigData->TrVector; - pDevExt->Irql = (UCHAR)PConfigData->TrIrql; - pDevExt->InterruptMode = PConfigData->InterruptMode; - pDevExt->Affinity = PConfigData->Affinity; - - // - // If the user said to permit sharing within the device, propagate this - // through. - // - - pDevExt->PermitShare = PConfigData->PermitShare; - - - // - // Before we test whether the port exists (which will enable the FIFO) - // convert the rx trigger value to what should be used in the register. - // - // If a bogus value was given - crank them down to 1. - // - // If this is a "souped up" UART with like a 64 byte FIFO, they - // should use the appropriate "spoofing" value to get the desired - // results. I.e., if on their chip 0xC0 in the FCR is for 64 bytes, - // they should specify 14 in the registry. - // - - switch (PConfigData->RxFIFO) { - - case 1: - - pDevExt->RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER; - break; - - case 4: - - pDevExt->RxFifoTrigger = SERIAL_4_BYTE_HIGH_WATER; - break; - - case 8: - - pDevExt->RxFifoTrigger = SERIAL_8_BYTE_HIGH_WATER; - break; - - case 14: - - pDevExt->RxFifoTrigger = SERIAL_14_BYTE_HIGH_WATER; - break; - - default: - - pDevExt->RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER; - break; - - } - - - if (PConfigData->TxFIFO < 1) { - - pDevExt->TxFifoAmount = 1; - - } else { - - pDevExt->TxFifoAmount = PConfigData->TxFIFO; - - } - - if (!SerialDoesPortExist( - pDevExt, - &pDevExt->DeviceName, - PConfigData->ForceFifoEnable, - PConfigData->LogFifo - )) { - - // - // We couldn't verify that there was actually a - // port. No need to log an error as the port exist - // code will log exactly why. - // - - SerialDbgPrintEx(TRACE_LEVEL_WARNING, DBG_PNP, "DoesPortExist test failed for " - "%wZ\n", &pDevExt->DeviceName); - - status = STATUS_NO_SUCH_DEVICE; - goto ExtensionCleanup; - - } - - - // - // If the user requested that we disable the port, then - // do it now. Log the fact that the port has been disabled. - // - - if (PConfigData->DisablePort) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "disabled port %wZ as requested in " - "configuration\n", &pDevExt->DeviceName); - - status = STATUS_NO_SUCH_DEVICE; - - SerialLogError( - pDevExt->DriverObject, - pDevExt->DeviceObject, - PConfigData->TrController, - SerialPhysicalZero, - 0, - 0, - 0, - 57, - STATUS_SUCCESS, - SERIAL_DISABLED_PORT, - pDevExt->DeviceName.Length+sizeof(WCHAR), - pDevExt->DeviceName.Buffer, - 0, - NULL - ); - - goto ExtensionCleanup; - - } - - - - // - // Set up the default device control fields. - // Note that if the values are changed after - // the file is open, they do NOT revert back - // to the old value at file close. - // - - pDevExt->SpecialChars.XonChar = SERIAL_DEF_XON; - pDevExt->SpecialChars.XoffChar = SERIAL_DEF_XOFF; - pDevExt->HandFlow.ControlHandShake = SERIAL_DTR_CONTROL; - pDevExt->HandFlow.FlowReplace = SERIAL_RTS_CONTROL; - - - // - // Default Line control protocol. 7E1 - // - // Seven data bits. - // Even parity. - // 1 Stop bits. - // - - pDevExt->LineControl = SERIAL_7_DATA | - SERIAL_EVEN_PARITY | - SERIAL_NONE_PARITY; - - pDevExt->ValidDataMask = 0x7f; - pDevExt->CurrentBaud = 1200; - - - // - // We set up the default xon/xoff limits. - // - // This may be a bogus value. It looks like the BufferSize - // is not set up until the device is actually opened. - // - - pDevExt->HandFlow.XoffLimit = pDevExt->BufferSize >> 3; - pDevExt->HandFlow.XonLimit = pDevExt->BufferSize >> 1; - - pDevExt->BufferSizePt8 = ((3*(pDevExt->BufferSize>>2))+ - (pDevExt->BufferSize>>4)); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, " The default interrupt read buffer size is: %d\n" - "------ The XoffLimit is : %d\n" - "------ The XonLimit is : %d\n" - "------ The pt 8 size is : %d\n", - pDevExt->BufferSize, pDevExt->HandFlow.XoffLimit, - pDevExt->HandFlow.XonLimit, pDevExt->BufferSizePt8); - - - // - // Go through all the "named" baud rates to find out which ones - // can be supported with this port. - // - // - - pDevExt->SupportedBauds = SERIAL_BAUD_USER; - - - for(i=0; SupportedBaudRates[i].BaudRate != SERIAL_BAUD_INVALID; i++) { - - if (!NT_ERROR(SerialGetDivisorFromBaud( - pDevExt->ClockRate, - (LONG)SupportedBaudRates[i].BaudRate, - &junk - ))) { - - pDevExt->SupportedBauds |= SupportedBaudRates[i].Mask; - } - } - - - - - // - // Mark this device as not being opened by anyone. We keep a - // variable around so that spurious interrupts are easily - // dismissed by the ISR. - // - - SetDeviceIsOpened(pDevExt, FALSE, FALSE); - - // - // Store values into the extension for interval timing. - // - - // - // If the interval timer is less than a second then come - // in with a short "polling" loop. - // - // For large (> then 2 seconds) use a 1 second poller. - // - - pDevExt->ShortIntervalAmount.QuadPart = -1; - pDevExt->LongIntervalAmount.QuadPart = -10000000; - pDevExt->CutOverAmount.QuadPart = 200000000; - - DISABLE_ALL_INTERRUPTS (pDevExt, pDevExt->Controller); - - WRITE_MODEM_CONTROL(pDevExt, pDevExt->Controller, (UCHAR)0); - - // make sure there is no escape character currently set - pDevExt->EscapeChar = 0; - // - // This should set up everything as it should be when - // a device is to be opened. We do need to lower the - // modem lines, and disable the recalcitrant fifo - // so that it will show up if the user boots to dos. - // - - // __WARNING_IRQ_SET_TOO_HIGH: we are calling interrupt synchronize routine directly. Suppress it because interrupt is not connected yet. - // __WARNING_INVALID_PARAM_VALUE_1: Interrupt is UNREFERENCED_PARAMETER, so it can be NULL -#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) - SerialReset(NULL, pDevExt); - -#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) - SerialMarkClose(NULL, pDevExt); - -#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) - SerialClrRTS(NULL, pDevExt); - -#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) - SerialClrDTR(NULL, pDevExt); - - // - // Fill in WMI hardware data - // - pDevExt->WmiHwData.IrqNumber = pDevExt->Irql; - pDevExt->WmiHwData.IrqLevel = pDevExt->Irql; - pDevExt->WmiHwData.IrqVector = pDevExt->Vector; - pDevExt->WmiHwData.IrqAffinityMask = pDevExt->Affinity; - pDevExt->WmiHwData.InterruptType = pDevExt->InterruptMode == Latched - ? SERIAL_WMI_INTTYPE_LATCHED : SERIAL_WMI_INTTYPE_LEVEL; - pDevExt->WmiHwData.BaseIOAddress = (ULONG_PTR)pDevExt->Controller; - - // - // Fill in WMI device state data (as defaults) - // - - pDevExt->WmiCommData.BaudRate = pDevExt->CurrentBaud; - pDevExt->WmiCommData.BitsPerByte = (pDevExt->LineControl & 0x03) + 5; - pDevExt->WmiCommData.ParityCheckEnable = (pDevExt->LineControl & 0x08) - ? TRUE : FALSE; - - switch (pDevExt->LineControl & SERIAL_PARITY_MASK) { - case SERIAL_NONE_PARITY: - pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE; - break; - - case SERIAL_ODD_PARITY: - pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD; - break; - - case SERIAL_EVEN_PARITY: - pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN; - break; - - case SERIAL_MARK_PARITY: - pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK; - break; - - case SERIAL_SPACE_PARITY: - pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE; - break; - - default: - ASSERTMSG(0, "Illegal Parity setting for WMI"); - pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE; - break; - } - - pDevExt->WmiCommData.StopBits = pDevExt->LineControl & SERIAL_STOP_MASK - ? (pDevExt->WmiCommData.BitsPerByte == 5 ? SERIAL_WMI_STOP_1_5 - : SERIAL_WMI_STOP_2) : SERIAL_WMI_STOP_1; - pDevExt->WmiCommData.XoffCharacter = pDevExt->SpecialChars.XoffChar; - pDevExt->WmiCommData.XoffXmitThreshold = pDevExt->HandFlow.XoffLimit; - pDevExt->WmiCommData.XonCharacter = pDevExt->SpecialChars.XonChar; - pDevExt->WmiCommData.XonXmitThreshold = pDevExt->HandFlow.XonLimit; - pDevExt->WmiCommData.MaximumBaudRate - = SerialReportMaxBaudRate(pDevExt->SupportedBauds); - pDevExt->WmiCommData.MaximumOutputBufferSize = (UINT32)((ULONG)-1); - pDevExt->WmiCommData.MaximumInputBufferSize = (UINT32)((ULONG)-1); - pDevExt->WmiCommData.Support16BitMode = FALSE; - pDevExt->WmiCommData.SupportDTRDSR = TRUE; - pDevExt->WmiCommData.SupportIntervalTimeouts = TRUE; - pDevExt->WmiCommData.SupportParityCheck = TRUE; - pDevExt->WmiCommData.SupportRTSCTS = TRUE; - pDevExt->WmiCommData.SupportXonXoff = TRUE; - pDevExt->WmiCommData.SettableBaudRate = TRUE; - pDevExt->WmiCommData.SettableDataBits = TRUE; - pDevExt->WmiCommData.SettableFlowControl = TRUE; - pDevExt->WmiCommData.SettableParity = TRUE; - pDevExt->WmiCommData.SettableParityCheck = TRUE; - pDevExt->WmiCommData.SettableStopBits = TRUE; - pDevExt->WmiCommData.IsBusy = FALSE; - - // - // Common error path cleanup. If the status is - // bad, get rid of the device extension, device object - // and any memory associated with it. - // - -ExtensionCleanup: ; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialInitController %x\n", status); - - return status; -} - - -NTSTATUS -SerialMapHWResources( - IN WDFDEVICE Device, - IN WDFCMRESLIST PResList, - IN WDFCMRESLIST PTrResList, - OUT PCONFIG_DATA PConfig - ) -/*++ - -Routine Description: - - This routine will get the configuration information and put - it and the translated values into CONFIG_DATA structures. - -Arguments: - - Device - Handle to a framework device object. - - Resources - Handle to a collection of framework resource objects. - This collection identifies the raw (bus-relative) hardware - resources that have been assigned to the device. - - ResourcesTranslated - Handle to a collection of framework resource objects. - This collection identifies the translated (system-physical) - hardware resources that have been assigned to the device. - The resources appear from the CPU's point of view. - Use this list of resources to map I/O space and - device-accessible memory into virtual address space - -Return Value: - - STATUS_SUCCESS if consistant configuration was found - otherwise. - returns STATUS_SERIAL_NO_DEVICE_INITED. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - NTSTATUS status = STATUS_SUCCESS; - ULONG i; - PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialTrResourceDesc, pPartialRawResourceDesc; - ULONG gotInt = 0; - ULONG gotIO = 0; - ULONG ioResIndex = 0; - ULONG curIoIndex = 0; - ULONG gotMem = 0; - BOOLEAN DebugPortInUse = FALSE; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialMapHWResources\n"); - - // - // Get the DeviceExtension.. - // - pDevExt = SerialGetDeviceExtension (Device); - - if ((PResList == NULL) || (PTrResList == NULL)) { - ASSERT(PResList != NULL); - ASSERT(PTrResList != NULL); - status = STATUS_INSUFFICIENT_RESOURCES; - goto End; - } - - for (i = 0; i < WdfCmResourceListGetCount(PTrResList); i++) { - - pPartialTrResourceDesc = WdfCmResourceListGetDescriptor(PTrResList, i); - pPartialRawResourceDesc = WdfCmResourceListGetDescriptor(PResList, i); - - switch (pPartialTrResourceDesc->Type) { - case CmResourceTypePort: - - ASSERT(!(pPartialTrResourceDesc->u.Port.Length == SERIAL_STATUS_LENGTH)); - - if (gotIO == 0) { - - if (curIoIndex == ioResIndex) { - - gotIO = 1; - PConfig->TrController = pPartialTrResourceDesc->u.Port.Start; - - if (!PConfig->TrController.LowPart) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Bogus port address %x\n", - PConfig->TrController.LowPart); - status = STATUS_DEVICE_CONFIGURATION_ERROR; - goto End; - } - // - // We need the raw address to check if the debugger is using the com port - // - PConfig->Controller = pPartialRawResourceDesc->u.Port.Start; - PConfig->AddressSpace = pPartialTrResourceDesc->Flags; - pDevExt->SerialReadUChar = SerialReadPortUChar; - pDevExt->SerialWriteUChar = SerialWritePortUChar; - - } else { - curIoIndex++; - } - } - - break; - - // - // If this is 8 bytes long and we haven't found any I/O range, - // then this is probably a fancy-pants machine with memory replacing - // IO space - // - case CmResourceTypeMemory: - - ASSERT(!(pPartialTrResourceDesc->u.Port.Length == SERIAL_STATUS_LENGTH)); - - if ((gotMem == 0) && (gotIO == 0) - && (pPartialTrResourceDesc->u.Memory.Length - == (SERIAL_REGISTER_SPAN + SERIAL_STATUS_LENGTH))) { - gotMem = 1; - PConfig->TrController = pPartialTrResourceDesc->u.Memory.Start; - - if (!PConfig->TrController.LowPart) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Bogus I/O memory address %x\n", - PConfig->TrController.LowPart); - status = STATUS_DEVICE_CONFIGURATION_ERROR; - goto End; - } - - PConfig->Controller = pPartialRawResourceDesc->u.Memory.Start; - PConfig->AddressSpace = CM_RESOURCE_PORT_MEMORY; - PConfig->SpanOfController = SERIAL_REGISTER_SPAN; - pDevExt->SerialReadUChar = SerialReadRegisterUChar; - pDevExt->SerialWriteUChar = SerialWriteRegisterUChar; - } - break; - - case CmResourceTypeInterrupt: - if (gotInt == 0) { - gotInt = 1; - PConfig->TrVector = pPartialTrResourceDesc->u.Interrupt.Vector; - - if (!PConfig->TrVector) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Bogus vector 0\n"); - status = STATUS_DEVICE_CONFIGURATION_ERROR; - goto End; - } - - if (pPartialTrResourceDesc->ShareDisposition == CmResourceShareShared) { - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Sharing interrupt with other devices \n"); - } else { - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Interrupt is not shared with other devices\n"); - } - - PConfig->TrIrql = pPartialTrResourceDesc->u.Interrupt.Level; - PConfig->Affinity = pPartialTrResourceDesc->u.Interrupt.Affinity; - } - break; - - default: break; - } // switch (pPartialTrResourceDesc->Type) - - } // for (i = 0; i < WdfCollectionGetCount - - if(!((gotMem || gotIO) && gotInt) ) - { - status = STATUS_INSUFFICIENT_RESOURCES; - goto End; - } - - // - // First check what type of AddressSpace this port is in. Then check - // if the debugger is using this port. If it is, set DebugPortInUse to TRUE. - // - if(PConfig->AddressSpace == CM_RESOURCE_PORT_MEMORY) { - - PHYSICAL_ADDRESS KdComPhysical; - - KdComPhysical = MmGetPhysicalAddress(*KdComPortInUse); - - if(KdComPhysical.LowPart == PConfig->Controller.LowPart) { - DebugPortInUse = TRUE; - } - - } else { - // - // This compare is done using **untranslated** values since that is what - // the kernel shoves in regardless of the architecture. - // - - if ((*KdComPortInUse) == (ULongToPtr(PConfig->Controller.LowPart))) { - DebugPortInUse = TRUE; - } - } - - if (DebugPortInUse) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Kernel debugger is using port at " - "address %p\n", *KdComPortInUse); - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Serial driver will not load port\n"); - - SerialLogError( - pDevExt->DriverObject, - NULL, - PConfig->TrController, - SerialPhysicalZero, - 0, - 0, - 0, - 3, - STATUS_SUCCESS, - SERIAL_KERNEL_DEBUGGER_ACTIVE, - pDevExt->DeviceName.Length+sizeof(WCHAR), - pDevExt->DeviceName.Buffer, - 0, - NULL - ); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto End; - } - -End: - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialMapHWResources %x\n", status); - - return status; -} - -VOID -SerialUnmapHWResources( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ) -/*++ - -Routine Description: - - Releases resources (not pool) stored in the device extension. - -Arguments: - - PDevExt - Pointer to the device extension to release resources from. - -Return Value: - - VOID - ---*/ -{ - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "-->SerialUnMapResources(%p)\n", - PDevExt); - PAGED_CODE(); - - // - // If necessary, unmap the device registers. - // - - if (PDevExt->UnMapRegisters) { - MmUnmapIoSpace(PDevExt->Controller, PDevExt->SpanOfController); - PDevExt->UnMapRegisters = FALSE; - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<--SerialUnMapResources\n"); -} - - -NTSTATUS -SerialReadSymName( - IN WDFDEVICE Device, - _Out_writes_bytes_(*SizeOfRegName) PWSTR RegName, - _Inout_ PUSHORT SizeOfRegName - ) -{ - NTSTATUS status; - WDFKEY hKey; - UNICODE_STRING value; - UNICODE_STRING valueName; - USHORT requiredLength; - - PAGED_CODE(); - - value.Buffer = RegName; - value.MaximumLength = *SizeOfRegName; - value.Length = 0; - - status = WdfDeviceOpenRegistryKey(Device, - PLUGPLAY_REGKEY_DEVICE, - STANDARD_RIGHTS_ALL, - WDF_NO_OBJECT_ATTRIBUTES, - &hKey); - - if (NT_SUCCESS (status)) { - // - // Fetch PortName which contains the suggested REG_SZ symbolic name. - // - - - RtlInitUnicodeString(&valueName, L"PortName"); - - status = WdfRegistryQueryUnicodeString (hKey, - &valueName, - &requiredLength, - &value); - - if (!NT_SUCCESS (status)) { - // - // This is for PCMCIA which currently puts the name under Identifier. - // - - RtlInitUnicodeString(&valueName, L"Identifier"); - status = WdfRegistryQueryUnicodeString (hKey, - &valueName, - &requiredLength, - &value); - - if (!NT_SUCCESS(status)) { - // - // Hmm. Either we have to pick a name or bail... - // - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Getting PortName/Identifier failed - %x\n", status); - } - } - - WdfRegistryClose(hKey); - } - - if(NT_SUCCESS(status)) { - // - // NULL terminate the string and return number of characters in the string. - // - if(value.Length > *SizeOfRegName - sizeof(WCHAR)) { - return STATUS_UNSUCCESSFUL; - } - - *SizeOfRegName = value.Length; - RegName[*SizeOfRegName/sizeof(WCHAR)] = UNICODE_NULL; - } - return status; -} - - -NTSTATUS -SerialDoExternalNaming(IN PSERIAL_DEVICE_EXTENSION PDevExt) - -/*++ - -Routine Description: - - This routine will be used to create a symbolic link - to the driver name in the given object directory. - - It will also create an entry in the device map for - this device - IF we could create the symbolic link. - -Arguments: - - Extension - Pointer to the device extension. - -Return Value: - - None. - ---*/ - -{ - NTSTATUS status = STATUS_SUCCESS; - WCHAR pRegName[SYMBOLIC_NAME_LENGTH]; - USHORT nameSize = sizeof(pRegName); - WDFSTRING stringHandle = NULL; - WDF_OBJECT_ATTRIBUTES attributes; - DECLARE_UNICODE_STRING_SIZE(symbolicLinkName,SYMBOLIC_NAME_LENGTH ) ; - - PAGED_CODE(); - - WDF_OBJECT_ATTRIBUTES_INIT(&attributes); - attributes.ParentObject = PDevExt->WdfDevice; - status = WdfStringCreate(NULL, &attributes, &stringHandle); - if(!NT_SUCCESS(status)){ - goto SerialDoExternalNamingError; - } - - status = WdfDeviceRetrieveDeviceName(PDevExt->WdfDevice, stringHandle); - if(!NT_SUCCESS(status)){ - goto SerialDoExternalNamingError; - } - - // - // Since we are storing the buffer pointer of the string handle in our - // extension, we will hold onto string handle until the device is deleted. - // - WdfStringGetUnicodeString(stringHandle, &PDevExt->DeviceName); - - SerialGetRegistryKeyValue(PDevExt->WdfDevice, L"SerialSkipExternalNaming", &PDevExt->SkipNaming); - - if (PDevExt->SkipNaming) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Skipping external naming due to registry settings\n"); - return STATUS_SUCCESS; - } - - status = SerialReadSymName(PDevExt->WdfDevice, pRegName, &nameSize); - if (!NT_SUCCESS(status)) { - goto SerialDoExternalNamingError; - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "DosName is %ws\n", pRegName); - - status = RtlUnicodeStringPrintf(&symbolicLinkName, - L"%ws%ws", - L"\\DosDevices\\", - pRegName); - - if (!NT_SUCCESS(status)) { - goto SerialDoExternalNamingError; - } - - status = WdfDeviceCreateSymbolicLink(PDevExt->WdfDevice, &symbolicLinkName); - - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't create the symbolic link for port %wZ\n", &symbolicLinkName); - - goto SerialDoExternalNamingError; - - } - - - PDevExt->CreatedSymbolicLink = TRUE; - - status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, - PDevExt->DeviceName.Buffer, - REG_SZ, - pRegName, - nameSize + sizeof(WCHAR)); - - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't create the device map entry\n" - "------- for port %ws\n", PDevExt->DeviceName.Buffer); - - goto SerialDoExternalNamingError; - } - - PDevExt->CreatedSerialCommEntry = TRUE; - - // - // Make the device visible via a device association as well. - // The reference string is the eight digit device index - // - status = WdfDeviceCreateDeviceInterface(PDevExt->WdfDevice, - (LPGUID) &GUID_DEVINTERFACE_COMPORT, - NULL); - - if (!NT_SUCCESS (status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't register class association\n" - "for port %wZ\n", &PDevExt->DeviceName); - - goto SerialDoExternalNamingError; - } - - return status; - - SerialDoExternalNamingError:; - - // - // Clean up error conditions - // - - PDevExt->DeviceName.Buffer = NULL; - - if (PDevExt->CreatedSerialCommEntry) { - _Analysis_assume_(NULL != PDevExt->DeviceName.Buffer); - RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, - PDevExt->DeviceName.Buffer); - } - - if(stringHandle) { - WdfObjectDelete(stringHandle); - } - - return status; -} - - -VOID -SerialUndoExternalNaming(IN PSERIAL_DEVICE_EXTENSION Extension) - -/*++ - -Routine Description: - - This routine will be used to delete a symbolic link - to the driver name in the given object directory. - - It will also delete an entry in the device map for - this device if the symbolic link had been created. - -Arguments: - - Extension - Pointer to the device extension. - -Return Value: - - None. - ---*/ - -{ - - NTSTATUS status; - PWCHAR deviceName = Extension->DeviceName.Buffer; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "In SerialUndoExternalNaming for extension: " - "%p of port %ws\n", Extension, deviceName); - - // - // Maybe there is nothing for us to do - // - - if (Extension->SkipNaming) { - return; - } - - // - // We're cleaning up here. One reason we're cleaning up - // is that we couldn't allocate space for the NtNameOfPort. - // - - if ((deviceName != NULL) && Extension->CreatedSerialCommEntry) { - - status = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, - SERIAL_DEVICE_MAP, - deviceName); - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, - "Couldn't delete value entry %ws\n", - deviceName); - - } - } -} - -VOID -SerialPurgePendingRequests(PSERIAL_DEVICE_EXTENSION pDevExt) -/*++ - -Routine Description: - - This routine completes any irps pending for the passed device object. - -Arguments: - - PDevObj - Pointer to the device object whose irps must die. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS status; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - ">SerialPurgePendingRequests(%p)\n", pDevExt); - - // - // Then cancel all the reads and writes. - // - - SerialPurgeRequests(pDevExt->WriteQueue, &pDevExt->CurrentWriteRequest); - - SerialPurgeRequests(pDevExt->ReadQueue, &pDevExt->CurrentReadRequest); - - // - // Next get rid of purges. - // - - SerialPurgeRequests(pDevExt->PurgeQueue, &pDevExt->CurrentPurgeRequest); - - // - // Get rid of any mask operations. - // - - SerialPurgeRequests( pDevExt->MaskQueue, &pDevExt->CurrentMaskRequest); - - // - // Now get rid of pending wait mask request. - // - - if (pDevExt->CurrentWaitRequest) { - - status = SerialClearCancelRoutine(pDevExt->CurrentWaitRequest, TRUE ); - if (NT_SUCCESS(status)) { - - SerialCompleteRequest(pDevExt->CurrentWaitRequest, STATUS_CANCELLED, 0); - pDevExt->CurrentWaitRequest = NULL; - - } - - } - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Controller); - - // - // Make sure that we are *aren't* accessing the divsior latch. - // - - WRITE_LINE_CONTROL(Extension, - Extension->Controller, - (UCHAR)(oldLCRContents & ~SERIAL_LCR_DLAB) - ); - - oldIERContents = READ_INTERRUPT_ENABLE(Extension, Extension->Controller); - - // - // Go up to power level for a very short time to prevent - // any interrupts from this device from coming in. - // - - KeRaiseIrql( - POWER_LEVEL, - &oldIrql - ); - - WRITE_INTERRUPT_ENABLE(Extension, - Extension->Controller, - 0x0f - ); - - value1 = READ_INTERRUPT_ENABLE(Extension, Extension->Controller); - value1 = value1 << 8; - value1 |= READ_RECEIVE_BUFFER(Extension, Extension->Controller); - - READ_DIVISOR_LATCH(Extension, - Extension->Controller, - (PSHORT) &value2 - ); - - WRITE_LINE_CONTROL(Extension, - Extension->Controller, - oldLCRContents - ); - - // - // Put the ier back to where it was before. If we are on a - // level sensitive port this should prevent the interrupts - // from coming in. If we are on a latched, we don't care - // cause the interrupts generated will just get dropped. - // - - WRITE_INTERRUPT_ENABLE(Extension, - Extension->Controller, - oldIERContents - ); - - KeLowerIrql(oldIrql); - - if (value1 == value2) { - - SerialLogError( - Extension->DeviceObject->DriverObject, - Extension->DeviceObject, - SerialPhysicalZero, - SerialPhysicalZero, - 0, - 0, - 0, - 62, - STATUS_SUCCESS, - SERIAL_DLAB_INVALID, - InsertString->Length+sizeof(WCHAR), - InsertString->Buffer, - 0, - NULL - ); - returnValue = FALSE; - goto AllDone; - - } - - AllDone: ; - - - // - // If we think that there is a serial device then we determine - // if a fifo is present. - // - - if (returnValue) { - - // - // Well, we think it's a serial device. Absolutely - // positively, prevent interrupts from occuring. - // - // We disable all the interrupt enable bits, and - // push down all the lines in the modem control - // We only needed to push down OUT2 which in - // PC's must also be enabled to get an interrupt. - // - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - - WRITE_MODEM_CONTROL(Extension, Extension->Controller, (UCHAR)0); - - // - // See if this is a 16550. We do this by writing to - // what would be the fifo control register with a bit - // pattern that tells the device to enable fifo's. - // We then read the iterrupt Id register to see if the - // bit pattern is present that identifies the 16550. - // - - WRITE_FIFO_CONTROL(Extension, - Extension->Controller, - SERIAL_FCR_ENABLE - ); - - regContents = READ_INTERRUPT_ID_REG(Extension, Extension->Controller); - - if (regContents & SERIAL_IIR_FIFOS_ENABLED) { - - // - // Save off that the device supports fifos. - // - - Extension->FifoPresent = TRUE; - - // - // There is a fine new "super" IO chip out there that - // will get stuck with a line status interrupt if you - // attempt to clear the fifo and enable it at the same - // time if data is present. The best workaround seems - // to be that you should turn off the fifo read a single - // byte, and then re-enable the fifo. - // - - WRITE_FIFO_CONTROL(Extension, - Extension->Controller, - (UCHAR)0 - ); - - READ_RECEIVE_BUFFER(Extension, Extension->Controller); - - // - // There are fifos on this card. Set the value of the - // receive fifo to interrupt when 4 characters are present. - // - - WRITE_FIFO_CONTROL(Extension, Extension->Controller, - (UCHAR)(SERIAL_FCR_ENABLE - | Extension->RxFifoTrigger - | SERIAL_FCR_RCVR_RESET - | SERIAL_FCR_TXMT_RESET)); - - } - - // - // The !Extension->FifoPresent is included in the test so that - // broken chips like the WinBond will still work after we test - // for the fifo. - // - - if (!ForceFifo || !Extension->FifoPresent) { - - Extension->FifoPresent = FALSE; - WRITE_FIFO_CONTROL(Extension, - Extension->Controller, - (UCHAR)0 - ); - - } - - if (Extension->FifoPresent) { - - if (LogFifo) { - - SerialLogError( - Extension->DeviceObject->DriverObject, - Extension->DeviceObject, - SerialPhysicalZero, - SerialPhysicalZero, - 0, - 0, - 0, - 15, - STATUS_SUCCESS, - SERIAL_FIFO_PRESENT, - InsertString->Length+sizeof(WCHAR), - InsertString->Buffer, - 0, - NULL - ); - - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, - "Fifo's detected at port address: %p\n", - Extension->Controller); - } - } - - return returnValue; -} - - - -BOOLEAN -SerialReset( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This places the hardware in a standard configuration. - - NOTE: This assumes that it is called at interrupt level. - - -Arguments: - - Context - The device extension for serial device - being managed. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension = Context; - UCHAR regContents; - UCHAR oldModemControl; - ULONG i; - - UNREFERENCED_PARAMETER(Interrupt); - - // - // Adjust the out2 bit. - // This will also prevent any interrupts from occuring. - // - - oldModemControl = READ_MODEM_CONTROL(extension, extension->Controller); - - WRITE_MODEM_CONTROL(extension, extension->Controller, - (UCHAR)(oldModemControl & ~SERIAL_MCR_OUT2)); - - // - // Reset the fifo's if there are any. - // - - if (extension->FifoPresent) { - - // - // There is a fine new "super" IO chip out there that - // will get stuck with a line status interrupt if you - // attempt to clear the fifo and enable it at the same - // time if data is present. The best workaround seems - // to be that you should turn off the fifo read a single - // byte, and then re-enable the fifo. - // - - WRITE_FIFO_CONTROL(extension, - extension->Controller, - (UCHAR)0 - ); - - READ_RECEIVE_BUFFER(extension, extension->Controller); - - WRITE_FIFO_CONTROL(extension, - extension->Controller, - (UCHAR)(SERIAL_FCR_ENABLE | extension->RxFifoTrigger | - SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET) - ); - - } - - // - // Make sure that the line control set up correct. - // - // 1) Make sure that the Divisor latch select is set - // up to select the transmit and receive register. - // - // 2) Make sure that we aren't in a break state. - // - - regContents = READ_LINE_CONTROL(extension, extension->Controller); - regContents &= ~(SERIAL_LCR_DLAB | SERIAL_LCR_BREAK); - - WRITE_LINE_CONTROL(extension, - extension->Controller, - regContents - ); - - // - // Read the receive buffer until the line status is - // clear. (Actually give up after a 5 reads.) - // - - for (i = 0; - i < 5; - i++ - ) { - #pragma warning(disable: 4127) - if (IsNotNEC_98) { - #pragma warning(default: 4127) - READ_RECEIVE_BUFFER(extension, extension->Controller); - if (!(READ_LINE_STATUS(extension, extension->Controller) & 1)) { - - break; - - } - } else { - // - // I get incorrect data when read enpty buffer. - // But do not read no data! for PC98! - // - if (!(READ_LINE_STATUS(extension, extension->Controller) & 1)) { - - break; - - } - READ_RECEIVE_BUFFER(extension, extension->Controller); - } - - } - - // - // Read the modem status until the low 4 bits are - // clear. (Actually give up after a 5 reads.) - // - - for (i = 0; - i < 1000; - i++ - ) { - - if (!(READ_MODEM_STATUS(extension, extension->Controller) & 0x0f)) { - - break; - - } - - } - - // - // Now we set the line control, modem control, and the - // baud to what they should be. - // - - // - // See if we have to enable special Auto Flow Control - // - - if (extension->TL16C550CAFC) { - oldModemControl = READ_MODEM_CONTROL(extension, extension->Controller); - - WRITE_MODEM_CONTROL(extension, extension->Controller, - (UCHAR)(oldModemControl | SERIAL_MCR_TL16C550CAFE)); - } - - - - SerialSetLineControl(extension->WdfInterrupt, extension); - - SerialSetupNewHandFlow( - extension, - &extension->HandFlow - ); - - SerialHandleModemUpdate( - extension, - FALSE - ); - - { - SHORT appropriateDivisor; - SERIAL_IOCTL_SYNC s; - - SerialGetDivisorFromBaud( extension->ClockRate, - extension->CurrentBaud, - &appropriateDivisor ); - - s.Extension = extension; - s.Data = (PVOID) (ULONG_PTR) appropriateDivisor; - SerialSetBaud(extension->WdfInterrupt, &s); - } - - // - // Enable which interrupts we want to receive. - // - // NOTE NOTE: This does not actually let interrupts - // occur. We must still raise the OUT2 bit in the - // modem control register. We will do that on open. - // - - ENABLE_ALL_INTERRUPTS(extension, extension->Controller); - - // - // Read the interrupt id register until the low bit is - // set. (Actually give up after a 5 reads.) - // - - for (i = 0; - i < 5; - i++ - ) { - - if (READ_INTERRUPT_ID_REG(extension, extension->Controller) & 0x01) { - - break; - - } - - } - - // - // Now we know that nothing could be transmitting at this point - // so we set the HoldingEmpty indicator. - // - - extension->HoldingEmpty = TRUE; - - return FALSE; -} - - - -PVOID -SerialGetMappedAddress( - PHYSICAL_ADDRESS IoAddress, - ULONG NumberOfBytes, - ULONG AddressSpace, - PBOOLEAN MappedAddress - ) - -/*++ - -Routine Description: - - This routine maps an IO address to system address space. - -Arguments: - - IoAddress - base device address to be mapped. - NumberOfBytes - number of bytes for which address is valid. - AddressSpace - Denotes whether the address is in io space or memory. - MappedAddress - indicates whether the address was mapped. - This only has meaning if the address returned - is non-null. - -Return Value: - - Mapped address - ---*/ - -{ - PVOID address; - - PAGED_CODE(); - - // - // Map the device base address into the virtual address space - // if the address is in memory space. - // - - if (!AddressSpace) { - - address = LocalMmMapIoSpace(IoAddress, - NumberOfBytes); - - *MappedAddress = (BOOLEAN)((address)?(TRUE):(FALSE)); - - - } else { - - address = ULongToPtr(IoAddress.LowPart); - *MappedAddress = FALSE; - - } - - return address; -} - -VOID -SerialSetInterruptPolicy( - _In_ WDFINTERRUPT WdfInterrupt - ) -/*++ - -Routine Description: - - This routine shows how to set the interrupt policy preferences. - -Arguments: - - WdfInterrupt - Interrupt object handle. - -Return Value: - - None - ---*/ -{ - WDF_INTERRUPT_EXTENDED_POLICY policyAndGroup; -#ifdef SERIAL_SELECT_INTERRUPT_GROUP - USHORT groupCount = 1; - USHORT group = 0; - UNICODE_STRING funcName; - PFN_KE_GET_ACTIVE_GROUP_COUNT fnKeQueryActiveGroupCount; - PFN_KE_QUERY_GROUP_AFFINITY fnKeQueryGroupAffinity; - KAFFINITY groupAffinity = (KAFFINITY)1; -#endif - - WDF_INTERRUPT_EXTENDED_POLICY_INIT(&policyAndGroup); - policyAndGroup.Priority = WdfIrqPriorityNormal; - -#ifdef SERIAL_SELECT_INTERRUPT_GROUP - // - // If OS supports groups, find how many they are. - // - RtlInitUnicodeString(&funcName, L"KeQueryActiveGroupCount"); - fnKeQueryActiveGroupCount = (PFN_KE_GET_ACTIVE_GROUP_COUNT) - MmGetSystemRoutineAddress(&funcName); - - if (fnKeQueryActiveGroupCount != NULL) { - groupCount = fnKeQueryActiveGroupCount(); - - // - // Make sure there is at least one group for the boot processor. - // - if (0 == groupCount) { - groupCount = 1; - } - } - - if (groupCount <= SERIAL_PREFERRED_INTERRUPT_GROUP) { - group = groupCount - 1; - } - else { - group = SERIAL_PREFERRED_INTERRUPT_GROUP; - } - - // - // Get the group affinity. - // - RtlInitUnicodeString(&funcName, L"KeQueryGroupAffinity"); - fnKeQueryGroupAffinity = (PFN_KE_QUERY_GROUP_AFFINITY) - MmGetSystemRoutineAddress(&funcName); - - if (fnKeQueryGroupAffinity != NULL) { - groupAffinity = fnKeQueryGroupAffinity(group); - - // - // Active groups have at least one processor. - // - if ((KAFFINITY)0 == groupAffinity) { - groupAffinity = (KAFFINITY)1; - } - } - - // - // Initialize group. - // - policyAndGroup.Policy = WdfIrqPolicySpecifiedProcessors; - policyAndGroup.TargetProcessorSetAndGroup.Group = group; - policyAndGroup.TargetProcessorSetAndGroup.Mask = groupAffinity; -#endif - - // - // Set interrupt policy and group preference. - // - WdfInterruptSetExtendedPolicy(WdfInterrupt, &policyAndGroup); -} - diff --git a/tests/projects/wdk/kmdf/serial/power.c b/tests/projects/wdk/kmdf/serial/power.c deleted file mode 100644 index 68aad3efa..000000000 --- a/tests/projects/wdk/kmdf/serial/power.c +++ /dev/null @@ -1,331 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - power.c - -Abstract: - - This module contains the code that handles the power IRPs for the serial - driver. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - - -#if defined(EVENT_TRACING) -#include "power.tmh" -#endif - - -PCHAR -DbgDevicePowerString( - IN WDF_POWER_DEVICE_STATE Type - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGESER,SerialEvtDeviceD0Exit) -#pragma alloc_text(PAGESER,SerialSaveDeviceState) -#endif // ALLOC_PRAGMA - -PCHAR -DbgDevicePowerString( - IN WDF_POWER_DEVICE_STATE Type - ) -/*++ - -Updated Routine Description: - DbgDevicePowerString does not change in this stage of the function driver. - ---*/ -{ - - switch (Type) - { - case WdfPowerDeviceInvalid: - return "WdfPowerDeviceInvalid"; - case WdfPowerDeviceD0: - return "WdfPowerDeviceD0"; - case WdfPowerDeviceD1: - return "WdfPowerDeviceD1"; - case WdfPowerDeviceD2: - return "WdfPowerDeviceD2"; - case WdfPowerDeviceD3: - return "WdfPowerDeviceD3"; - case WdfPowerDeviceD3Final: - return "WdfPowerDeviceD3Final"; - case WdfPowerDevicePrepareForHibernation: - return "WdfPowerDevicePrepareForHibernation"; - case WdfPowerDeviceMaximum: - return "WdfPowerDeviceMaximum"; - default: - return "UnKnown Device Power State"; - } -} - -NTSTATUS -SerialEvtDeviceD0Entry( - IN WDFDEVICE Device, - IN WDF_POWER_DEVICE_STATE PreviousState - ) -/*++ - -Routine Description: - - EvtDeviceD0Entry event callback must perform any operations that are - necessary before the specified device is used. It will be called every - time the hardware needs to be (re-)initialized. This includes after - IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE, - IRP_MN_SET_POWER-D0. - - This function is not marked pageable because this function is in the - device power up path. When a function is marked pagable and the code - section is paged out, it will generate a page fault which could impact - the fast resume behavior because the client driver will have to wait - until the system drivers can service this page fault. - - This function runs at PASSIVE_LEVEL, even though it is not paged. A - driver can optionally make this function pageable if DO_POWER_PAGABLE - is set. Even if DO_POWER_PAGABLE isn't set, this function still runs - at PASSIVE_LEVEL. In this case, though, the function absolutely must - not do anything that will cause a page fault. - -Arguments: - - Device - Handle to a framework device object. - - PreviousState - Device power state which the device was in most recently. - If the device is being newly started, this will be - PowerDeviceUnspecified. - -Return Value: - - NTSTATUS - ---*/ -{ - PSERIAL_DEVICE_EXTENSION deviceExtension; - PSERIAL_DEVICE_STATE pDevState; - SHORT divisor; - SERIAL_IOCTL_SYNC S; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, - "-->SerialEvtDeviceD0Entry - coming from %s\n", DbgDevicePowerString(PreviousState)); - - deviceExtension = SerialGetDeviceExtension (Device); - pDevState = &deviceExtension->DeviceState; - - // - // Restore the state of the UART. First, that involves disabling - // interrupts both via OUT2 and IER. - // - - WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller, 0); - DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller); - - // - // Set the baud rate - // - - SerialGetDivisorFromBaud(deviceExtension->ClockRate, deviceExtension->CurrentBaud, &divisor); - S.Extension = deviceExtension; - S.Data = (PVOID) (ULONG_PTR) divisor; - -#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "PFD warning that we are calling interrupt synchronize routine directly. Suppress it because interrupt is disabled above.") - SerialSetBaud(deviceExtension->WdfInterrupt, &S); - - // - // Reset / Re-enable the FIFO's - // - - if (deviceExtension->FifoPresent) { - WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0); - READ_RECEIVE_BUFFER(deviceExtension, deviceExtension->Controller); - WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, - (UCHAR)(SERIAL_FCR_ENABLE | deviceExtension->RxFifoTrigger - | SERIAL_FCR_RCVR_RESET - | SERIAL_FCR_TXMT_RESET)); - } else { - WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0); - } - - // - // Restore a couple more registers - // - - WRITE_INTERRUPT_ENABLE(deviceExtension, deviceExtension->Controller, pDevState->IER); - WRITE_LINE_CONTROL(deviceExtension, deviceExtension->Controller, pDevState->LCR); - - // - // Clear out any stale interrupts - // - - READ_INTERRUPT_ID_REG(deviceExtension, deviceExtension->Controller); - READ_LINE_STATUS(deviceExtension, deviceExtension->Controller); - READ_MODEM_STATUS(deviceExtension, deviceExtension->Controller); - - // - // TODO: move this code to EvtInterruptEnable. - // - - if (deviceExtension->DeviceState.Reopen == TRUE) { - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Reopening device\n"); - - SetDeviceIsOpened(deviceExtension, TRUE, FALSE); - - // - // This enables interrupts on the device! - // - - WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller, - (UCHAR)(pDevState->MCR | SERIAL_MCR_OUT2)); - - // - // Refire the state machine - // - - DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller); - ENABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller); - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--SerialEvtDeviceD0Entry\n"); - - return STATUS_SUCCESS; -} - - -NTSTATUS -SerialEvtDeviceD0Exit( - IN WDFDEVICE Device, - IN WDF_POWER_DEVICE_STATE TargetState - ) -/*++ - -Routine Description: - - EvtDeviceD0Exit event callback must perform any operations that are - necessary before the specified device is moved out of the D0 state. If the - driver needs to save hardware state before the device is powered down, then - that should be done here. - - This function runs at PASSIVE_LEVEL, though it is generally not paged. A - driver can optionally make this function pageable if DO_POWER_PAGABLE is set. - - Even if DO_POWER_PAGABLE isn't set, this function still runs at - PASSIVE_LEVEL. In this case, though, the function absolutely must not do - anything that will cause a page fault. - -Arguments: - - Device - Handle to a framework device object. - - TargetState - Device power state which the device will be put in once this - callback is complete. - -Return Value: - - NTSTATUS - ---*/ -{ - PSERIAL_DEVICE_EXTENSION deviceExtension; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, - "-->SerialEvtDeviceD0Exit - moving to %s\n", DbgDevicePowerString(TargetState)); - - PAGED_CODE(); - - deviceExtension = SerialGetDeviceExtension (Device); - - if (deviceExtension->DeviceIsOpened == TRUE) { - LARGE_INTEGER charTime; - - SetDeviceIsOpened(deviceExtension, FALSE, TRUE); - - charTime.QuadPart = -SerialGetCharTime(deviceExtension).QuadPart; - - // - // Shut down the chip - // - - SerialDisableUART(deviceExtension); - - // - // Drain the device - // - - SerialDrainUART(deviceExtension, &charTime); - - // - // Save the device state - // - - SerialSaveDeviceState(deviceExtension); - } - else - { - SetDeviceIsOpened(deviceExtension, FALSE, FALSE); - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--SerialEvtDeviceD0Exit\n"); - - return STATUS_SUCCESS; -} - - -VOID -SerialSaveDeviceState(IN PSERIAL_DEVICE_EXTENSION PDevExt) -/*++ - -Routine Description: - - This routine saves the device state of the UART - -Arguments: - - PDevExt - Pointer to the device extension for the devobj to save the state - for. - -Return Value: - - VOID - - ---*/ -{ - PSERIAL_DEVICE_STATE pDevState = &PDevExt->DeviceState; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Entering SerialSaveDeviceState\n"); - - // - // Read necessary registers direct - // - - pDevState->IER = READ_INTERRUPT_ENABLE(PDevExt, PDevExt->Controller); - pDevState->MCR = READ_MODEM_CONTROL(PDevExt, PDevExt->Controller); - pDevState->LCR = READ_LINE_CONTROL(PDevExt, PDevExt->Controller); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Leaving SerialSaveDeviceState\n"); -} - - -VOID -SetDeviceIsOpened(IN PSERIAL_DEVICE_EXTENSION PDevExt, IN BOOLEAN DeviceIsOpened, IN BOOLEAN Reopen) -{ - - PDevExt->DeviceIsOpened = DeviceIsOpened; - PDevExt->DeviceState.Reopen = Reopen; - -} - - - diff --git a/tests/projects/wdk/kmdf/serial/precomp.h b/tests/projects/wdk/kmdf/serial/precomp.h deleted file mode 100644 index 7c7c5d5ef..000000000 --- a/tests/projects/wdk/kmdf/serial/precomp.h +++ /dev/null @@ -1,18 +0,0 @@ - -#include -#include -#define WIN9X_COMPAT_SPINLOCK -#include "ntddk.h" -#include -#define NTSTRSAFE_LIB -#include -#include "ntddser.h" -#include -#include // required for GUID definitions -#include -#include "serial.h" -#include "serialp.h" -#include "serlog.h" -#include "log.h" -#include "trace.h" - diff --git a/tests/projects/wdk/kmdf/serial/precompsrc.c b/tests/projects/wdk/kmdf/serial/precompsrc.c deleted file mode 100644 index 5944cf515..000000000 --- a/tests/projects/wdk/kmdf/serial/precompsrc.c +++ /dev/null @@ -1 +0,0 @@ -#include "precomp.h" \ No newline at end of file diff --git a/tests/projects/wdk/kmdf/serial/purge.c b/tests/projects/wdk/kmdf/serial/purge.c deleted file mode 100644 index fcc32148e..000000000 --- a/tests/projects/wdk/kmdf/serial/purge.c +++ /dev/null @@ -1,175 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - purge.c - -Abstract: - - This module contains the code that is very specific to purge - operations in the serial driver - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "purge.tmh" -#endif - - -VOID -SerialStartPurge( - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - Depending on the mask in the current request, purge the interrupt - buffer, the read queue, or the write queue, or all of the above. - -Arguments: - - Extension - Pointer to the device extension. - -Return Value: - - Will return STATUS_SUCCESS always. This is reasonable - since the DPC completion code that calls this routine doesn't - care and the purge request always goes through to completion - once it's started. - ---*/ - -{ - - WDFREQUEST NewRequest; - PREQUEST_CONTEXT reqContext; - - do { - - ULONG Mask; - reqContext = SerialGetRequestContext(Extension->CurrentPurgeRequest); - Mask = *((ULONG *) (reqContext->SystemBuffer)); - - if (Mask & SERIAL_PURGE_TXABORT) { - - SerialFlushRequests( - Extension->WriteQueue, - &Extension->CurrentWriteRequest - ); - - SerialFlushRequests( - Extension->WriteQueue, - &Extension->CurrentXoffRequest - ); - - } - - if (Mask & SERIAL_PURGE_RXABORT) { - - SerialFlushRequests( - Extension->ReadQueue, - &Extension->CurrentReadRequest - ); - - } - - if (Mask & SERIAL_PURGE_RXCLEAR) { - - // - // Clean out the interrupt buffer. - // - // Note that we do this under protection of the - // the drivers control lock so that we don't hose - // the pointers if there is currently a read that - // is reading out of the buffer. - // - - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialPurgeInterruptBuff, - Extension - ); - - } - - reqContext->Status = STATUS_SUCCESS; - reqContext->Information = 0; - - SerialGetNextRequest( - &Extension->CurrentPurgeRequest, - Extension->PurgeQueue, - &NewRequest, - TRUE, - Extension - ); - - } while (NewRequest); - - return; - -} - -BOOLEAN -SerialPurgeInterruptBuff( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine simply resets the interrupt (typeahead) buffer. - - NOTE: This routine is being called from WdfInterruptSynchronize. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - Always false. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - UNREFERENCED_PARAMETER(Interrupt); - - // - // The typeahead buffer is by definition empty if there - // currently is a read owned by the isr. - // - - - if (Extension->ReadBufferBase == Extension->InterruptReadBuffer) { - - Extension->CurrentCharSlot = Extension->InterruptReadBuffer; - Extension->FirstReadableChar = Extension->InterruptReadBuffer; - Extension->LastCharSlot = Extension->InterruptReadBuffer + - (Extension->BufferSize - 1); - Extension->CharsInInterruptBuffer = 0; - - SerialHandleReducedIntBuffer(Extension); - - } - - return FALSE; - -} - - diff --git a/tests/projects/wdk/kmdf/serial/qsfile.c b/tests/projects/wdk/kmdf/serial/qsfile.c deleted file mode 100644 index ad1604131..000000000 --- a/tests/projects/wdk/kmdf/serial/qsfile.c +++ /dev/null @@ -1,180 +0,0 @@ -/*++ - -Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation - -Module Name: - - qsfile.c - -Abstract: - - This module contains the code that is very specific to query/set file - operations in the serial driver. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "qsfile.tmh" -#endif - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGESRP0,SerialQueryInformationFile) -#pragma alloc_text(PAGESRP0,SerialSetInformationFile) -#endif - - -NTSTATUS -SerialQueryInformationFile( - IN WDFDEVICE Device, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routine is used to query the end of file information on - the opened serial port. Any other file information request - is retured with an invalid parameter. - - This routine always returns an end of file of 0. - -Arguments: - - DeviceObject - Pointer to the device object for this device - - Irp - Pointer to the IRP for the current request - -Return Value: - - The function value is the final status of the call - ---*/ - -{ - NTSTATUS Status; - PIO_STACK_LOCATION IrpSp; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialQueryInformationFile(%p, %p)\n", Device, Irp); - - PAGED_CODE(); - - - IrpSp = IoGetCurrentIrpStackLocation(Irp); - Irp->IoStatus.Information = 0L; - Status = STATUS_SUCCESS; - - if (IrpSp->Parameters.QueryFile.FileInformationClass == - FileStandardInformation) { - - if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(FILE_STANDARD_INFORMATION)) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - PFILE_STANDARD_INFORMATION Buf = Irp->AssociatedIrp.SystemBuffer; - - Buf->AllocationSize.QuadPart = 0; - Buf->EndOfFile = Buf->AllocationSize; - Buf->NumberOfLinks = 0; - Buf->DeletePending = FALSE; - Buf->Directory = FALSE; - Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION); - } - - } else if (IrpSp->Parameters.QueryFile.FileInformationClass == - FilePositionInformation) { - - if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(FILE_POSITION_INFORMATION)) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - - ((PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)-> - CurrentByteOffset.QuadPart = 0; - Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION); - } - - } else { - Status = STATUS_INVALID_PARAMETER; - } - - Irp->IoStatus.Status = Status; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; - -} - -NTSTATUS -SerialSetInformationFile( - IN WDFDEVICE Device, - IN PIRP Irp - ) - -/*++ - -Routine Description: - - This routine is used to set the end of file information on - the opened parallel port. Any other file information request - is retured with an invalid parameter. - - This routine always ignores the actual end of file since - the query information code always returns an end of file of 0. - -Arguments: - - DeviceObject - Pointer to the device object for this device - - Irp - Pointer to the IRP for the current request - -Return Value: - -The function value is the final status of the call - ---*/ - -{ - NTSTATUS Status; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialSetInformationFile(%p, %p)\n", Device, Irp); - - Irp->IoStatus.Information = 0L; - if ((IoGetCurrentIrpStackLocation(Irp)-> - Parameters.SetFile.FileInformationClass == - FileEndOfFileInformation) || - (IoGetCurrentIrpStackLocation(Irp)-> - Parameters.SetFile.FileInformationClass == - FileAllocationInformation)) { - - Status = STATUS_SUCCESS; - - } else { - - Status = STATUS_INVALID_PARAMETER; - - } - - Irp->IoStatus.Status = Status; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; - -} - diff --git a/tests/projects/wdk/kmdf/serial/read.c b/tests/projects/wdk/kmdf/serial/read.c deleted file mode 100644 index ab745fdd7..000000000 --- a/tests/projects/wdk/kmdf/serial/read.c +++ /dev/null @@ -1,1748 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - read.c - -Abstract: - - This module contains the code that is very specific to read - operations in the serial driver - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "read.tmh" -#endif - -EVT_WDF_REQUEST_CANCEL SerialCancelCurrentRead; - -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabReadFromIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateReadByIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateInterruptBuffer; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateAndSwitchToUser; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateAndSwitchToNew; - -ULONG -SerialGetCharsFromIntBuffer( - PSERIAL_DEVICE_EXTENSION Extension - ); - - -NTSTATUS -SerialResizeBuffer( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -ULONG -SerialMoveToNewIntBuffer( - PSERIAL_DEVICE_EXTENSION Extension, - PUCHAR NewBuffer - ); - -VOID -SerialEvtIoRead( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t Length - ) - -/*++ - -Routine Description: - - This is the dispatch routine for reading. It validates the parameters - for the read request and if all is ok then it places the request - on the work queue. - -Arguments: - - Queue - Queue handle - Request - Handle to the read request - Lenght - Length of the data buffer associated with the request. - The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get - a zero length request. - -Return Value: - - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension; - NTSTATUS status; - WDFDEVICE hDevice; - WDF_REQUEST_PARAMETERS params; - PREQUEST_CONTEXT reqContext; - size_t bufLen; - - hDevice = WdfIoQueueGetDevice(Queue); - extension = SerialGetDeviceExtension(hDevice); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, - ">SerialEvtIoRead(%p, 0x%I64x)\n", Request, Length); - - if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "MajorFunction = params.Type; - reqContext->Length = (ULONG) Length; - - status = WdfRequestRetrieveOutputBuffer (Request, Length, &reqContext->SystemBuffer, &bufLen); - - if (!NT_SUCCESS (status)) { - - SerialCompleteRequest(Request , status, 0); - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_READ, "Length); - - // - // Well it looks like we actually have to do some - // work. Put the read on the queue so that we can - // process it when our previous reads are done. - // - SerialStartOrQueue(extension, Request, extension->ReadQueue, - &extension->CurrentReadRequest, SerialStartRead); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "SerialStartRead(%p)\n", Extension); - - updateChar.Extension = Extension; - - - do { - - reqContext = SerialGetRequestContext(Extension->CurrentReadRequest); - - // - // Check to see if this is a resize request. If it is - // then go to a routine that specializes in that. - // - - if (reqContext->MajorFunction != IRP_MJ_READ) { - - NTSTATUS localStatus = SerialResizeBuffer(Extension); - UNREFERENCED_PARAMETER(localStatus); - ASSERT(NT_SUCCESS(localStatus)); - - } else { - - Extension->NumberNeededForRead = reqContext->Length; - - // - // Calculate the timeout value needed for the - // request. Note that the values stored in the - // timeout record are in milliseconds. - // - - useTotalTimer = FALSE; - returnWithWhatsPresent = FALSE; - os2ssreturn = FALSE; - crunchDownToOne = FALSE; - useIntervalTimer = FALSE; - - // - // - // CIMEXCIMEX -- this is a lie - // - // Always initialize the timer objects so that the - // completion code can tell when it attempts to - // cancel the timers whether the timers had ever - // been Set. - // - // CIMEXCIMEX -- this is the truth - // - // What we want to do is just make sure the timers are - // cancelled to the best of our ability and move on with - // life. - // - - SerialCancelTimer(Extension->ReadRequestTotalTimer, Extension); - SerialCancelTimer(Extension->ReadRequestIntervalTimer, Extension); - - // - // We get the *current* timeout values to use for timing - // this read. - // - - - timeoutsForIrp = Extension->Timeouts; - - // - // Calculate the interval timeout for the read. - // - - if (timeoutsForIrp.ReadIntervalTimeout && - (timeoutsForIrp.ReadIntervalTimeout != - MAXULONG)) { - - useIntervalTimer = TRUE; - - Extension->IntervalTime.QuadPart = - UInt32x32To64( - timeoutsForIrp.ReadIntervalTimeout, - 10000 - ); - - - if (Extension->IntervalTime.QuadPart >= - Extension->CutOverAmount.QuadPart) { - - Extension->IntervalTimeToUse = - &Extension->LongIntervalAmount; - - } else { - - Extension->IntervalTimeToUse = - &Extension->ShortIntervalAmount; - - } - - } - - if (timeoutsForIrp.ReadIntervalTimeout == MAXULONG) { - - // - // We need to do special return quickly stuff here. - // - // 1) If both constant and multiplier are - // 0 then we return immediately with whatever - // we've got, even if it was zero. - // - // 2) If constant and multiplier are not MAXULONG - // then return immediately if any characters - // are present, but if nothing is there, then - // use the timeouts as specified. - // - // 3) If multiplier is MAXULONG then do as in - // "2" but return when the first character - // arrives. - // - - if (!timeoutsForIrp.ReadTotalTimeoutConstant && - !timeoutsForIrp.ReadTotalTimeoutMultiplier) { - - returnWithWhatsPresent = TRUE; - - } else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG) - && - (timeoutsForIrp.ReadTotalTimeoutMultiplier - != MAXULONG)) { - - useTotalTimer = TRUE; - os2ssreturn = TRUE; - multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier; - constantVal = timeoutsForIrp.ReadTotalTimeoutConstant; - - } else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG) - && - (timeoutsForIrp.ReadTotalTimeoutMultiplier - == MAXULONG)) { - - useTotalTimer = TRUE; - os2ssreturn = TRUE; - crunchDownToOne = TRUE; - multiplierVal = 0; - constantVal = timeoutsForIrp.ReadTotalTimeoutConstant; - - } - - } else { - - // - // If both the multiplier and the constant are - // zero then don't do any total timeout processing. - // - - if (timeoutsForIrp.ReadTotalTimeoutMultiplier || - timeoutsForIrp.ReadTotalTimeoutConstant) { - - // - // We have some timer values to calculate. - // - - useTotalTimer = TRUE; - multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier; - constantVal = timeoutsForIrp.ReadTotalTimeoutConstant; - - } - - } - - if (useTotalTimer) { - - totalTime.QuadPart = ((LONGLONG)(UInt32x32To64( - Extension->NumberNeededForRead, - multiplierVal - ) - + constantVal)) - * -10000; - - } - - - // - // We do this copy in the hope of getting most (if not - // all) of the characters out of the interrupt buffer. - // - // Note that we need to protect this operation with a - // spinlock since we don't want a purge to hose us. - // - - updateChar.CharsCopied = SerialGetCharsFromIntBuffer(Extension); - - // - // See if we have any cause to return immediately. - // - - if (returnWithWhatsPresent || (!Extension->NumberNeededForRead) || - (os2ssreturn && - reqContext->Information)) { - - // - // We got all we needed for this read. - // Update the number of characters in the - // interrupt read buffer. - // - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialUpdateInterruptBuffer, - &updateChar - ); - - reqContext->Status = STATUS_SUCCESS; - - } else { - - // - // The request might go under control of the isr. It - // won't hurt to initialize the reference count - // right now. - // - - SERIAL_INIT_REFERENCE(reqContext); - - // - // If we are supposed to crunch the read down to - // one character, then update the read length - // in the request and truncate the number needed for - // read down to one. Note that if we are doing - // this crunching, then the information must be - // zero (or we would have completed above) and - // the number needed for the read must still be - // equal to the read length. - // - - if (crunchDownToOne) { - - ASSERT( - (!reqContext->Information) - && - (Extension->NumberNeededForRead == reqContext->Length) - ); - - Extension->NumberNeededForRead = 1; - reqContext->Length = 1; - - } - - // - // We still need to get more characters for this read. - // synchronize with the isr so that we can update the - // number of characters and if necessary it will have the - // isr switch to copying into the users buffer. - // - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialUpdateAndSwitchToUser, - &updateChar - ); - - if (!updateChar.Completed) { - - SerialSetCancelRoutine(Extension->CurrentReadRequest, - SerialCancelCurrentRead); - - // - // The request still isn't complete. The - // completion routines will end up reinvoking - // this routine. So we simply leave. - // - // First thought we should start off the total - // timer for the read and increment the reference - // count that the total timer has on the current - // request. Note that this is safe, because even if - // the io has been satisfied by the isr it can't - // complete yet because we still own the cancel - // spinlock. - // - - if (useTotalTimer) { - BOOLEAN result; - - result = SerialSetTimer( - Extension->ReadRequestTotalTimer, - totalTime - ); - - if(result == FALSE) { - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_TOTAL_TIMER - ); - } - - } - - if (useIntervalTimer) { - - BOOLEAN result; - - KeQuerySystemTime( - &Extension->LastReadTime - - ); - result = SerialSetTimer( - Extension->ReadRequestIntervalTimer, - *Extension->IntervalTimeToUse - ); - - if(result == FALSE) { - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_INT_TIMER - ); - } - - } - - break; - - } else { - - reqContext->Status = STATUS_SUCCESS; - } - - } - - } - - // - // Well the operation is complete. - // - - SerialGetNextRequest(&Extension->CurrentReadRequest, - Extension->ReadQueue, - &newRequest, TRUE, Extension); - - } while (newRequest); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "SerialCompleteRead(%p)\n", - extension); - - // - // We set this to indicate to the interval timer - // that the read has completed. - // - // Recall that the interval timer dpc can be lurking in some - // DPC queue. - // - - extension->CountOnLastRead = SERIAL_COMPLETE_READ_COMPLETE; - - SerialTryToCompleteCurrent( - extension, - NULL, - STATUS_SUCCESS, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_ISR - ); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "CountOnLastRead = SERIAL_COMPLETE_READ_CANCEL; - - SerialTryToCompleteCurrent( - extension, - SerialGrabReadFromIsr, - STATUS_CANCELLED, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_CANCEL - ); - -} - - -BOOLEAN -SerialGrabReadFromIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to grab (if possible) the request from the - isr. If it finds that the isr still owns the request it grabs - the ipr away (updating the number of characters copied into the - users buffer). If it grabs it away it also decrements the - reference count on the request since it no longer belongs to the - isr (and the dpc that would complete it). - - NOTE: This routine assumes that if the current buffer that the - ISR is copying characters into is the interrupt buffer then - the dpc has already been queued. - - NOTE: This routine is being called from WdfInterruptSynchronize. - - NOTE: This routine assumes that it is called with the cancel spin - lock held. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - Always false. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension = Context; - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(extension->CurrentReadRequest); - - if (extension->ReadBufferBase != - extension->InterruptReadBuffer) { - - // - // We need to set the information to the number of characters - // that the read wanted minus the number of characters that - // didn't get read into the interrupt buffer. - // - - reqContext->Information = reqContext->Length - - ((extension->LastCharSlot - extension->CurrentCharSlot) + 1); - - // - // Switch back to the interrupt buffer. - // - - extension->ReadBufferBase = extension->InterruptReadBuffer; - extension->CurrentCharSlot = extension->InterruptReadBuffer; - extension->FirstReadableChar = extension->InterruptReadBuffer; - extension->LastCharSlot = extension->InterruptReadBuffer + - (extension->BufferSize - 1); - extension->CharsInInterruptBuffer = 0; - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - } - - return FALSE; - -} - -VOID -SerialReadTimeout( - IN WDFTIMER Timer - ) - -/*++ - -Routine Description: - - This routine is used to complete a read because its total - timer has expired. - -Arguments: - - -Return Value: - - None. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension = NULL; - - extension = SerialGetDeviceExtension(WdfTimerGetParentObject(Timer)); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, ">SerialReadTimeout(%p)\n", - extension); - - // - // We set this to indicate to the interval timer - // that the read has completed due to total timeout. - // - // Recall that the interval timer dpc can be lurking in some - // DPC queue. - // - - extension->CountOnLastRead = SERIAL_COMPLETE_READ_TOTAL; - - SerialTryToCompleteCurrent( - extension, - SerialGrabReadFromIsr, - STATUS_TIMEOUT, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_TOTAL_TIMER - ); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "CountOnLastRead = extension->ReadByIsr; - extension->ReadByIsr = 0; - - return FALSE; - -} - - -VOID -SerialIntervalReadTimeout( - IN WDFTIMER Timer - ) - -/*++ - -Routine Description: - - This routine is used timeout the request if the time between - characters exceed the interval time. A global is kept in - the device extension that records the count of characters read - the last the last time this routine was invoked (This dpc - will resubmit the timer if the count has changed). If the - count has not changed then this routine will attempt to complete - the request. Note the special case of the last count being zero. - The timer isn't really in effect until the first character is - read. - -Arguments: - - -Return Value: - - None. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION extension = NULL; - - extension = SerialGetDeviceExtension(WdfTimerGetParentObject(Timer)); - - - //SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, ">SerialIntervalReadTimeout(%p)\n", - // extension); - - if (extension->CountOnLastRead == SERIAL_COMPLETE_READ_TOTAL) { - - // - // This value is only set by the total - // timer to indicate that it has fired. - // If so, then we should simply try to complete. - // - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, "in SERIAL_COMPLETE_READ_TOTAL\n"); - - SerialTryToCompleteCurrent( - extension, - SerialGrabReadFromIsr, - STATUS_TIMEOUT, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_INT_TIMER - ); - - } else if (extension->CountOnLastRead == SERIAL_COMPLETE_READ_COMPLETE) { - - // - // This value is only set by the regular - // completion routine. - // - // If so, then we should simply try to complete. - // - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, "in SERIAL_COMPLETE_READ_COMPLETE\n"); - - SerialTryToCompleteCurrent( - extension, - SerialGrabReadFromIsr, - STATUS_SUCCESS, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_INT_TIMER - ); - - } else if (extension->CountOnLastRead == SERIAL_COMPLETE_READ_CANCEL) { - - // - // This value is only set by the cancel - // read routine. - // - // If so, then we should simply try to complete. - // - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, "in SERIAL_COMPLETE_READ_CANCEL\n"); - - SerialTryToCompleteCurrent( - extension, - SerialGrabReadFromIsr, - STATUS_CANCELLED, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_INT_TIMER - ); - - } else if (extension->CountOnLastRead || extension->ReadByIsr) { - - // - // Something has happened since we last came here. We - // check to see if the ISR has read in any more characters. - // If it did then we should update the isr's read count - // and resubmit the timer. - // - - if (extension->ReadByIsr) { - - WdfInterruptSynchronize( - extension->WdfInterrupt, - SerialUpdateReadByIsr, - extension - ); - - // - // Save off the "last" time something was read. - // As we come back to this routine we will compare - // the current time to the "last" time. If the - // difference is ever larger then the interval - // requested by the user, then time out the request. - // - - KeQuerySystemTime( - &extension->LastReadTime - ); - - SerialSetTimer( - extension->ReadRequestIntervalTimer, - *extension->IntervalTimeToUse - ); - - } else { - - // - // Take the difference between the current time - // and the last time we had characters and - // see if it is greater then the interval time. - // if it is, then time out the request. Otherwise - // go away again for a while. - // - - // - // No characters read in the interval time. Kill - // this read. - // - - LARGE_INTEGER currentTime; - - KeQuerySystemTime( - ¤tTime - ); - - if ((currentTime.QuadPart - extension->LastReadTime.QuadPart) >= - extension->IntervalTime.QuadPart) { - - SerialTryToCompleteCurrent( - extension, - SerialGrabReadFromIsr, - STATUS_TIMEOUT, - &extension->CurrentReadRequest, - extension->ReadQueue, - extension->ReadRequestIntervalTimer, - extension->ReadRequestTotalTimer, - SerialStartRead, - SerialGetNextRequest, - SERIAL_REF_INT_TIMER - ); - - } else { - - SerialSetTimer( - extension->ReadRequestIntervalTimer, - *extension->IntervalTimeToUse - ); - - } - - - } - - } else { - - // - // Timer doesn't really start until the first character. - // So we should simply resubmit ourselves. - // - - SerialSetTimer( - extension->ReadRequestIntervalTimer, - *extension->IntervalTimeToUse - ); - - } - - - //SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "CurrentReadRequest); - - // - // The minimum of the number of characters we need and - // the number of characters available - // - - numberOfCharsToGet = Extension->CharsInInterruptBuffer; - - if (numberOfCharsToGet > Extension->NumberNeededForRead) { - - numberOfCharsToGet = Extension->NumberNeededForRead; - - } - - if (numberOfCharsToGet) { - - // - // This will hold the number of characters between the - // first available character and the end of the buffer. - // Note that the buffer could wrap around but for the - // purposes of the first copy we don't care about that. - // - - firstTryNumberToGet = (ULONG)(Extension->LastCharSlot - - Extension->FirstReadableChar) + 1; - - if (firstTryNumberToGet > numberOfCharsToGet) { - - // - // The characters don't wrap. Actually they may wrap but - // we don't care for the purposes of this read since the - // characters we need are available before the wrap. - // - - RtlMoveMemory( - ((PUCHAR)(reqContext->SystemBuffer)) - + (reqContext->Length - Extension->NumberNeededForRead), - Extension->FirstReadableChar, - numberOfCharsToGet - ); - - Extension->NumberNeededForRead -= numberOfCharsToGet; - - // - // We now will move the pointer to the first character after - // what we just copied into the users buffer. - // - // We need to check if the stream of readable characters - // is wrapping around to the beginning of the buffer. - // - // Note that we may have just taken the last characters - // at the end of the buffer. - // - - if ((Extension->FirstReadableChar + (numberOfCharsToGet - 1)) == - Extension->LastCharSlot) { - - Extension->FirstReadableChar = Extension->InterruptReadBuffer; - - } else { - - Extension->FirstReadableChar += numberOfCharsToGet; - - } - - } else { - - // - // The characters do wrap. Get up until the end of the buffer. - // - - RtlMoveMemory( - ((PUCHAR)(reqContext->SystemBuffer)) - + (reqContext->Length - Extension->NumberNeededForRead), - Extension->FirstReadableChar, - firstTryNumberToGet - ); - - Extension->NumberNeededForRead -= firstTryNumberToGet; - - // - // Now get the rest of the characters from the beginning of the - // buffer. - // - - RtlMoveMemory( - ((PUCHAR)(reqContext->SystemBuffer)) - + (reqContext->Length - Extension->NumberNeededForRead), - Extension->InterruptReadBuffer, - numberOfCharsToGet - firstTryNumberToGet - ); - - Extension->FirstReadableChar = Extension->InterruptReadBuffer + - (numberOfCharsToGet - - firstTryNumberToGet); - - Extension->NumberNeededForRead -= (numberOfCharsToGet - - firstTryNumberToGet); - - } - - } - - reqContext->Information += numberOfCharsToGet; - return numberOfCharsToGet; - -} - - -BOOLEAN -SerialUpdateInterruptBuffer( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to update the number of characters that - remain in the interrupt buffer. We need to use this routine - since the count could be updated during the update by execution - of the ISR. - - NOTE: This is called by WdfInterruptSynchronize. - -Arguments: - - Context - Points to a structure that contains a pointer to the - device extension and count of the number of characters - that we previously copied into the users buffer. The - structure actually has a third field that we don't - use in this routine. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_UPDATE_CHAR update = Context; - PSERIAL_DEVICE_EXTENSION extension = update->Extension; - - UNREFERENCED_PARAMETER(Interrupt); - - ASSERT(extension->CharsInInterruptBuffer >= update->CharsCopied); - extension->CharsInInterruptBuffer -= update->CharsCopied; - - // - // Deal with flow control if necessary. - // - - SerialHandleReducedIntBuffer(extension); - - - return FALSE; - -} - - -BOOLEAN -SerialUpdateAndSwitchToUser( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine gets the (hopefully) few characters that - remain in the interrupt buffer after the first time we tried - to get them out. If we still don't have enough characters - to satisfy the read it will then we set things up so that the - ISR uses the user buffer copy into. - - This routine is also used to update a count that is maintained - by the ISR to keep track of the number of characters in its buffer. - - NOTE: This is called by WdfInterruptSynchronize. - -Arguments: - - Context - Points to a structure that contains a pointer to the - device extension, a count of the number of characters - that we previously copied into the users buffer, and - a boolean that we will set that defines whether we - switched the ISR to copy into the users buffer. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_UPDATE_CHAR updateChar = Context; - PSERIAL_DEVICE_EXTENSION extension = updateChar->Extension; - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(extension->CurrentReadRequest); - - SerialUpdateInterruptBuffer(extension->WdfInterrupt, Context); - - // - // There are more characters to get to satisfy this read. - // Copy any characters that have arrived since we got - // the last batch. - // - - updateChar->CharsCopied = SerialGetCharsFromIntBuffer(extension); - - SerialUpdateInterruptBuffer(extension->WdfInterrupt, Context); - - // - // No more new characters will be "received" until we exit - // this routine. We again check to make sure that we - // haven't satisfied this read, and if we haven't we set things - // up so that the ISR copies into the user buffer. - // - - if (extension->NumberNeededForRead) { - - // - // We shouldn't be switching unless there are no - // characters left. - // - - ASSERT(!extension->CharsInInterruptBuffer); - - // - // We use the following to values to do inteval timing. - // - // CountOnLastRead is mostly used to simply prevent - // the interval timer from timing out before any characters - // are read. (Interval timing should only be effective - // after the first character is read.) - // - // After the first time the interval timer fires and - // characters have be read we will simply update with - // the value of ReadByIsr and then set ReadByIsr to zero. - // (We do that in a synchronization routine. - // - // If the interval timer dpc routine ever encounters - // ReadByIsr == 0 when CountOnLastRead is non-zero it - // will timeout the read. - // - // (Note that we have a special case of CountOnLastRead - // < 0. This is done by the read completion routines other - // than the total timeout dpc to indicate that the total - // timeout has expired.) - // - - extension->CountOnLastRead = (LONG)reqContext->Information; - - extension->ReadByIsr = 0; - - // - // By compareing the read buffer base address to the - // the base address of the interrupt buffer the ISR - // can determine whether we are using the interrupt - // buffer or the user buffer. - // - - extension->ReadBufferBase = reqContext->SystemBuffer; - - // - // The current char slot is after the last copied in - // character. We know there is always room since we - // we wouldn't have gotten here if there wasn't. - // - - extension->CurrentCharSlot = extension->ReadBufferBase + - reqContext->Information; - - // - // The last position that a character can go is on the - // last byte of user buffer. While the actual allocated - // buffer space may be bigger, we know that there is at - // least as much as the read length. - // - - extension->LastCharSlot = extension->ReadBufferBase + - (reqContext->Length - 1); -#if 0 // We set the cancel before calling this routine in StartRead - // - // Mark the request as being in a cancelable state. - // - IoSetCancelRoutine( - extension->CurrentReadIrp, - SerialCancelCurrentRead - ); - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_CANCEL - ); -#endif - // - // Increment the reference count twice. - // - // Once for the Isr owning the request and once - // because the cancel routine has a reference - // to it. - // - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - updateChar->Completed = FALSE; - - } else { - - updateChar->Completed = TRUE; - - } - - return FALSE; - -} -// -// We use this structure only to communicate to the synchronization -// routine when we are switching to the resized buffer. -// -typedef struct _SERIAL_RESIZE_PARAMS { - PSERIAL_DEVICE_EXTENSION Extension; - PUCHAR OldBuffer; - PUCHAR NewBuffer; - ULONG NewBufferSize; - ULONG NumberMoved; - } SERIAL_RESIZE_PARAMS,*PSERIAL_RESIZE_PARAMS; - - -NTSTATUS -SerialResizeBuffer( - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - This routine will process the resize buffer request. - If size requested for the RX buffer is smaller than - the current buffer then we will simply return - STATUS_SUCCESS. (We don't want to make buffers smaller. - If we did that then we all of a sudden have "overrun" - problems to deal with as well as flow control to deal - with - very painful.) We ignore the TX buffer size - request since we don't use a TX buffer. - -Arguments: - - Extension - Pointer to the device extension for the port. - -Return Value: - - STATUS_SUCCESS if everything worked out ok. - STATUS_INSUFFICIENT_RESOURCES if we couldn't allocate the - memory for the buffer. - ---*/ - -{ - - PREQUEST_CONTEXT reqContext = SerialGetRequestContext(Extension->CurrentReadRequest); - PSERIAL_QUEUE_SIZE rs = reqContext->SystemBuffer; - - PVOID newBuffer = reqContext->Type3InputBuffer; - - - reqContext->Type3InputBuffer = NULL; - reqContext->Information = 0L; - reqContext->Status = STATUS_SUCCESS; - - if (rs->InSize <= Extension->BufferSize) { - - // - // Nothing to do. We don't make buffers smaller. Just - // agree with the user. We must deallocate the memory - // that was already allocated in the ioctl dispatch routine. - // - - ExFreePool(newBuffer); - - } else { - - SERIAL_RESIZE_PARAMS rp; - - // - // Hmmm, looks like we actually have to go - // through with this. We need to move all the - // data that is in the current buffer into this - // new buffer. We'll do this in two steps. - // - // First we go up to dispatch level and try to - // move as much as we can without stopping the - // ISR from running. We go up to dispatch level - // by acquiring the control lock. We do it at - // dispatch using the control lock so that: - // - // 1) We can't be context switched in the middle - // of the move. Our pointers into the buffer - // could be *VERY* stale by the time we got back. - // - // 2) We use the control lock since we don't want - // some pesky purge request to come along while - // we are trying to move. - // - // After the move, but while we still hold the control - // lock, we synch with the ISR and get those last - // (hopefully) few characters that have come in since - // we started the copy. We switch all of our pointers, - // counters, and such to point to this new buffer. NOTE: - // we need to be careful. If the buffer we were using - // was not the default one created when we initialized - // the device (i.e. it was created via a previous WDFREQUEST of - // this type), we should deallocate it. - // - - rp.Extension = Extension; - rp.OldBuffer = Extension->InterruptReadBuffer; - rp.NewBuffer = newBuffer; - rp.NewBufferSize = rs->InSize; - - rp.NumberMoved = SerialMoveToNewIntBuffer( - Extension, - newBuffer - ); - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialUpdateAndSwitchToNew, - &rp - ); - - // - // Free up the memory that the old buffer consumed. - // - - ExFreePool(rp.OldBuffer); - - } - - return STATUS_SUCCESS; - -} - - -ULONG -SerialMoveToNewIntBuffer( - PSERIAL_DEVICE_EXTENSION Extension, - PUCHAR NewBuffer - ) - -/*++ - -Routine Description: - - This routine is used to copy any characters out of the interrupt - buffer into the "new" buffer. It will be reading values that - are updated with the ISR but this is safe since this value is - only decremented by synchronization routines. This routine will - return the number of characters copied so some other routine - can call a synchronization routine to update what is seen at - interrupt level. - -Arguments: - - Extension - A pointer to the device extension. - NewBuffer - Where the characters are to be move to. - -Return Value: - - The number of characters that were copied into the user - buffer. - ---*/ - -{ - - ULONG numberOfCharsMoved = Extension->CharsInInterruptBuffer; - - - if (numberOfCharsMoved) { - - // - // This holds the number of characters between the first - // readable character and the last character we will read or - // the real physical end of the buffer (not the last readable - // character). - // - ULONG firstTryNumberToGet = (ULONG)(Extension->LastCharSlot - - Extension->FirstReadableChar) + 1; - - if (firstTryNumberToGet >= numberOfCharsMoved) { - - // - // The characters don't wrap. - // - - RtlMoveMemory( - NewBuffer, - Extension->FirstReadableChar, - numberOfCharsMoved - ); - - if ((Extension->FirstReadableChar+(numberOfCharsMoved-1)) == - Extension->LastCharSlot) { - - Extension->FirstReadableChar = Extension->InterruptReadBuffer; - - } else { - - Extension->FirstReadableChar += numberOfCharsMoved; - - } - - } else { - - // - // The characters do wrap. Get up until the end of the buffer. - // - - RtlMoveMemory( - NewBuffer, - Extension->FirstReadableChar, - firstTryNumberToGet - ); - - // - // Now get the rest of the characters from the beginning of the - // buffer. - // - - RtlMoveMemory( - NewBuffer+firstTryNumberToGet, - Extension->InterruptReadBuffer, - numberOfCharsMoved - firstTryNumberToGet - ); - - Extension->FirstReadableChar = Extension->InterruptReadBuffer + - numberOfCharsMoved - firstTryNumberToGet; - - } - - } - - return numberOfCharsMoved; - -} - - -BOOLEAN -SerialUpdateAndSwitchToNew( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine gets the (hopefully) few characters that - remain in the interrupt buffer after the first time we tried - to get them out. - - NOTE: This is called by WdfInterruptSynchronize. - -Arguments: - - Context - Points to a structure that contains a pointer to the - device extension, a pointer to the buffer we are moving - to, and a count of the number of characters - that we previously copied into the new buffer, and the - actual size of the new buffer. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_RESIZE_PARAMS params = Context; - PSERIAL_DEVICE_EXTENSION extension = params->Extension; - ULONG tempCharsInInterruptBuffer = extension->CharsInInterruptBuffer; - - UNREFERENCED_PARAMETER(Interrupt); - - ASSERT(extension->CharsInInterruptBuffer >= params->NumberMoved); - - // - // We temporarily reduce the chars in interrupt buffer to - // "fool" the move routine. We will restore it after the - // move. - // - - extension->CharsInInterruptBuffer -= params->NumberMoved; - - if (extension->CharsInInterruptBuffer) { - - SerialMoveToNewIntBuffer( - extension, - params->NewBuffer + params->NumberMoved - ); - - } - - extension->CharsInInterruptBuffer = tempCharsInInterruptBuffer; - - - extension->LastCharSlot = params->NewBuffer + (params->NewBufferSize - 1); - extension->FirstReadableChar = params->NewBuffer; - extension->ReadBufferBase = params->NewBuffer; - extension->InterruptReadBuffer = params->NewBuffer; - extension->BufferSize = params->NewBufferSize; - - // - // We *KNOW* that the new interrupt buffer is larger than the - // old buffer. We don't need to worry about it being full. - // - - extension->CurrentCharSlot = extension->InterruptReadBuffer + - extension->CharsInInterruptBuffer; - - // - // We set up the default xon/xoff limits. - // - - extension->HandFlow.XoffLimit = extension->BufferSize >> 3; - extension->HandFlow.XonLimit = extension->BufferSize >> 1; - - extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit; - extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit; - - extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+ - (extension->BufferSize>>4)); - - // - // Since we (essentially) reduced the percentage of the interrupt - // buffer being full, we need to handle any flow control. - // - - SerialHandleReducedIntBuffer(extension); - - return FALSE; - -} - - diff --git a/tests/projects/wdk/kmdf/serial/registry.c b/tests/projects/wdk/kmdf/serial/registry.c deleted file mode 100644 index 5ab25955a..000000000 --- a/tests/projects/wdk/kmdf/serial/registry.c +++ /dev/null @@ -1,443 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - registry.c - -Abstract: - - This module contains the code that is used to get values from the - registry and to manipulate entries in the registry. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "registry.tmh" -#endif - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(INIT,SerialGetConfigDefaults) -#pragma alloc_text(PAGESRP0,SerialGetRegistryKeyValue) -#pragma alloc_text(PAGESRP0,SerialPutRegistryKeyValue) -#pragma alloc_text(PAGESRP0,SerialGetFdoRegistryKeyValue) -#endif // ALLOC_PRAGMA - - -#define PARAMATER_NAME_LEN 80 - - -NTSTATUS -SerialGetConfigDefaults( - IN PSERIAL_FIRMWARE_DATA DriverDefaultsPtr, - IN WDFDRIVER Driver - ) - -/*++ - -Routine Description: - - This routine reads the default configuration data from the - registry for the serial driver. - - It also builds fields in the registry for several configuration - options if they don't exist. - -Arguments: - - DriverDefaultsPtr - Pointer to a structure that will contain - the default configuration values. - - RegistryPath - points to the entry for this driver in the - current control set of the registry. - -Return Value: - - STATUS_SUCCESS if we got the defaults, otherwise we failed. - The only way to fail this call is if the STATUS_INSUFFICIENT_RESOURCES. - ---*/ - -{ - - NTSTATUS status = STATUS_SUCCESS; // return value - WDFKEY hKey; - DECLARE_UNICODE_STRING_SIZE(valueName,PARAMATER_NAME_LEN); - - status = WdfDriverOpenParametersRegistryKey(Driver, - STANDARD_RIGHTS_ALL, - WDF_NO_OBJECT_ATTRIBUTES, - &hKey); - if (!NT_SUCCESS (status)) { - return status; - } - - status = RtlUnicodeStringPrintf(&valueName,L"BreakOnEntry"); - if (!NT_SUCCESS (status)) { - goto End; - - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->ShouldBreakOnEntry); - - if (!NT_SUCCESS (status)) { - DriverDefaultsPtr->ShouldBreakOnEntry = 0; - } - - status = RtlUnicodeStringPrintf(&valueName,L"DebugLevel"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->DebugLevel); - - if (!NT_SUCCESS (status)) { - DriverDefaultsPtr->DebugLevel = 0; - } - - - status = RtlUnicodeStringPrintf(&valueName,L"ForceFifoEnable"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->ForceFifoEnableDefault); - - if (!NT_SUCCESS (status)) { - - // - // If it isn't then write out values so that it could - // be adjusted later. - // - DriverDefaultsPtr->ForceFifoEnableDefault = SERIAL_FORCE_FIFO_DEFAULT; - - status = WdfRegistryAssignULong(hKey, - &valueName, - DriverDefaultsPtr->ForceFifoEnableDefault - ); - if (!NT_SUCCESS (status)) { - goto End; - } - - } - - status = RtlUnicodeStringPrintf(&valueName,L"RxFIFO"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->RxFIFODefault); - - if (!NT_SUCCESS (status)) { - - DriverDefaultsPtr->RxFIFODefault = SERIAL_RX_FIFO_DEFAULT; - - status = WdfRegistryAssignULong(hKey, - &valueName, - DriverDefaultsPtr->RxFIFODefault - ); - if (!NT_SUCCESS (status)) { - goto End; - } - - } - - status = RtlUnicodeStringPrintf(&valueName,L"TxFIFO"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->TxFIFODefault); - - if (!NT_SUCCESS (status)) { - - DriverDefaultsPtr->TxFIFODefault = SERIAL_TX_FIFO_DEFAULT; - - status = WdfRegistryAssignULong(hKey, - &valueName, - DriverDefaultsPtr->TxFIFODefault - ); - if (!NT_SUCCESS (status)) { - goto End; - } - - } - - status = RtlUnicodeStringPrintf(&valueName,L"PermitShare"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->PermitShareDefault); - - if (!NT_SUCCESS (status)) { - - DriverDefaultsPtr->PermitShareDefault = SERIAL_PERMIT_SHARE_DEFAULT; - - status = WdfRegistryAssignULong(hKey, - &valueName, - DriverDefaultsPtr->PermitShareDefault - ); - if (!NT_SUCCESS (status)) { - goto End; - } - - } - - status = RtlUnicodeStringPrintf(&valueName,L"LogFifo"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->LogFifoDefault); - - if (!NT_SUCCESS (status)) { - - DriverDefaultsPtr->LogFifoDefault = SERIAL_LOG_FIFO_DEFAULT; - - status = WdfRegistryAssignULong(hKey, - &valueName, - DriverDefaultsPtr->LogFifoDefault - ); - if (!NT_SUCCESS (status)) { - goto End; - } - - DriverDefaultsPtr->LogFifoDefault = 1; - } - - - status = RtlUnicodeStringPrintf(&valueName,L"UartRemovalDetect"); - if (!NT_SUCCESS (status)) { - goto End; - } - - status = WdfRegistryQueryULong (hKey, - &valueName, - &DriverDefaultsPtr->UartRemovalDetect); - - if (!NT_SUCCESS (status)) { - DriverDefaultsPtr->UartRemovalDetect = 0; - } - - -End: - WdfRegistryClose(hKey); - return (status); -} - -BOOLEAN -SerialGetRegistryKeyValue( - IN WDFDEVICE WdfDevice, - _In_ PCWSTR Name, - OUT PULONG Value - ) -/*++ - -Routine Description: - - Can be used to read any REG_DWORD registry value stored - under Device Parameter. - -Arguments: - - FdoData - pointer to the device extension - Name - Name of the registry value - Value - - - -Return Value: - - TRUE if successful - FALSE if not present/error in reading registry - ---*/ -{ - WDFKEY hKey = NULL; - NTSTATUS status; - BOOLEAN retValue = FALSE; - UNICODE_STRING valueName; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, ">SerialGetRegistryKeyValue(XXX)\n"); - - *Value = 0; - - status = WdfDeviceOpenRegistryKey(WdfDevice, - PLUGPLAY_REGKEY_DEVICE, - STANDARD_RIGHTS_ALL, - WDF_NO_OBJECT_ATTRIBUTES, - &hKey); - - if (NT_SUCCESS (status)) { - - RtlInitUnicodeString(&valueName,Name); - - status = WdfRegistryQueryULong (hKey, - &valueName, - Value); - - if (NT_SUCCESS (status)) { - retValue = TRUE; - } - - WdfRegistryClose(hKey); - } - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "<--SerialGetRegistryKeyValue %ws %d \n", - Name, *Value); - - return retValue; -} - -#define PARAMATER_NAME_LEN 80 - -BOOLEAN -SerialPutRegistryKeyValue( - IN WDFDEVICE WdfDevice, - _In_ PCWSTR Name, - IN ULONG Value - ) -/*++ - -Routine Description: - - Can be used to write any REG_DWORD registry value stored - under Device Parameter. - -Arguments: - - -Return Value: - - TRUE - if write is successful - FALSE - otherwise - ---*/ -{ - WDFKEY hKey = NULL; - NTSTATUS status; - BOOLEAN retValue = FALSE; - UNICODE_STRING valueName; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "Entered PciDrvWriteRegistryValue\n"); - - // - // write the value out to the registry - // - status = WdfDeviceOpenRegistryKey(WdfDevice, - PLUGPLAY_REGKEY_DEVICE, - STANDARD_RIGHTS_ALL, - WDF_NO_OBJECT_ATTRIBUTES, - &hKey); - - if (NT_SUCCESS (status)) { - - RtlInitUnicodeString(&valueName,Name); - - status = WdfRegistryAssignULong (hKey, - &valueName, - Value - ); - - if (NT_SUCCESS (status)) { - retValue = TRUE; - } - - WdfRegistryClose(hKey); - } - - return retValue; - -} - -BOOLEAN -SerialGetFdoRegistryKeyValue( - IN PWDFDEVICE_INIT DeviceInit, - _In_ PCWSTR Name, - OUT PULONG Value - ) -/*++ - -Routine Description: - - Can be used to read any REG_DWORD registry value stored - under Device Parameter. - -Arguments: - - FdoData - pointer to the device extension - Name - Name of the registry value - Value - - - -Return Value: - - TRUE if successful - FALSE if not present/error in reading registry - ---*/ -{ - WDFKEY hKey = NULL; - NTSTATUS status; - BOOLEAN retValue = FALSE; - UNICODE_STRING valueName; - - PAGED_CODE(); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, - "-->SerialGetFdoRegistryKeyValue\n"); - - *Value = 0; - - status = WdfFdoInitOpenRegistryKey(DeviceInit, - PLUGPLAY_REGKEY_DEVICE, - STANDARD_RIGHTS_ALL, - WDF_NO_OBJECT_ATTRIBUTES, - &hKey); - - if (NT_SUCCESS (status)) { - - RtlInitUnicodeString(&valueName,Name); - - status = WdfRegistryQueryULong (hKey, &valueName, Value); - - if (NT_SUCCESS (status)) { - retValue = TRUE; - } - - WdfRegistryClose(hKey); - } - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, - "<--SerialGetFdoRegistryKeyValue %ws %d \n", - Name, *Value); - - return retValue; -} - - diff --git a/tests/projects/wdk/kmdf/serial/serial.h b/tests/projects/wdk/kmdf/serial/serial.h deleted file mode 100644 index fcbf9748f..000000000 --- a/tests/projects/wdk/kmdf/serial/serial.h +++ /dev/null @@ -1,1757 +0,0 @@ -/*++ - -Copyright (c) 1990, 1991, 1992, 1993 - 1997 Microsoft Corporation - -Module Name : - - serial.h - -Abstract: - - Type definitions and data for the serial port driver - ---*/ - -#define POOL_TAG 'XMOC' - - -// -// Some default driver values. We will check the registry for -// them first. -// -#define SERIAL_UNINITIALIZED_DEFAULT 1234567 -#define SERIAL_FORCE_FIFO_DEFAULT 1 -#define SERIAL_RX_FIFO_DEFAULT 8 -#define SERIAL_TX_FIFO_DEFAULT 14 -#define SERIAL_PERMIT_SHARE_DEFAULT 0 -#define SERIAL_LOG_FIFO_DEFAULT 0 - - -// -// This define gives the default Object directory -// that we should use to insert the symbolic links -// between the NT device name and namespace used by -// that object directory. -#define DEFAULT_DIRECTORY L"DosDevices" - -// -// For the above directory, the serial port will -// use the following name as the suffix of the serial -// ports for that directory. It will also append -// a number onto the end of the name. That number -// will start at 1. -#define DEFAULT_SERIAL_NAME L"COM" -// -// -// This define gives the default NT name for -// for serial ports detected by the firmware. -// This name will be appended to Device prefix -// with a number following it. The number is -// incremented each time encounter a serial -// port detected by the firmware. Note that -// on a system with multiple busses, this means -// that the first port on a bus is not necessarily -// \Device\Serial0. -// -#define DEFAULT_NT_SUFFIX L"Serial" -#define _DRIVER_NAME_ "Serial.sys" - -#define DEVICE_OBJECT_NAME_LENGTH 128 -#define SYMBOLIC_NAME_LENGTH 128 -#define SERIAL_DEVICE_MAP L"SERIALCOMM" - -// -// GUID_DEVINTERFACE_COMPORT is not defined in the Win2K -// headers, so we will need this definition to avoid compilation -// errors. -// -#define GUID_DEVINTERFACE_COMPORT GUID_CLASS_COMPORT - -// -// This value - which could be redefined at compile -// time, define the stride between registers -// -#if !defined(SERIAL_REGISTER_STRIDE) -#define SERIAL_REGISTER_STRIDE 1 -#endif - -// -// Offsets from the base register address of the -// various registers for the 8250 family of UARTS. -// -#define RECEIVE_BUFFER_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE)) -#define TRANSMIT_HOLDING_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE)) -#define INTERRUPT_ENABLE_REGISTER ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE)) -#define INTERRUPT_IDENT_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE)) -#define FIFO_CONTROL_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE)) -#define LINE_CONTROL_REGISTER ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE)) -#define MODEM_CONTROL_REGISTER ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE)) -#define LINE_STATUS_REGISTER ((ULONG)((0x05)*SERIAL_REGISTER_STRIDE)) -#define MODEM_STATUS_REGISTER ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE)) -#define DIVISOR_LATCH_LSB ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE)) -#define DIVISOR_LATCH_MSB ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE)) -#define SERIAL_REGISTER_SPAN ((ULONG)(7*SERIAL_REGISTER_STRIDE)) - -// -// If we have an interrupt status register this is its assumed -// length. -// -#define SERIAL_STATUS_LENGTH ((ULONG)(1*SERIAL_REGISTER_STRIDE)) - -// -// Bitmask definitions for accessing the 8250 device registers. -// - -// -// These bits define the number of data bits trasmitted in -// the Serial Data Unit (SDU - Start,data, parity, and stop bits) -// -#define SERIAL_DATA_LENGTH_5 0x00 -#define SERIAL_DATA_LENGTH_6 0x01 -#define SERIAL_DATA_LENGTH_7 0x02 -#define SERIAL_DATA_LENGTH_8 0x03 - - -// -// These masks define the interrupts that can be enabled or disabled. -// -// -// This interrupt is used to notify that there is new incomming -// data available. The SERIAL_RDA interrupt is enabled by this bit. -// -#define SERIAL_IER_RDA 0x01 - -// -// This interrupt is used to notify that there is space available -// in the transmitter for another character. The SERIAL_THR -// interrupt is enabled by this bit. -// -#define SERIAL_IER_THR 0x02 - -// -// This interrupt is used to notify that some sort of error occured -// with the incomming data. The SERIAL_RLS interrupt is enabled by -// this bit. -#define SERIAL_IER_RLS 0x04 - -// -// This interrupt is used to notify that some sort of change has -// taken place in the modem control line. The SERIAL_MS interrupt is -// enabled by this bit. -// -#define SERIAL_IER_MS 0x08 - - -// -// These masks define the values of the interrupt identification -// register. The low bit must be clear in the interrupt identification -// register for any of these interrupts to be valid. The interrupts -// are defined in priority order, with the highest value being most -// important. See above for a description of what each interrupt -// implies. -// -#define SERIAL_IIR_RLS 0x06 -#define SERIAL_IIR_RDA 0x04 -#define SERIAL_IIR_CTI 0x0c -#define SERIAL_IIR_THR 0x02 -#define SERIAL_IIR_MS 0x00 - -// -// This bit mask get the value of the high two bits of the -// interrupt id register. If this is a 16550 class chip -// these bits will be a one if the fifo's are enbled, otherwise -// they will always be zero. -// -#define SERIAL_IIR_FIFOS_ENABLED 0xc0 - -// -// If the low bit is logic one in the interrupt identification register -// this implies that *NO* interrupts are pending on the device. -// -#define SERIAL_IIR_NO_INTERRUPT_PENDING 0x01 - - -// -// Use these bits to detect removal of serial card for Stratus implementation -// -#define SERIAL_IIR_MUST_BE_ZERO 0x30 - - -// -// These masks define access to the fifo control register. -// - -// -// Enabling this bit in the fifo control register will turn -// on the fifos. If the fifos are enabled then the high two -// bits of the interrupt id register will be set to one. Note -// that this only occurs on a 16550 class chip. If the high -// two bits in the interrupt id register are not one then -// we know we have a lower model chip. -// -// -#define SERIAL_FCR_ENABLE ((UCHAR)0x01) -#define SERIAL_FCR_RCVR_RESET ((UCHAR)0x02) -#define SERIAL_FCR_TXMT_RESET ((UCHAR)0x04) - -// -// This set of values define the high water marks (when the -// interrupts trip) for the receive fifo. -// -#define SERIAL_1_BYTE_HIGH_WATER ((UCHAR)0x00) -#define SERIAL_4_BYTE_HIGH_WATER ((UCHAR)0x40) -#define SERIAL_8_BYTE_HIGH_WATER ((UCHAR)0x80) -#define SERIAL_14_BYTE_HIGH_WATER ((UCHAR)0xc0) - -// -// These masks define access to the line control register. -// - -// -// This defines the bit used to control the definition of the "first" -// two registers for the 8250. These registers are the input/output -// register and the interrupt enable register. When the DLAB bit is -// enabled these registers become the least significant and most -// significant bytes of the divisor value. -// -#define SERIAL_LCR_DLAB 0x80 - -// -// This defines the bit used to control whether the device is sending -// a break. When this bit is set the device is sending a space (logic 0). -// -// Most protocols will assume that this is a hangup. -// -#define SERIAL_LCR_BREAK 0x40 - -// -// These defines are used to set the line control register. -// -#define SERIAL_5_DATA ((UCHAR)0x00) -#define SERIAL_6_DATA ((UCHAR)0x01) -#define SERIAL_7_DATA ((UCHAR)0x02) -#define SERIAL_8_DATA ((UCHAR)0x03) -#define SERIAL_DATA_MASK ((UCHAR)0x03) - -#define SERIAL_1_STOP ((UCHAR)0x00) -#define SERIAL_1_5_STOP ((UCHAR)0x04) // Only valid for 5 data bits -#define SERIAL_2_STOP ((UCHAR)0x04) // Not valid for 5 data bits -#define SERIAL_STOP_MASK ((UCHAR)0x04) - -#define SERIAL_NONE_PARITY ((UCHAR)0x00) -#define SERIAL_ODD_PARITY ((UCHAR)0x08) -#define SERIAL_EVEN_PARITY ((UCHAR)0x18) -#define SERIAL_MARK_PARITY ((UCHAR)0x28) -#define SERIAL_SPACE_PARITY ((UCHAR)0x38) -#define SERIAL_PARITY_MASK ((UCHAR)0x38) - -// -// These masks define access the modem control register. -// - -// -// This bit controls the data terminal ready (DTR) line. When -// this bit is set the line goes to logic 0 (which is then inverted -// by normal hardware). This is normally used to indicate that -// the device is available to be used. Some odd hardware -// protocols (like the kernel debugger) use this for handshaking -// purposes. -// -#define SERIAL_MCR_DTR 0x01 - -// -// This bit controls the ready to send (RTS) line. When this bit -// is set the line goes to logic 0 (which is then inverted by the normal -// hardware). This is used for hardware handshaking. It indicates that -// the hardware is ready to send data and it is waiting for the -// receiving end to set clear to send (CTS). -// -#define SERIAL_MCR_RTS 0x02 - -// -// This bit is used for general purpose output. -// -#define SERIAL_MCR_OUT1 0x04 - -// -// This bit is used for general purpose output. -// -#define SERIAL_MCR_OUT2 0x08 - -// -// This bit controls the loopback testing mode of the device. Basically -// the outputs are connected to the inputs (and vice versa). -// -#define SERIAL_MCR_LOOP 0x10 - -// -// This bit enables auto flow control on a TI TL16C550C/TL16C550CI -// - -#define SERIAL_MCR_TL16C550CAFE 0x20 - - -// -// These masks define access to the line status register. The line -// status register contains information about the status of data -// transfer. The first five bits deal with receive data and the -// last two bits deal with transmission. An interrupt is generated -// whenever bits 1 through 4 in this register are set. -// - -// -// This bit is the data ready indicator. It is set to indicate that -// a complete character has been received. This bit is cleared whenever -// the receive buffer register has been read. -// -#define SERIAL_LSR_DR 0x01 - -// -// This is the overrun indicator. It is set to indicate that the receive -// buffer register was not read befor a new character was transferred -// into the buffer. This bit is cleared when this register is read. -// -#define SERIAL_LSR_OE 0x02 - -// -// This is the parity error indicator. It is set whenever the hardware -// detects that the incoming serial data unit does not have the correct -// parity as defined by the parity select in the line control register. -// This bit is cleared by reading this register. -// -#define SERIAL_LSR_PE 0x04 - -// -// This is the framing error indicator. It is set whenever the hardware -// detects that the incoming serial data unit does not have a valid -// stop bit. This bit is cleared by reading this register. -// -#define SERIAL_LSR_FE 0x08 - -// -// This is the break interrupt indicator. It is set whenever the data -// line is held to logic 0 for more than the amount of time it takes -// to send one serial data unit. This bit is cleared whenever the -// this register is read. -// -#define SERIAL_LSR_BI 0x10 - -// -// This is the transmit holding register empty indicator. It is set -// to indicate that the hardware is ready to accept another character -// for transmission. This bit is cleared whenever a character is -// written to the transmit holding register. -// -#define SERIAL_LSR_THRE 0x20 - -// -// This bit is the transmitter empty indicator. It is set whenever the -// transmit holding buffer is empty and the transmit shift register -// (a non-software accessable register that is used to actually put -// the data out on the wire) is empty. Basically this means that all -// data has been sent. It is cleared whenever the transmit holding or -// the shift registers contain data. -// -#define SERIAL_LSR_TEMT 0x40 - -// -// This bit indicates that there is at least one error in the fifo. -// The bit will not be turned off until there are no more errors -// in the fifo. -// -#define SERIAL_LSR_FIFOERR 0x80 - - -// -// These masks are used to access the modem status register. -// Whenever one of the first four bits in the modem status -// register changes state a modem status interrupt is generated. -// - -// -// This bit is the delta clear to send. It is used to indicate -// that the clear to send bit (in this register) has *changed* -// since this register was last read by the CPU. -// -#define SERIAL_MSR_DCTS 0x01 - -// -// This bit is the delta data set ready. It is used to indicate -// that the data set ready bit (in this register) has *changed* -// since this register was last read by the CPU. -// -#define SERIAL_MSR_DDSR 0x02 - -// -// This is the trailing edge ring indicator. It is used to indicate -// that the ring indicator input has changed from a low to high state. -// -#define SERIAL_MSR_TERI 0x04 - -// -// This bit is the delta data carrier detect. It is used to indicate -// that the data carrier bit (in this register) has *changed* -// since this register was last read by the CPU. -// -#define SERIAL_MSR_DDCD 0x08 - -// -// This bit contains the (complemented) state of the clear to send -// (CTS) line. -// -#define SERIAL_MSR_CTS 0x10 - -// -// This bit contains the (complemented) state of the data set ready -// (DSR) line. -// -#define SERIAL_MSR_DSR 0x20 - -// -// This bit contains the (complemented) state of the ring indicator -// (RI) line. -// -#define SERIAL_MSR_RI 0x40 - -// -// This bit contains the (complemented) state of the data carrier detect -// (DCD) line. -// -#define SERIAL_MSR_DCD 0x80 - -// -// This should be more than enough space to hold then -// numeric suffix of the device name. -// -#define DEVICE_NAME_DELTA 20 - - -// -// Up to 16 Ports Per card. However for sixteen -// port cards the interrupt status register must me -// the indexing kind rather then the bitmask kind. -// -// -#define SERIAL_MAX_PORTS_INDEXED (16) -#define SERIAL_MAX_PORTS_NONINDEXED (8) - -typedef struct _CONFIG_DATA { - PHYSICAL_ADDRESS Controller; - PHYSICAL_ADDRESS TrController; - ULONG SpanOfController; - ULONG ClockRate; - ULONG AddressSpace; - ULONG DisablePort; - ULONG ForceFifoEnable; - ULONG RxFIFO; - ULONG TxFIFO; - ULONG PermitShare; - ULONG PermitSystemWideShare; - ULONG LogFifo; - KINTERRUPT_MODE InterruptMode; - ULONG TrVector; - ULONG TrIrql; - KAFFINITY Affinity; - ULONG TL16C550CAFC; - } CONFIG_DATA,*PCONFIG_DATA; - - -// -// This structure contains configuration data, much of which -// is read from the registry. -// -typedef struct _SERIAL_FIRMWARE_DATA { - PDRIVER_OBJECT DriverObject; - ULONG ControllersFound; - ULONG ForceFifoEnableDefault; - ULONG DebugLevel; - ULONG ShouldBreakOnEntry; - ULONG RxFIFODefault; - ULONG TxFIFODefault; - ULONG PermitShareDefault; - ULONG PermitSystemWideShare; - ULONG LogFifoDefault; - ULONG UartRemovalDetect; - UNICODE_STRING Directory; - UNICODE_STRING NtNameSuffix; - UNICODE_STRING DirectorySymbolicName; - LIST_ENTRY ConfigList; -} SERIAL_FIRMWARE_DATA,*PSERIAL_FIRMWARE_DATA; - -// -// Default xon/xoff characters. -// -#define SERIAL_DEF_XON 0x11 -#define SERIAL_DEF_XOFF 0x13 - -// -// Reasons that recption may be held up. -// -#define SERIAL_RX_DTR ((ULONG)0x01) -#define SERIAL_RX_XOFF ((ULONG)0x02) -#define SERIAL_RX_RTS ((ULONG)0x04) -#define SERIAL_RX_DSR ((ULONG)0x08) - -// -// Reasons that transmission may be held up. -// -#define SERIAL_TX_CTS ((ULONG)0x01) -#define SERIAL_TX_DSR ((ULONG)0x02) -#define SERIAL_TX_DCD ((ULONG)0x04) -#define SERIAL_TX_XOFF ((ULONG)0x08) -#define SERIAL_TX_BREAK ((ULONG)0x10) - -// -// These values are used by the routines that can be used -// to complete a read (other than interval timeout) to indicate -// to the interval timeout that it should complete. -// -#define SERIAL_COMPLETE_READ_CANCEL ((LONG)-1) -#define SERIAL_COMPLETE_READ_TOTAL ((LONG)-2) -#define SERIAL_COMPLETE_READ_COMPLETE ((LONG)-3) - -// -// These are default values that shouldn't appear in the registry -// -#define SERIAL_BAD_VALUE ((ULONG)-1) - - -typedef struct _SERIAL_DEVICE_STATE { - // - // TRUE if we need to set the state to open - // on a powerup - // - - BOOLEAN Reopen; - - // - // Hardware registers - // - - UCHAR IER; - // FCR is known by other values - UCHAR LCR; - UCHAR MCR; - // LSR is never written - // MSR is never written - // SCR is either scratch or interrupt status - - -} SERIAL_DEVICE_STATE, *PSERIAL_DEVICE_STATE; - - -typedef -UCHAR -(*PREAD_PORT_UCHAR)( - IN UCHAR *Register - ); - -typedef -VOID -(*PWRITE_PORT_UCHAR)( - IN UCHAR *Register, - IN UCHAR Value - ); - -typedef struct _SERIAL_DEVICE_EXTENSION { - // - // WDF device handle - // - WDFDEVICE WdfDevice; - // - // Points to the device object that contains - // this device extension. - // - PDEVICE_OBJECT DeviceObject; - // - // We keep a pointer around to our device name for dumps - // and for creating "external" symbolic links to this - // device. - // - UNICODE_STRING DeviceName; - // - // Pointer to the driver object - // - - PDRIVER_OBJECT DriverObject; - - // - // Records whether we actually created the symbolic link name - // at driver load time. If we didn't create it, we won't try - // to destroy it when we unload. - // - BOOLEAN CreatedSymbolicLink; - - // - // Records whether we actually created an entry in SERIALCOMM - // at driver load time. If we didn't create it, we won't try - // to destroy it when the device is removed. - // - BOOLEAN CreatedSerialCommEntry; - - // - // Did we update system count for serial ports - // - BOOLEAN IsSystemConfigInfoUpdated; - - // - // Should we expose external interfaces? - // - ULONG SkipNaming; - - // - // Support the TI TL16C550C and TL16C550CI auto flow control - // - - ULONG TL16C550CAFC; - - // - // Detect removed hardware in intterrupt routine flag - // - ULONG UartRemovalDetect; - - // - // We keep track of whether the somebody has the device currently - // opened with a simple boolean. We need to know this so that - // spurious interrupts from the device (especially during initialization) - // will be ignored. This value is only accessed in the ISR and - // is only set via synchronization routines. We may be able - // to get rid of this boolean when the code is more fleshed out. - // - BOOLEAN DeviceIsOpened; - - // - // Current state during powerdown - // - - SERIAL_DEVICE_STATE DeviceState; - - // - // TRUE if we own power policy - // - - BOOLEAN OwnsPowerPolicy; - - // - // TRUE if we should retain power on close and not aggressively - // reduce power consumption - // - - BOOLEAN RetainPowerOnClose; - - // - // Should we enable wakeup - // - - BOOLEAN IsWakeEnabled; - - // - // This list head is used to contain the time ordered list - // of read requests. Access to this list is protected by - // the global cancel spinlock. - // - WDFQUEUE ReadQueue; - - // - // This list head is used to contain the time ordered list - // of write requests. Access to this list is protected by - // the global cancel spinlock. - // - WDFQUEUE WriteQueue; - - // - // This list head is used to contain the time ordered list - // of set and wait mask requests. Access to this list is protected by - // the global cancel spinlock. - // - WDFQUEUE MaskQueue; - - // - // Holds the serialized list of purge requests. - // - WDFQUEUE PurgeQueue; - - // - // This points to the request that is currently being processed - // for the read queue. This field is initialized by the open to - // NULL. - // - // This value is only set at dispatch level. It may be - // read at interrupt level. - // - WDFREQUEST CurrentReadRequest; - - // - // This points to the request that is currently being processed - // for the write queue. - // - // This value is only set at dispatch level. It may be - // read at interrupt level. - // - WDFREQUEST CurrentWriteRequest; - - // - // Points to the request that is currently being processed to - // affect the wait mask operations. - // - WDFREQUEST CurrentMaskRequest; - - // - // Points to the request that is currently being processed to - // purge the read/write queues and buffers. - // - WDFREQUEST CurrentPurgeRequest; - - // - // Points to the current request that is waiting on a comm event. - // - WDFREQUEST CurrentWaitRequest; - - // - // Points to the request that is being used to send an immediate - // character. - // - WDFREQUEST CurrentImmediateRequest; - - // - // Points to the request that is being used to count the number - // of characters received after an xoff (as currently defined - // by the IOCTL_SERIAL_XOFF_COUNTER ioctl) is sent. - // - WDFREQUEST CurrentXoffRequest; - - // - // The base address for the set of device registers - // of the serial port. - // - PUCHAR Controller; - // - // This value holds the span (in units of bytes) of the register - // set controlling this port. This is constant over the life - // of the port. - // - ULONG SpanOfController; - - // - // Address space - // - - ULONG AddressSpace; - - PREAD_PORT_UCHAR SerialReadUChar; - PWRITE_PORT_UCHAR SerialWriteUChar; - - // - // Hold the clock rate input to the serial part. - // - ULONG ClockRate; - - // - // The number of characters to push out if a fifo is present. - // - ULONG TxFifoAmount; - - // - // Set to indicate that it is ok to share interrupts within the device. - // - ULONG PermitShare; - - - // - // Points to the interrupt object for used by this device. - // - WDFINTERRUPT WdfInterrupt; - - // - // Translated vector - // - ULONG Vector; - // - // Translated Irql - // - KIRQL Irql; - - KINTERRUPT_MODE InterruptMode; - - KAFFINITY Affinity; - - // - // This value is set by the read code to hold the time value - // used for read interval timing. We keep it in the extension - // so that the interval timer dpc routine determine if the - // interval time has passed for the IO. - // - LARGE_INTEGER IntervalTime; - - // - // These two values hold the "constant" time that we should use - // to delay for the read interval time. - // - LARGE_INTEGER ShortIntervalAmount; - LARGE_INTEGER LongIntervalAmount; - - // - // This holds the value that we use to determine if we should use - // the long interval delay or the short interval delay. - // - LARGE_INTEGER CutOverAmount; - - // - // This holds the system time when we last time we had - // checked that we had actually read characters. Used - // for interval timing. - // - LARGE_INTEGER LastReadTime; - - - // - // This points the the delta time that we should use to - // delay for interval timing. - // - PLARGE_INTEGER IntervalTimeToUse; - - - // - // Set at intialization to indicate that on the current - // architecture we need to unmap the base register address - // when we unload the driver. - // - BOOLEAN UnMapRegisters; - - // - // Holds the number of bytes remaining in the current write - // request. - // - // This location is only accessed while at interrupt level. - // - ULONG WriteLength; - - // - // Holds a pointer to the current character to be sent in - // the current write. - // - // This location is only accessed while at interrupt level. - // - PUCHAR WriteCurrentChar; - - // - // This is a buffer for the read processing. - // - // The buffer works as a ring. When the character is read from - // the device it will be place at the end of the ring. - // - // Characters are only placed in this buffer at interrupt level - // although character may be read at any level. The pointers - // that manage this buffer may not be updated except at interrupt - // level. - // - PUCHAR InterruptReadBuffer; - - // - // This is a pointer to the first character of the buffer into - // which the interrupt service routine is copying characters. - // - PUCHAR ReadBufferBase; - - // - // This is a count of the number of characters in the interrupt - // buffer. This value is set and read at interrupt level. Note - // that this value is only *incremented* at interrupt level so - // it is safe to read it at any level. When characters are - // copied out of the read buffer, this count is decremented by - // a routine that synchronizes with the ISR. - // - ULONG CharsInInterruptBuffer; - - // - // Points to the first available position for a newly received - // character. This variable is only accessed at interrupt level and - // buffer initialization code. - // - PUCHAR CurrentCharSlot; - - // - // This variable is used to contain the last available position - // in the read buffer. It is updated at open and at interrupt - // level when switching between the users buffer and the interrupt - // buffer. - // - PUCHAR LastCharSlot; - - // - // This marks the first character that is available to satisfy - // a read request. Note that while this always points to valid - // memory, it may not point to a character that can be sent to - // the user. This can occur when the buffer is empty. - // - PUCHAR FirstReadableChar; - - // - // Pointer to the lock variable returned for this extension when - // locking down the driver - // - PVOID LockPtr; - - - // - // This variable holds the size of whatever buffer we are currently - // using. - // - ULONG BufferSize; - - // - // This variable holds .8 of BufferSize. We don't want to recalculate - // this real often - It's needed when so that an application can be - // "notified" that the buffer is getting full. - // - ULONG BufferSizePt8; - - // - // This value holds the number of characters desired for a - // particular read. It is initially set by read length in the - // WDFREQUEST. It is decremented each time more characters are placed - // into the "users" buffer buy the code that reads characters - // out of the typeahead buffer into the users buffer. If the - // typeahead buffer is exhausted by the read, and the reads buffer - // is given to the isr to fill, this value is becomes meaningless. - // - ULONG NumberNeededForRead; - - // - // This mask will hold the bitmask sent down via the set mask - // ioctl. It is used by the interrupt service routine to determine - // if the occurence of "events" (in the serial drivers understanding - // of the concept of an event) should be noted. - // - ULONG IsrWaitMask; - - // - // This mask will always be a subset of the IsrWaitMask. While - // at device level, if an event occurs that is "marked" as interesting - // in the IsrWaitMask, the driver will turn on that bit in this - // history mask. The driver will then look to see if there is a - // request waiting for an event to occur. If there is one, it - // will copy the value of the history mask into the wait request, zero - // the history mask, and complete the wait request. If there is no - // waiting request, the driver will be satisfied with just recording - // that the event occured. If a wait request should be queued, - // the driver will look to see if the history mask is non-zero. If - // it is non-zero, the driver will copy the history mask into the - // request, zero the history mask, and then complete the request. - // - ULONG HistoryMask; - - // - // This is a pointer to the where the history mask should be - // placed when completing a wait. It is only accessed at - // device level. - // - // We have a pointer here to assist us to synchronize completing a wait. - // If this is non-zero, then we have wait outstanding, and the isr still - // knows about it. We make this pointer null so that the isr won't - // attempt to complete the wait. - // - // We still keep a pointer around to the wait request, since the actual - // pointer to the wait request will be used for the "common" request completion - // path. - // - ULONG *IrpMaskLocation; - - // - // This mask holds all of the reason that transmission - // is not proceeding. Normal transmission can not occur - // if this is non-zero. - // - // This is only written from interrupt level. - // This could be (but is not) read at any level. - // - ULONG TXHolding; - - // - // This mask holds all of the reason that reception - // is not proceeding. Normal reception can not occur - // if this is non-zero. - // - // This is only written from interrupt level. - // This could be (but is not) read at any level. - // - ULONG RXHolding; - - // - // This holds the reasons that the driver thinks it is in - // an error state. - // - // This is only written from interrupt level. - // This could be (but is not) read at any level. - // - ULONG ErrorWord; - - // - // This keeps a total of the number of characters that - // are in all of the "write" irps that the driver knows - // about. It is only accessed with the cancel spinlock - // held. - // - ULONG TotalCharsQueued; - - // - // This holds a count of the number of characters read - // the last time the interval timer dpc fired. It - // is a long (rather than a ulong) since the other read - // completion routines use negative values to indicate - // to the interval timer that it should complete the read - // if the interval timer DPC was lurking in some DPC queue when - // some other way to complete occurs. - // - LONG CountOnLastRead; - - // - // This is a count of the number of characters read by the - // isr routine. It is *ONLY* written at isr level. We can - // read it at dispatch level. - // - ULONG ReadByIsr; - - // - // This holds the current baud rate for the device. - // - ULONG CurrentBaud; - - // - // This is the number of characters read since the XoffCounter - // was started. This variable is only accessed at device level. - // If it is greater than zero, it implies that there is an - // XoffCounter ioctl in the queue. - // - LONG CountSinceXoff; - - // - // This ulong is incremented each time something trys to start - // the execution path that tries to lower the RTS line when - // doing transmit toggling. If it "bumps" into another path - // (indicated by a false return value from queueing a dpc - // and a TRUE return value tring to start a timer) it will - // decrement the count. These increments and decrements - // are all done at device level. Note that in the case - // of a bump while trying to start the timer, we have to - // go up to device level to do the decrement. - // - ULONG CountOfTryingToLowerRTS; - - // - // This ULONG is used to keep track of the "named" (in ntddser.h) - // baud rates that this particular device supports. - // - ULONG SupportedBauds; - - // - // Holds the timeout controls for the device. This value - // is set by the Ioctl processing. - // - // It should only be accessed under protection of the control - // lock since more than one request can be in the control dispatch - // routine at one time. - // - SERIAL_TIMEOUTS Timeouts; - - // - // This holds the various characters that are used - // for replacement on errors and also for flow control. - // - // They are only set at interrupt level. - // - SERIAL_CHARS SpecialChars; - - // - // This structure holds the handshake and control flow - // settings for the serial driver. - // - // It is only set at interrupt level. It can be - // be read at any level with the control lock held. - // - SERIAL_HANDFLOW HandFlow; - - - // - // Holds performance statistics that applications can query. - // Reset on each open. Only set at device level. - // - SERIALPERF_STATS PerfStats; - - // - // This holds what we beleive to be the current value of - // the line control register. - // - // It should only be accessed under protection of the control - // lock since more than one request can be in the control dispatch - // routine at one time. - // - UCHAR LineControl; - - - // - // This is only accessed at interrupt level. It keeps track - // of whether the holding register is empty. - // - BOOLEAN HoldingEmpty; - - // - // This variable is only accessed at interrupt level. It - // indicates that we want to transmit a character immediately. - // That is - in front of any characters that could be transmitting - // from a normal write. - // - BOOLEAN TransmitImmediate; - - // - // This variable is only accessed at interrupt level. Whenever - // a wait is initiated this variable is set to false. - // Whenever any kind of character is written it is set to true. - // Whenever the write queue is found to be empty the code that - // is processing that completing request will synchonize with the interrupt. - // If this synchronization code finds that the variable is true and that - // there is a wait on the transmit queue being empty then it is - // certain that the queue was emptied and that it has happened since - // the wait was initiated. - // - BOOLEAN EmptiedTransmit; - - // - // We keep the following values around so that we can connect - // to the interrupt and report resources after the configuration - // record is gone. - // - - // - // We hold the character that should be transmitted immediately. - // - // Note that we can't use this to determine whether there is - // a character to send because the character to send could be - // zero. - // - UCHAR ImmediateChar; - - // - // This holds the mask that will be used to mask off unwanted - // data bits of the received data (valid data bits can be 5,6,7,8) - // The mask will normally be 0xff. This is set while the control - // lock is held since it wouldn't have adverse effects on the - // isr if it is changed in the middle of reading characters. - // (What it would do to the app is another question - but then - // the app asked the driver to do it.) - // - UCHAR ValidDataMask; - - // - // The application can turn on a mode,via the - // IOCTL_SERIAL_LSRMST_INSERT ioctl, that will cause the - // serial driver to insert the line status or the modem - // status into the RX stream. The parameter with the ioctl - // is a pointer to a UCHAR. If the value of the UCHAR is - // zero, then no insertion will ever take place. If the - // value of the UCHAR is non-zero (and not equal to the - // xon/xoff characters), then the serial driver will insert. - // - UCHAR EscapeChar; - - // - // These two booleans are used to indicate to the isr transmit - // code that it should send the xon or xoff character. They are - // only accessed at open and at interrupt level. - // - BOOLEAN SendXonChar; - BOOLEAN SendXoffChar; - - // - // This boolean will be true if a 16550 is present *and* enabled. - // - BOOLEAN FifoPresent; - - // - // This is the water mark that the rxfifo should be - // set to when the fifo is turned on. This is not the actual - // value, but the encoded value that goes into the register. - // - UCHAR RxFifoTrigger; - - // - // This points to a DPC used to complete write requests. - // - WDFDPC CompleteWriteDpc; - - // - // This points to a DPC used to complete read requests. - // - WDFDPC CompleteReadDpc; - - - // - // This dpc is fired off if a comm error occurs. It will - // execute a dpc routine that will cancel all pending reads - // and writes. - // - WDFDPC CommErrorDpc; - - // - // This dpc is fired off if an event occurs and there was - // a request waiting on that event. A dpc routine will execute - // that completes the request. - // - WDFDPC CommWaitDpc; - - // - // This dpc is fired off when the transmit immediate char - // character is given to the hardware. It will simply complete - // the request. - // - WDFDPC CompleteImmediateDpc; - - // - // This dpc is fired off if the xoff counter actually runs down - // to zero. - // - WDFDPC XoffCountCompleteDpc; - - // - // This dpc is fired off only from device level to start off - // a timer that will queue a dpc to check if the RTS line - // should be lowered when we are doing transmit toggling. - // - WDFDPC StartTimerLowerRTSDpc; - - // - // This timer used to handle total read request timing. - // - WDFTIMER ReadRequestTotalTimer; - - // - // This timer used to handle interval read request timing. - // - WDFTIMER ReadRequestIntervalTimer; - - // - // This timer used to handle total write request timing. - // - WDFTIMER WriteRequestTotalTimer; - - // - // This is timer structure used to handle total time request timing. - // - WDFTIMER ImmediateTotalTimer; - - // - // This timer is used to timeout the xoff counter io. - // - WDFTIMER XoffCountTimer; - - // - // This timer is used to invoke a dpc one character time - // after the timer is set. That dpc will be used to check - // whether we should lower the RTS line if we are doing - // transmit toggling. - // - WDFTIMER LowerRTSTimer; - - // - // WMI Information - // - - // - // WMI Comm Data - // - - SERIAL_WMI_COMM_DATA WmiCommData; - - // - // WMI HW Data - // - - SERIAL_WMI_HW_DATA WmiHwData; - - // - // WMI Performance Data - // - - SERIAL_WMI_PERF_DATA WmiPerfData; - -} SERIAL_DEVICE_EXTENSION,*PSERIAL_DEVICE_EXTENSION; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SERIAL_DEVICE_EXTENSION, - SerialGetDeviceExtension) - -// -// This is the scratch area for every request. -// We will copy some of the frequently used information of the request -// into our context area so that way we don't have to call WdfRequestGetParams -// function everytime. -// -typedef struct _REQUEST_CONTEXT { - ULONG_PTR Information; - NTSTATUS Status; - ULONG Length; - PVOID RefCount; - PVOID SystemBuffer; - UCHAR MajorFunction; - PFN_WDF_REQUEST_CANCEL CancelRoutine; - BOOLEAN Cancelled; - PVOID Type3InputBuffer; - PSERIAL_DEVICE_EXTENSION Extension; - ULONG IoctlCode; - BOOLEAN MarkCancelableOnResume; -} REQUEST_CONTEXT, *PREQUEST_CONTEXT; - - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, - SerialGetRequestContext) - - -// -// This is the Interrupt context for the Serial device. This structure is used -// for keeping track of whether the Interrupt is connected or not. -// -typedef struct _SERIAL_INTERRUPT_CONTEXT { - - // - // This boolean value indicates whether Interrupt is connected. - // - BOOLEAN IsInterruptConnected; - - // - // This lock is used to synchronize the file close logic and - // the Surprise Removal logic. When a surprise remove happens, - // the device interrupts are disabled. When this occurs, the - // file close logic should not attempt to use the interrupt - // object. - // - WDFWAITLOCK InterruptStateLock; - -} SERIAL_INTERRUPT_CONTEXT, *PSERIAL_INTERRUPT_CONTEXT; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SERIAL_INTERRUPT_CONTEXT, - SerialGetInterruptContext) - - -#define SERIAL_FLAGS_CLEAR 0x0L -#define SERIAL_FLAGS_STARTED 0x1L -#define SERIAL_FLAGS_STOPPED 0x2L -#define SERIAL_FLAGS_BROKENHW 0x4L -#define SERIAL_FLAGS_LEGACY_ENUMED 0x8L - - -__inline -UCHAR -SerialReadPortUChar ( - IN UCHAR * x - ) -{ - return READ_PORT_UCHAR (x); -} -__inline -VOID -SerialWritePortUChar ( - IN UCHAR * x, - IN UCHAR y - ) -{ - WRITE_PORT_UCHAR (x,y); -} - -__inline -UCHAR -SerialReadRegisterUChar ( - IN UCHAR * x - ) -{ - return READ_REGISTER_UCHAR (x); -} - -__inline -VOID -SerialWriteRegisterUChar ( - IN UCHAR * x, - IN UCHAR y - ) -{ - WRITE_REGISTER_UCHAR (x,y); -} - - - -// -// Sets the divisor latch register. The divisor latch register -// is used to control the baud rate of the 8250. -// -// As with all of these routines it is assumed that it is called -// at a safe point to access the hardware registers. In addition -// it also assumes that the data is correct. -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// DesiredDivisor - The value to which the divisor latch register should -// be set. -// -#define WRITE_DIVISOR_LATCH(Extension, BaseAddress,DesiredDivisor) \ -do \ -{ \ - PUCHAR Address = BaseAddress; \ - SHORT Divisor = DesiredDivisor; \ - UCHAR LineControl; \ - LineControl = Extension->SerialReadUChar(Address+LINE_CONTROL_REGISTER); \ - Extension->SerialWriteUChar( \ - Address+LINE_CONTROL_REGISTER, \ - (UCHAR)(LineControl | SERIAL_LCR_DLAB) \ - ); \ - Extension->SerialWriteUChar( \ - Address+DIVISOR_LATCH_LSB, \ - (UCHAR)(Divisor & 0xff) \ - ); \ - Extension->SerialWriteUChar( \ - Address+DIVISOR_LATCH_MSB, \ - (UCHAR)((Divisor & 0xff00) >> 8) \ - ); \ - Extension->SerialWriteUChar( \ - Address+LINE_CONTROL_REGISTER, \ - LineControl \ - ); \ -} WHILE (0) - -// -// Reads the divisor latch register. The divisor latch register -// is used to control the baud rate of the 8250. -// -// As with all of these routines it is assumed that it is called -// at a safe point to access the hardware registers. In addition -// it also assumes that the data is correct. -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// DesiredDivisor - A pointer to the 2 byte word which will contain -// the value of the divisor. -// -#define READ_DIVISOR_LATCH(Extension, BaseAddress,PDesiredDivisor) \ -do \ -{ \ - PUCHAR Address = BaseAddress; \ - PSHORT PDivisor = PDesiredDivisor; \ - UCHAR LineControl; \ - UCHAR Lsb; \ - UCHAR Msb; \ - LineControl = Extension->SerialReadUChar(Address+LINE_CONTROL_REGISTER); \ - Extension->SerialWriteUChar( \ - Address+LINE_CONTROL_REGISTER, \ - (UCHAR)(LineControl | SERIAL_LCR_DLAB) \ - ); \ - Lsb = Extension->SerialReadUChar(Address+DIVISOR_LATCH_LSB); \ - Msb = Extension->SerialReadUChar(Address+DIVISOR_LATCH_MSB); \ - *PDivisor = Lsb; \ - *PDivisor = *PDivisor | (((USHORT)Msb) << 8); \ - Extension->SerialWriteUChar( \ - Address+LINE_CONTROL_REGISTER, \ - LineControl \ - ); \ -} WHILE (0) - -// -// This macro reads the interrupt enable register. -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -#define READ_INTERRUPT_ENABLE(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+INTERRUPT_ENABLE_REGISTER)) - -// -// This macro writes the interrupt enable register. -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// Values - The values to write to the interrupt enable register. -// -#define WRITE_INTERRUPT_ENABLE(Extension, BaseAddress,Values) \ -do \ -{ \ - Extension->SerialWriteUChar( \ - BaseAddress+INTERRUPT_ENABLE_REGISTER, \ - Values \ - ); \ -} WHILE (0) - -// -// This macro disables all interrupts on the hardware. -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define DISABLE_ALL_INTERRUPTS(Extension, BaseAddress) \ -do \ -{ \ - WRITE_INTERRUPT_ENABLE(Extension, BaseAddress,0); \ -} WHILE (0) - -// -// This macro enables all interrupts on the hardware. -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define ENABLE_ALL_INTERRUPTS(Extension, BaseAddress) \ -do \ -{ \ - \ - WRITE_INTERRUPT_ENABLE( \ - (Extension), (BaseAddress), \ - (UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \ - SERIAL_IER_RLS | SERIAL_IER_MS) \ - ); \ - \ -} WHILE (0) - -// -// This macro reads the interrupt identification register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// Note that this routine potententially quites a transmitter -// empty interrupt. This is because one way that the transmitter -// empty interrupt is cleared is to simply read the interrupt id -// register. -// -// -#define READ_INTERRUPT_ID_REG(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+INTERRUPT_IDENT_REGISTER)) - -// -// This macro reads the modem control register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define READ_MODEM_CONTROL(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+MODEM_CONTROL_REGISTER)) - -// -// This macro reads the modem status register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define READ_MODEM_STATUS(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+MODEM_STATUS_REGISTER)) - -// -// This macro reads a value out of the receive buffer -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define READ_RECEIVE_BUFFER(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+RECEIVE_BUFFER_REGISTER)) - -// -// This macro reads the line status register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define READ_LINE_STATUS(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+LINE_STATUS_REGISTER)) - -// -// This macro writes the line control register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define WRITE_LINE_CONTROL(Extension, BaseAddress,NewLineControl) \ -do \ -{ \ - Extension->SerialWriteUChar( \ - (BaseAddress)+LINE_CONTROL_REGISTER, \ - (NewLineControl) \ - ); \ -} WHILE (0) - -// -// This macro reads the line control register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// -#define READ_LINE_CONTROL(Extension, BaseAddress) \ - (Extension->SerialReadUChar((BaseAddress)+LINE_CONTROL_REGISTER)) - - -// -// This macro writes to the transmit register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// TransmitChar - The character to send down the wire. -// -// -#define WRITE_TRANSMIT_HOLDING(Extension, BaseAddress,TransmitChar) \ -do \ -{ \ - Extension->SerialWriteUChar( \ - (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \ - (TransmitChar) \ - ); \ -} WHILE (0) - -// -// This macro writes to the transmit FIFO register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// TransmitChars - Pointer to the characters to send down the wire. -// -// TxN - number of charactes to send. -// -// -#define WRITE_TRANSMIT_FIFO_HOLDING(Extension, BaseAddress,TransmitChars,TxN) \ -do \ -{ \ - WRITE_PORT_BUFFER_UCHAR( \ - (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \ - (TransmitChars), \ - (TxN) \ - ); \ -} WHILE (0) - -// -// This macro writes to the control register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// ControlValue - The value to set the fifo control register too. -// -// -#define WRITE_FIFO_CONTROL(Extension, BaseAddress,ControlValue) \ -do \ -{ \ - Extension->SerialWriteUChar( \ - (BaseAddress)+FIFO_CONTROL_REGISTER, \ - (ControlValue) \ - ); \ -} WHILE (0) - -// -// This macro writes to the modem control register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. -// -// ModemControl - The control bits to send to the modem control. -// -// -#define WRITE_MODEM_CONTROL(Extension, BaseAddress,ModemControl) \ -do \ -{ \ - Extension->SerialWriteUChar( \ - (BaseAddress)+MODEM_CONTROL_REGISTER, \ - (ModemControl) \ - ); \ -} WHILE (0) - -#define WRITE_INTERRUPT_STATUS(Extension, BaseAddress,Status) \ -do \ -{ \ - Extension->SerialWriteUChar(BaseAddress, Status); \ -} WHILE (0) - - -// -// This macro reads the interrupt status register -// -// Arguments: -// -// BaseAddress - A pointer to the address from which the hardware -// device registers are located. BaseAddress is gotten -// from PSERIAL_MULTIPORT_DISPATCH->InterruptStatus which -// already has the complete address -// -// AddressSpace - Flag indicating where port is located, MMIO or IO -// space -// -// -#define READ_INTERRUPT_STATUS(Extension, BaseAddress) \ - Extension->SerialReadUChar(BaseAddress)) - -// -// We use this to query into the registry as to whether we -// should break at driver entry. -// - -extern SERIAL_FIRMWARE_DATA driverDefaults; - - -// -// This is exported from the kernel. It is used to point -// to the address that the kernel debugger is using. -// - -extern PUCHAR *KdComPortInUse; - - -typedef enum _SERIAL_MEM_COMPARES { - AddressesAreEqual, - AddressesOverlap, - AddressesAreDisjoint - } SERIAL_MEM_COMPARES,*PSERIAL_MEM_COMPARES; - -#define SERIAL_BAUD_INVALID 0xFFFFFFFF - -typedef struct _SUPPORTED_BAUD_RATES { - UINT32 BaudRate; - ULONG Mask; -}SUPPORTED_BAUD_RATES; - diff --git a/tests/projects/wdk/kmdf/serial/serial.inx b/tests/projects/wdk/kmdf/serial/serial.inx deleted file mode 100644 index 3322653b0..000000000 Binary files a/tests/projects/wdk/kmdf/serial/serial.inx and /dev/null differ diff --git a/tests/projects/wdk/kmdf/serial/serial.rc b/tests/projects/wdk/kmdf/serial/serial.rc deleted file mode 100644 index 9fbb59de3..000000000 --- a/tests/projects/wdk/kmdf/serial/serial.rc +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_SYSTEM -#define VER_FILEDESCRIPTION_STR "Serial Device Driver" -#define VER_INTERNALNAME_STR "serial.sys" -#define VER_ORIGINALFILENAME_STR "serial.sys" - -#include "common.ver" - -#include "serlog.rc" - diff --git a/tests/projects/wdk/kmdf/serial/serialp.h b/tests/projects/wdk/kmdf/serial/serialp.h deleted file mode 100644 index d363f3503..000000000 --- a/tests/projects/wdk/kmdf/serial/serialp.h +++ /dev/null @@ -1,596 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name : - - serialp.h - -Abstract: - - Prototypes and macros that are used throughout the driver. - ---*/ - -//----------------------------------------------------------------------------- -// 4127 -- Conditional Expression is Constant warning -//----------------------------------------------------------------------------- -#define WHILE(constant) \ -__pragma(warning(suppress: 4127)) while(constant) - -typedef -VOID -(*PSERIAL_START_ROUTINE) ( - IN PSERIAL_DEVICE_EXTENSION - ); - -typedef -VOID -(*PSERIAL_GET_NEXT_ROUTINE) ( - IN WDFREQUEST *CurrentOpRequest, - IN WDFQUEUE QueueToProcess, - OUT WDFREQUEST *NewRequest, - IN BOOLEAN CompleteCurrent, - PSERIAL_DEVICE_EXTENSION Extension - ); - -DRIVER_INITIALIZE DriverEntry; - -EVT_WDF_DRIVER_DEVICE_ADD SerialEvtDeviceAdd; -EVT_WDF_OBJECT_CONTEXT_CLEANUP SerialEvtDriverContextCleanup; -EVT_WDF_DEVICE_CONTEXT_CLEANUP SerialEvtDeviceContextCleanup; - -EVT_WDF_DEVICE_D0_ENTRY SerialEvtDeviceD0Entry; -EVT_WDF_DEVICE_D0_EXIT SerialEvtDeviceD0Exit; -EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED SerialEvtDeviceD0EntryPostInterruptsEnabled; -EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED SerialEvtDeviceD0ExitPreInterruptsDisabled; -EVT_WDF_DEVICE_PREPARE_HARDWARE SerialEvtPrepareHardware; -EVT_WDF_DEVICE_RELEASE_HARDWARE SerialEvtReleaseHardware; - -EVT_WDF_DEVICE_FILE_CREATE SerialEvtDeviceFileCreate; -EVT_WDF_FILE_CLOSE SerialEvtFileClose; - -EVT_WDF_IO_QUEUE_IO_READ SerialEvtIoRead; -EVT_WDF_IO_QUEUE_IO_WRITE SerialEvtIoWrite; -EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SerialEvtIoDeviceControl; -EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL SerialEvtIoInternalDeviceControl; -EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE SerialEvtCanceledOnQueue; -EVT_WDF_IO_QUEUE_IO_STOP SerialEvtIoStop; -EVT_WDF_IO_QUEUE_IO_RESUME SerialEvtIoResume; - -EVT_WDF_INTERRUPT_ENABLE SerialEvtInterruptEnable; -EVT_WDF_INTERRUPT_DISABLE SerialEvtInterruptDisable; - -EVT_WDF_DPC SerialCompleteRead; -EVT_WDF_DPC SerialCompleteWrite; -EVT_WDF_DPC SerialCommError; -EVT_WDF_DPC SerialCompleteImmediate; -EVT_WDF_DPC SerialCompleteXoff; -EVT_WDF_DPC SerialCompleteWait; -EVT_WDF_DPC SerialStartTimerLowerRTS; - -EVT_WDF_TIMER SerialReadTimeout; -EVT_WDF_TIMER SerialIntervalReadTimeout; -EVT_WDF_TIMER SerialWriteTimeout; -EVT_WDF_TIMER SerialTimeoutImmediate; -EVT_WDF_TIMER SerialTimeoutXoff; -EVT_WDF_TIMER SerialInvokePerhapsLowerRTS; - -VOID -SerialStartRead( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialStartWrite( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialStartMask( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialStartImmediate( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialStartPurge( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialGetNextWrite( - IN WDFREQUEST *CurrentOpRequest, - IN WDFQUEUE QueueToProcess, - IN WDFREQUEST *NewRequest, - IN BOOLEAN CompleteCurrent, - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialWdmDeviceFileCreate; -EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialWdmFileClose; -EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialFlush; - -EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialQueryInformationFile; -EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialSetInformationFile; - -NTSTATUS -SerialDeviceFileCreateWorker ( - IN WDFDEVICE Device - ); - - -VOID -SerialFileCloseWorker( - IN WDFDEVICE Device - ); - -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialProcessEmptyTransmit; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetDTR; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialClrDTR; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetRTS; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialClrRTS; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetBaud; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetLineControl; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetHandFlow; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialTurnOnBreak; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialTurnOffBreak; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPretendXoff; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPretendXon; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialReset; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPerhapsLowerRTS; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialMarkOpen; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialMarkClose; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetStats; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialClearStats; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetChars; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetMCRContents; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetMCRContents; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetFCRContents; - -BOOLEAN -SerialSetupNewHandFlow( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN PSERIAL_HANDFLOW NewHandFlow - ); - - -VOID -SerialHandleReducedIntBuffer( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialProdXonXoff( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN BOOLEAN SendXon - ); - -EVT_WDF_REQUEST_CANCEL SerialCancelWait; - - -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPurgeInterruptBuff; - -VOID -SerialPurgeRequests( - IN WDFQUEUE QueueToClean, - IN WDFREQUEST *CurrentOpRequest - ); - -VOID -SerialFlushRequests( - IN WDFQUEUE QueueToClean, - IN WDFREQUEST *CurrentOpRequest - ); - -VOID -SerialGetNextRequest( - IN WDFREQUEST *CurrentOpRequest, - IN WDFQUEUE QueueToProcess, - OUT WDFREQUEST *NextIrp, - IN BOOLEAN CompleteCurrent, - IN PSERIAL_DEVICE_EXTENSION extension - ); - - -VOID -SerialTryToCompleteCurrent( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN PFN_WDF_INTERRUPT_SYNCHRONIZE SynchRoutine OPTIONAL, - IN NTSTATUS StatusToUse, - IN WDFREQUEST *CurrentOpRequest, - IN WDFQUEUE QueueToProcess, - IN WDFTIMER IntervalTimer, - IN WDFTIMER TotalTimer, - IN PSERIAL_START_ROUTINE Starter, - IN PSERIAL_GET_NEXT_ROUTINE GetNextIrp, - IN LONG RefType - ); - -VOID -SerialStartOrQueue( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN WDFREQUEST Request, - IN WDFQUEUE QueueToExamine, - IN WDFREQUEST *CurrentOpRequest, - IN PSERIAL_START_ROUTINE Starter - ); - -NTSTATUS -SerialCompleteIfError( - PSERIAL_DEVICE_EXTENSION extension, - WDFREQUEST Request - ); - -ULONG -SerialHandleModemUpdate( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN BOOLEAN DoingTX - ); - - -EVT_WDF_INTERRUPT_ISR SerialISR; - -NTSTATUS -SerialGetDivisorFromBaud( - IN ULONG ClockRate, - IN LONG DesiredBaud, - OUT PSHORT AppropriateDivisor - ); - -VOID -SerialCleanupDevice( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -UCHAR -SerialProcessLSR( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -LARGE_INTEGER -SerialGetCharTime( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - - -VOID -SerialPutChar( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN UCHAR CharToPut - ); - -NTSTATUS -SerialGetConfigDefaults( - IN PSERIAL_FIRMWARE_DATA DriverDefaultsPtr, - IN WDFDRIVER Driver - ); - -VOID -SerialGetProperties( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN PSERIAL_COMMPROP Properties - ); - -VOID -SerialLogError( - _In_ PDRIVER_OBJECT DriverObject, - _In_opt_ PDEVICE_OBJECT DeviceObject, - _In_ PHYSICAL_ADDRESS P1, - _In_ PHYSICAL_ADDRESS P2, - _In_ ULONG SequenceNumber, - _In_ UCHAR MajorFunctionCode, - _In_ UCHAR RetryCount, - _In_ ULONG UniqueErrorValue, - _In_ NTSTATUS FinalStatus, - _In_ NTSTATUS SpecificIOStatus, - _In_ ULONG LengthOfInsert1, - _In_reads_bytes_opt_(LengthOfInsert1) PWCHAR Insert1, - _In_ ULONG LengthOfInsert2, - _In_reads_bytes_opt_(LengthOfInsert2) PWCHAR Insert2 - ); - -NTSTATUS -SerialMapHWResources( - IN WDFDEVICE Device, - IN WDFCMRESLIST PResList, - IN WDFCMRESLIST PTrResList, - OUT PCONFIG_DATA PConfig - ); - -VOID -SerialUnmapHWResources( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -BOOLEAN -SerialGetRegistryKeyValue ( - IN WDFDEVICE WdfDevice, - _In_ PCWSTR Name, - OUT PULONG Value - ); - - -BOOLEAN -SerialPutRegistryKeyValue ( - IN WDFDEVICE WdfDevice, - _In_ PCWSTR Name, - IN ULONG Value - ); - -NTSTATUS -SerialInitController( - IN PSERIAL_DEVICE_EXTENSION pDevExt, - IN PCONFIG_DATA PConfigData - ); - -BOOLEAN -SerialCIsrSw( - IN WDFINTERRUPT Interrupt, - IN ULONG MessageID - ); - -NTSTATUS -SerialDoExternalNaming( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -PVOID -SerialGetMappedAddress( - PHYSICAL_ADDRESS IoAddress, - ULONG NumberOfBytes, - ULONG AddressSpace, - PBOOLEAN MappedAddress - ); - -BOOLEAN -SerialDoesPortExist( - IN PSERIAL_DEVICE_EXTENSION Extension, - PUNICODE_STRING InsertString, - IN ULONG ForceFifo, - IN ULONG LogFifo - ); - -SERIAL_MEM_COMPARES -SerialMemCompare( - IN PHYSICAL_ADDRESS A, - IN ULONG SpanOfA, - IN PHYSICAL_ADDRESS B, - IN ULONG SpanOfB - ); - -VOID -SerialUndoExternalNaming( - IN PSERIAL_DEVICE_EXTENSION Extension - ); - -VOID -SerialReleaseResources( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -VOID -SerialPurgePendingRequests( - PSERIAL_DEVICE_EXTENSION pDevExt - ); - -VOID -SerialDisableUART( - IN PVOID Context - ); - -VOID -SerialDrainUART( - IN PSERIAL_DEVICE_EXTENSION PDevExt, - IN PLARGE_INTEGER PDrainTime - ); - -VOID -SerialSaveDeviceState( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -NTSTATUS -SerialSetPowerPolicy( - IN PSERIAL_DEVICE_EXTENSION DeviceExtension - ); - -UINT32 -SerialReportMaxBaudRate( - ULONG Bauds - ); - -BOOLEAN -SerialInsertQueueDpc( - IN WDFDPC Dpc - ); - -BOOLEAN -SerialSetTimer( - IN WDFTIMER Timer, - IN LARGE_INTEGER DueTime - ); - -BOOLEAN -SerialCancelTimer( - IN WDFTIMER Timer, - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -VOID -SerialUnlockPages( - IN WDFDPC PDpc, - IN PVOID PDeferredContext, - IN PVOID PSysContext1, - IN PVOID PSysContext2) - ; - -VOID -SerialMarkHardwareBroken( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -VOID -SerialDisableInterfacesResources( - IN PSERIAL_DEVICE_EXTENSION PDevExt, - IN BOOLEAN DisableUART - ); - -VOID -SerialSetDeviceFlags( - IN PSERIAL_DEVICE_EXTENSION PDevExt, - OUT PULONG PFlags, - IN ULONG Value, - IN BOOLEAN Set - ); - - -VOID -SetDeviceIsOpened( - IN PSERIAL_DEVICE_EXTENSION PDevExt, - IN BOOLEAN DeviceIsOpened, - IN BOOLEAN Reopen - ); - -BOOLEAN -IsQueueEmpty( - IN WDFQUEUE Queue - ); - -NTSTATUS -SerialCreateTimersAndDpcs( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -VOID -SerialDrainTimersAndDpcs( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ); - -VOID -SerialSetCancelRoutine( - IN WDFREQUEST Request, - IN PFN_WDF_REQUEST_CANCEL CancelRoutine - ); - -NTSTATUS -SerialClearCancelRoutine( - IN WDFREQUEST Request, - IN BOOLEAN ClearReference - ); - -NTSTATUS -SerialWmiRegistration( - WDFDEVICE Device - ); - -NTSTATUS -SerialReadSymName( - IN WDFDEVICE Device, - _Out_writes_bytes_(*SizeOfRegName) PWSTR RegName, - _Inout_ PUSHORT SizeOfRegName - ); - -VOID -SerialCompleteRequest( - IN WDFREQUEST Request, - IN NTSTATUS Status, - IN ULONG_PTR Info - ); - -BOOLEAN -SerialGetFdoRegistryKeyValue( - IN PWDFDEVICE_INIT DeviceInit, - _In_ PCWSTR Name, - OUT PULONG Value - ); - -VOID -SerialSetInterruptPolicy( - _In_ WDFINTERRUPT WdfInterrupt - ); - -typedef struct _SERIAL_UPDATE_CHAR { - PSERIAL_DEVICE_EXTENSION Extension; - ULONG CharsCopied; - BOOLEAN Completed; - } SERIAL_UPDATE_CHAR,*PSERIAL_UPDATE_CHAR; - -// -// The following simple structure is used to send a pointer -// the device extension and an ioctl specific pointer -// to data. -// -typedef struct _SERIAL_IOCTL_SYNC { - PSERIAL_DEVICE_EXTENSION Extension; - PVOID Data; - } SERIAL_IOCTL_SYNC,*PSERIAL_IOCTL_SYNC; - - -// -// The following three macros are used to initialize, set -// and clear references in IRPs that are used by -// this driver. The reference is stored in the fourth -// argument of the request, which is never used by any operation -// accepted by this driver. -// - -#define SERIAL_REF_ISR (0x00000001) -#define SERIAL_REF_CANCEL (0x00000002) -#define SERIAL_REF_TOTAL_TIMER (0x00000004) -#define SERIAL_REF_INT_TIMER (0x00000008) -#define SERIAL_REF_XOFF_REF (0x00000010) - - -#define SERIAL_INIT_REFERENCE(ReqContext) { \ - (ReqContext)->RefCount = NULL; \ - } - -#define SERIAL_SET_REFERENCE(ReqContext, RefType) \ - do { \ - LONG _refType = (RefType); \ - PULONG_PTR _arg4 = (PVOID)&(ReqContext)->RefCount; \ - ASSERT(!(*_arg4 & _refType)); \ - *_arg4 |= _refType; \ - } WHILE (0) - -#define SERIAL_CLEAR_REFERENCE(ReqContext, RefType) \ - do { \ - LONG _refType = (RefType); \ - PULONG_PTR _arg4 = (PVOID)&(ReqContext)->RefCount; \ - ASSERT(*_arg4 & _refType); \ - *_arg4 &= ~_refType; \ - } WHILE (0) - -#define SERIAL_REFERENCE_COUNT(ReqContext) \ - ((ULONG_PTR)(((ReqContext)->RefCount))) - -#define SERIAL_TEST_REFERENCE(ReqContext, RefType) ((ULONG_PTR)ReqContext ->RefCount & RefType) - -// -// Prototypes and defines to handle processor groups. -// -typedef -USHORT -(*PFN_KE_GET_ACTIVE_GROUP_COUNT)( - VOID - ); - -typedef -KAFFINITY -(*PFN_KE_QUERY_GROUP_AFFINITY) ( - _In_ USHORT GroupNumber - ); - -// -// Force the serial interrupt to run on the last interrupt group. -// -//#define SERIAL_SELECT_INTERRUPT_GROUP 1 -#define SERIAL_LAST_INTERRUPT_GROUP 0xFFFF -#define SERIAL_PREFERRED_INTERRUPT_GROUP SERIAL_LAST_INTERRUPT_GROUP - - - diff --git a/tests/projects/wdk/kmdf/serial/serlog.mc b/tests/projects/wdk/kmdf/serial/serlog.mc deleted file mode 100644 index ee6935b67..000000000 --- a/tests/projects/wdk/kmdf/serial/serlog.mc +++ /dev/null @@ -1,290 +0,0 @@ -;/*++ BUILD Version: 0001 // Increment this if a change has global effects -; -;Copyright (c) 1992, 1993 Microsoft Corporation -; -;Module Name: -; -; ntiologc.h -; -;Abstract: -; -; Constant definitions for the I/O error code log values. -; -;--*/ -; -;#ifndef _SERLOG_ -;#define _SERLOG_ -; -;// -;// Status values are 32 bit values layed out as follows: -;// -;// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 -;// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -;// +---+-+-------------------------+-------------------------------+ -;// |Sev|C| Facility | Code | -;// +---+-+-------------------------+-------------------------------+ -;// -;// where -;// -;// Sev - is the severity code -;// -;// 00 - Success -;// 01 - Informational -;// 10 - Warning -;// 11 - Error -;// -;// C - is the Customer code flag -;// -;// Facility - is the facility code -;// -;// Code - is the facility's status code -;// -; -MessageIdTypedef=NTSTATUS - -SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS - Informational=0x1:STATUS_SEVERITY_INFORMATIONAL - Warning=0x2:STATUS_SEVERITY_WARNING - Error=0x3:STATUS_SEVERITY_ERROR - ) - -FacilityNames=(System=0x0 - RpcRuntime=0x2:FACILITY_RPC_RUNTIME - RpcStubs=0x3:FACILITY_RPC_STUBS - Io=0x4:FACILITY_IO_ERROR_CODE - Serial=0x6:FACILITY_SERIAL_ERROR_CODE - ) - - -MessageId=0x0001 Facility=Serial Severity=Informational SymbolicName=SERIAL_KERNEL_DEBUGGER_ACTIVE -Language=English -The kernel debugger is already using %2. -. - -MessageId=0x0002 Facility=Serial Severity=Informational SymbolicName=SERIAL_FIFO_PRESENT -Language=English -While validating that %2 was really a serial port, a fifo was detected. The fifo will be used. -. - -MessageId=0x0003 Facility=Serial Severity=Informational SymbolicName=SERIAL_USER_OVERRIDE -Language=English -User configuration data for parameter %2 overriding firmware configuration data. -. - -MessageId=0x0004 Facility=Serial Severity=Warning SymbolicName=SERIAL_NO_SYMLINK_CREATED -Language=English -Unable to create the symbolic link for %2. -. - -MessageId=0x0005 Facility=Serial Severity=Warning SymbolicName=SERIAL_NO_DEVICE_MAP_CREATED -Language=English -Unable to create the device map entry for %2. -. - -MessageId=0x0006 Facility=Serial Severity=Warning SymbolicName=SERIAL_NO_DEVICE_MAP_DELETED -Language=English -Unable to delete the device map entry for %2. -. - -MessageId=0x0007 Facility=Serial Severity=Error SymbolicName=SERIAL_UNREPORTED_IRQL_CONFLICT -Language=English -Another driver on the system, which did not report its resources, has already claimed the interrupt used by %2. -. - -MessageId=0x0008 Facility=Serial Severity=Error SymbolicName=SERIAL_INSUFFICIENT_RESOURCES -Language=English -Not enough resources were available for the driver. -. - -MessageId=0x0009 Facility=Serial Severity=Error SymbolicName=SERIAL_UNSUPPORTED_CLOCK_RATE -Language=English -The baud clock rate configuration is not supported on device %2. -. - -MessageId=0x000A Facility=Serial Severity=Error SymbolicName=SERIAL_REGISTERS_NOT_MAPPED -Language=English -The hardware locations for %2 could not be translated to something the memory management system could understand. -. - -MessageId=0x000B Facility=Serial Severity=Error SymbolicName=SERIAL_RESOURCE_CONFLICT -Language=English -The hardware resources for %2 are already in use by another device. -. - -MessageId=0x000C Facility=Serial Severity=Error SymbolicName=SERIAL_NO_BUFFER_ALLOCATED -Language=English -No memory could be allocated in which to place new data for %2. -. - -MessageId=0x000D Facility=Serial Severity=Error SymbolicName=SERIAL_IER_INVALID -Language=English -While validating that %2 was really a serial port, the interrupt enable register contained enabled bits in a must be zero bitfield. -The device is assumed not to be a serial port and will be deleted. -. - -MessageId=0x000E Facility=Serial Severity=Error SymbolicName=SERIAL_MCR_INVALID -Language=English -While validating that %2 was really a serial port, the modem control register contained enabled bits in a must be zero bitfield. -The device is assumed not to be a serial port and will be deleted. -. - -MessageId=0x000F Facility=Serial Severity=Error SymbolicName=SERIAL_IIR_INVALID -Language=English -While validating that %2 was really a serial port, the interrupt id register contained enabled bits in a must be zero bitfield. -The device is assumed not to be a serial port and will be deleted. -. - -MessageId=0x0010 Facility=Serial Severity=Error SymbolicName=SERIAL_DL_INVALID -Language=English -While validating that %2 was really a serial port, the baud rate register could not be set consistantly. -The device is assumed not to be a serial port and will be deleted. -. - -MessageId=0x0011 Facility=Serial Severity=Error SymbolicName=SERIAL_NOT_ENOUGH_CONFIG_INFO -Language=English -Some firmware configuration information was incomplete. -. - -MessageId=0x0012 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_PARAMETERS_INFO -Language=English -No Parameters subkey was found for user defined data. This is odd, and it also means no user configuration can be found. -. - -MessageId=0x0013 Facility=Serial Severity=Error SymbolicName=SERIAL_UNABLE_TO_ACCESS_CONFIG -Language=English -Specific user configuration data is unretrievable. -. - -MessageId=0x0014 Facility=Serial Severity=Error SymbolicName=SERIAL_INVALID_PORT_INDEX -Language=English -On parameter %2 which indicates a multiport card, must have a port index specified greater than 0. -. - -MessageId=0x0015 Facility=Serial Severity=Error SymbolicName=SERIAL_PORT_INDEX_TOO_HIGH -Language=English -On parameter %2 which indicates a multiport card, the port index for the multiport card is too large. -. - -MessageId=0x0016 Facility=Serial Severity=Error SymbolicName=SERIAL_UNKNOWN_BUS -Language=English -The bus type for %2 is not recognizable. -. - -MessageId=0x0017 Facility=Serial Severity=Error SymbolicName=SERIAL_BUS_NOT_PRESENT -Language=English -The bus type for %2 is not available on this computer. -. - -MessageId=0x0018 Facility=Serial Severity=Error SymbolicName=SERIAL_BUS_INTERRUPT_CONFLICT -Language=English -The bus specified for %2 does not support the specified method of interrupt. -. - -MessageId=0x0019 Facility=Serial Severity=Error SymbolicName=SERIAL_INVALID_USER_CONFIG -Language=English -User configuration for parameter %2 must have %3. -. - -MessageId=0x001A Facility=Serial Severity=Error SymbolicName=SERIAL_DEVICE_TOO_HIGH -Language=English -The user specified port for %2 is way too high in physical memory. -. - -MessageId=0x001B Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_TOO_HIGH -Language=English -The status port for %2 is way too high in physical memory. -. - -MessageId=0x001C Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_CONTROL_CONFLICT -Language=English -The status port for %2 overlaps the control registers for the device. -. - -MessageId=0x001D Facility=Serial Severity=Error SymbolicName=SERIAL_CONTROL_OVERLAP -Language=English -The control registers for %2 overlaps with the %3 control registers. -. - -MessageId=0x001E Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_OVERLAP -Language=English -The status register for %2 overlaps the %3 control registers. -. - -MessageId=0x001F Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_STATUS_OVERLAP -Language=English -The status register for %2 overlaps with the %3 status register. -. - -MessageId=0x0020 Facility=Serial Severity=Error SymbolicName=SERIAL_CONTROL_STATUS_OVERLAP -Language=English -The control registers for %2 overlaps the %3 status register. -. - -MessageId=0x0021 Facility=Serial Severity=Error SymbolicName=SERIAL_MULTI_INTERRUPT_CONFLICT -Language=English -Two ports, %2 and %3, on a single multiport card can't have two different interrupts. -. - -MessageId=0x0022 Facility=Serial Severity=Informational SymbolicName=SERIAL_DISABLED_PORT -Language=English -Disabling %2 as requested by the configuration data. -. - -MessageId=0x0023 Facility=Serial Severity=Error SymbolicName=SERIAL_GARBLED_PARAMETER -Language=English -Parameter %2 data is unretrievable from the registry. -. - -MessageId=0x0024 Facility=Serial Severity=Error SymbolicName=SERIAL_DLAB_INVALID -Language=English -While validating that %2 was really a serial port, the contents of the divisor latch register was identical to the interrupt enable and the receive registers. -The device is assumed not to be a serial port and will be deleted. -. - -MessageId=0x0025 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_TRANSLATE_PORT -Language=English -Could not translate the user reported I/O port for %2. -. - -MessageId=0x0026 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_GET_INTERRUPT -Language=English -Could not get the user reported interrupt for %2 from the HAL. -. - -MessageId=0x0027 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_TRANSLATE_ISR -Language=English -Could not translate the user reported Interrupt Status Register for %2. -. - -MessageId=0x0028 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_DEVICE_REPORT -Language=English -Could not report the discovered legacy device %2 to the IO subsystem. -. - -MessageId=0x0029 Facility=Serial Severity=Error SymbolicName=SERIAL_REGISTRY_WRITE_FAILED -Language=English -Error writing to the registry. -. - -MessageId=0x002A Facility=Serial Severity=Warning SymbolicName=SERIAL_MOUSE_CONFLICT_IRQ -Language=English -There is a serial mouse using the same interrupt as %2. Therefore, %2 will not be started. -. - -MessageId=0x002B Facility=Serial Severity=Warning SymbolicName=SERIAL_MOUSE_ON_PORT -Language=English -There was a serial mouse found on %2. Therefore, %2 will be assigned to the mouse. -. - -MessageId=0x002C Facility=Serial Severity=Error SymbolicName=SERIAL_NO_DEVICE_REPORT_RES -Language=English -Could not report device %2 to IO subsystem due to a resource conflict. -. - -MessageId=0x002D Facility=Serial Severity=Error SymbolicName=SERIAL_HARDWARE_FAILURE -Language=English -The serial driver detected a hardware failure on device %2 and will disable this device. -. - -;#endif /* _NTIOLOGC_ */ - diff --git a/tests/projects/wdk/kmdf/serial/trace.h b/tests/projects/wdk/kmdf/serial/trace.h deleted file mode 100644 index 5bd9d50ca..000000000 --- a/tests/projects/wdk/kmdf/serial/trace.h +++ /dev/null @@ -1,118 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - TRACE.h - -Abstract: - - Header file for the debug tracing related function defintions and macros. - -Environment: - - Kernel mode - ---*/ - -#include // For TRACE_LEVEL definitions - -#if !defined(EVENT_TRACING) - -// -// TODO: These defines are missing in evntrace.h -// in some DDK build environments (XP). -// -#if !defined(TRACE_LEVEL_NONE) - #define TRACE_LEVEL_NONE 0 - #define TRACE_LEVEL_CRITICAL 1 - #define TRACE_LEVEL_FATAL 1 - #define TRACE_LEVEL_ERROR 2 - #define TRACE_LEVEL_WARNING 3 - #define TRACE_LEVEL_INFORMATION 4 - #define TRACE_LEVEL_VERBOSE 5 - #define TRACE_LEVEL_RESERVED6 6 - #define TRACE_LEVEL_RESERVED7 7 - #define TRACE_LEVEL_RESERVED8 8 - #define TRACE_LEVEL_RESERVED9 9 -#endif - - -// -// Define Debug Flags -// -#define DBG_INIT 0x00000001 -#define DBG_PNP 0x00000002 -#define DBG_POWER 0x00000004 -#define DBG_WMI 0x00000008 -#define DBG_CREATE_CLOSE 0x00000010 -#define DBG_IOCTLS 0x00000020 -#define DBG_WRITE 0x00000040 -#define DBG_READ 0x00000080 -#define DBG_DPC 0x00000100 -#define DBG_INTERRUPT 0x00000200 -#define DBG_LOCKS 0x00000400 -#define DBG_QUEUEING 0x00000800 -#define DBG_HW_ACCESS 0x00001000 - -VOID -TraceEvents ( - IN ULONG DebugPrintLevel, - IN ULONG DebugPrintFlag, - IN PCCHAR DebugMessage, - ... - ); - -#define WPP_INIT_TRACING(DriverObject, RegistryPath) -#define WPP_CLEANUP(DriverObject) - -#else -// -// If software tracing is defined in the sources file.. -// WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver. -// *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID *** -// WPP_DEFINE_BIT allows setting debug bit masks to selectively print. -// The names defined in the WPP_DEFINE_BIT call define the actual names -// that are used to control the level of tracing for the control guid -// specified. -// -// Name of the logger is Serial and the guid is -// {F3A79AB6-9827-4419-9465-45CF949EF659} -// (0xf3a79ab6, 0x9827, 0x4419, 0x94, 0x65, 0x45, 0xcf, 0x94, 0x9e, 0xf6, 0x59); -// - -#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings - -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID(SerialTraceGuid,(bc6c9364,fc67,42c5,acf7,abed3b12ecc6), \ - WPP_DEFINE_BIT(DBG_INIT) /* bit 0 = 0x00000001 */ \ - WPP_DEFINE_BIT(DBG_PNP) /* bit 1 = 0x00000002 */ \ - WPP_DEFINE_BIT(DBG_POWER) /* bit 2 = 0x00000004 */ \ - WPP_DEFINE_BIT(DBG_WMI) /* bit 3 = 0x00000008 */ \ - WPP_DEFINE_BIT(DBG_CREATE_CLOSE) /* bit 4 = 0x00000010 */ \ - WPP_DEFINE_BIT(DBG_IOCTLS) /* bit 5 = 0x00000020 */ \ - WPP_DEFINE_BIT(DBG_WRITE) /* bit 6 = 0x00000040 */ \ - WPP_DEFINE_BIT(DBG_READ) /* bit 7 = 0x00000080 */ \ - WPP_DEFINE_BIT(DBG_DPC) /* bit 8 = 0x00000100 */ \ - WPP_DEFINE_BIT(DBG_INTERRUPT) /* bit 9 = 0x00000200 */ \ - WPP_DEFINE_BIT(DBG_LOCKS) /* bit 10 = 0x00000400 */ \ - WPP_DEFINE_BIT(DBG_QUEUEING) /* bit 11 = 0x00000800 */ \ - WPP_DEFINE_BIT(DBG_HW_ACCESS) /* bit 12 = 0x00001000 */ \ - /* You can have up to 32 defines. If you want more than that,\ - you have to provide another trace control GUID */\ - ) - - -#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) -#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) - - -#endif - - diff --git a/tests/projects/wdk/kmdf/serial/utils.c b/tests/projects/wdk/kmdf/serial/utils.c deleted file mode 100644 index a84136efe..000000000 --- a/tests/projects/wdk/kmdf/serial/utils.c +++ /dev/null @@ -1,1946 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - utils.c - -Abstract: - - This module contains code that perform queueing and completion - manipulation on requests. Also module generic functions such - as error logging. - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "utils.tmh" -#endif - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGESRP0,SerialMemCompare) -#pragma alloc_text(PAGESRP0,SerialLogError) -#pragma alloc_text(PAGESRP0,SerialMarkHardwareBroken) -#endif // ALLOC_PRAGMA - - -VOID -SerialRundownIrpRefs( - IN WDFREQUEST *CurrentOpRequest, - IN WDFTIMER IntervalTimer, - IN WDFTIMER TotalTimer, - IN PSERIAL_DEVICE_EXTENSION PDevExt, - IN LONG RefType - ); - -static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; - -VOID -SerialPurgeRequests( - IN WDFQUEUE QueueToClean, - IN WDFREQUEST *CurrentOpRequest - ) - -/*++ - -Routine Description: - - This function is used to cancel all queued and the current irps - for reads or for writes. Called at DPC level. - -Arguments: - - QueueToClean - A pointer to the queue which we're going to clean out. - - CurrentOpRequest - Pointer to a pointer to the current request. - -Return Value: - - None. - ---*/ - -{ - NTSTATUS status; - PREQUEST_CONTEXT reqContext; - - WdfIoQueuePurge(QueueToClean, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); - - // - // The queue is clean. Now go after the current if - // it's there. - // - - if (*CurrentOpRequest) { - - PFN_WDF_REQUEST_CANCEL CancelRoutine; - - reqContext = SerialGetRequestContext(*CurrentOpRequest); - CancelRoutine = reqContext->CancelRoutine; - // - // Clear the common cancel routine but don't clear the reference because the - // request specific cancel routine called below will clear the reference. - // - status = SerialClearCancelRoutine(*CurrentOpRequest, FALSE); - if (NT_SUCCESS(status)) { - // - // Let us just call the CancelRoutine to start the next request. - // - if(CancelRoutine) { - CancelRoutine(*CurrentOpRequest); - } - } - } -} - -VOID -SerialFlushRequests( - IN WDFQUEUE QueueToClean, - IN WDFREQUEST *CurrentOpRequest - ) - -/*++ - -Routine Description: - - This function is used to cancel all queued and the current irps - for reads or for writes. Called at DPC level. - -Arguments: - - QueueToClean - A pointer to the queue which we're going to clean out. - - CurrentOpRequest - Pointer to a pointer to the current request. - -Return Value: - - None. - ---*/ - -{ - SerialPurgeRequests(QueueToClean, CurrentOpRequest); - - // - // Since purge puts the queue state to fail requests, we have to explicitly - // change the queue state to accept requests. - // - WdfIoQueueStart(QueueToClean); - -} - - -VOID -SerialGetNextRequest( - IN WDFREQUEST * CurrentOpRequest, - IN WDFQUEUE QueueToProcess, - OUT WDFREQUEST * NextRequest, - IN BOOLEAN CompleteCurrent, - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - This function is used to make the head of the particular - queue the current request. It also completes the what - was the old current request if desired. - -Arguments: - - CurrentOpRequest - Pointer to a pointer to the currently active - request for the particular work list. Note that - this item is not actually part of the list. - - QueueToProcess - The list to pull the new item off of. - - NextIrp - The next Request to process. Note that CurrentOpRequest - will be set to this value under protection of the - cancel spin lock. However, if *NextIrp is NULL when - this routine returns, it is not necessaryly true the - what is pointed to by CurrentOpRequest will also be NULL. - The reason for this is that if the queue is empty - when we hold the cancel spin lock, a new request may come - in immediately after we release the lock. - - CompleteCurrent - If TRUE then this routine will complete the - request pointed to by the pointer argument - CurrentOpRequest. - -Return Value: - - None. - ---*/ - -{ - WDFREQUEST oldRequest = NULL; - PREQUEST_CONTEXT reqContext; - NTSTATUS status; - - UNREFERENCED_PARAMETER(Extension); - - oldRequest = *CurrentOpRequest; - *CurrentOpRequest = NULL; - - // - // Check to see if there is a new request to start up. - // - - status = WdfIoQueueRetrieveNextRequest( - QueueToProcess, - CurrentOpRequest - ); - - if(!NT_SUCCESS(status)) { - ASSERTMSG("WdfIoQueueRetrieveNextRequest failed", - status == STATUS_NO_MORE_ENTRIES); - } - - *NextRequest = *CurrentOpRequest; - - if (CompleteCurrent) { - - if (oldRequest) { - - reqContext = SerialGetRequestContext(oldRequest); - - SerialCompleteRequest(oldRequest, - reqContext->Status, - reqContext->Information); - } - } -} - -VOID -SerialTryToCompleteCurrent( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN PFN_WDF_INTERRUPT_SYNCHRONIZE SynchRoutine OPTIONAL, - IN NTSTATUS StatusToUse, - IN WDFREQUEST *CurrentOpRequest, - IN WDFQUEUE QueueToProcess OPTIONAL, - IN WDFTIMER IntervalTimer OPTIONAL, - IN WDFTIMER TotalTimer OPTIONAL, - IN PSERIAL_START_ROUTINE Starter OPTIONAL, - IN PSERIAL_GET_NEXT_ROUTINE GetNextRequest OPTIONAL, - IN LONG RefType - ) - -/*++ - -Routine Description: - - This routine attempts to remove all of the reasons there are - references on the current read/write. If everything can be completed - it will complete this read/write and try to start another. - - NOTE: This routine assumes that it is called with the cancel - spinlock held. - -Arguments: - - Extension - Simply a pointer to the device extension. - - SynchRoutine - A routine that will synchronize with the isr - and attempt to remove the knowledge of the - current request from the isr. NOTE: This pointer - can be null. - - IrqlForRelease - This routine is called with the cancel spinlock held. - This is the irql that was current when the cancel - spinlock was acquired. - - StatusToUse - The request's status field will be set to this value, if - this routine can complete the request. - - -Return Value: - - None. - ---*/ - -{ - PREQUEST_CONTEXT reqContext; - - ASSERTMSG("SerialTryToCompleteCurrent: CurrentOpRequest is NULL", *CurrentOpRequest); - - reqContext = SerialGetRequestContext(*CurrentOpRequest); - - if(RefType == SERIAL_REF_ISR || RefType == SERIAL_REF_XOFF_REF) { - // - // We can decrement the reference to "remove" the fact - // that the caller no longer will be accessing this request. - // - - SERIAL_CLEAR_REFERENCE( - reqContext, - RefType - ); - } - - if (SynchRoutine) { - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SynchRoutine, - Extension - ); - - } - - // - // Try to run down all other references to this request. - // - - SerialRundownIrpRefs( - CurrentOpRequest, - IntervalTimer, - TotalTimer, - Extension, - RefType - ); - - if(StatusToUse == STATUS_CANCELLED) { - // - // This function is called from a cancelroutine. So mark - // the request as cancelled. We need to do this because - // we may not complete the request below if somebody - // else has a reference to it. - // This state variable was added to avoid calling - // WdfRequestMarkCancelable second time on a request that - // has cancelled but wasn't completed in the cancel routine. - // - reqContext->Cancelled = TRUE; - } - - // - // See if the ref count is zero after trying to complete everybody else. - // - - if (!SERIAL_REFERENCE_COUNT(reqContext)) { - - WDFREQUEST newRequest; - - - // - // The ref count was zero so we should complete this - // request. - // - // The following call will also cause the current request to be - // completed. - // - - reqContext->Status = StatusToUse; - - if (StatusToUse == STATUS_CANCELLED) { - - reqContext->Information = 0; - - } - - if (GetNextRequest) { - - GetNextRequest( - CurrentOpRequest, - QueueToProcess, - &newRequest, - TRUE, - Extension - ); - - if (newRequest) { - - Starter(Extension); - - } - - } else { - - WDFREQUEST oldRequest = *CurrentOpRequest; - - // - // There was no get next routine. We will simply complete - // the request. We should make sure that we null out the - // pointer to the pointer to this request. - // - - *CurrentOpRequest = NULL; - - SerialCompleteRequest(oldRequest, - reqContext->Status, - reqContext->Information); - } - - } else { - - - } - -} - - -VOID -SerialEvtIoStop( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN ULONG ActionFlags - ) -/*++ - -Routine Description: - - This callback is invoked for every request pending in the driver (not queue) - - in-flight request. The Action parameter tells us why the callback is invoked - - because the device is being stopped, removed or suspended. In this - driver, we have told the framework not to stop or remove when there - are pending requests, so only reason for this callback is when the system is - suspending. - -Arguments: - - Queue - Queue the request currently belongs to - Request - Request that is currently out of queue and being processed by the driver - Action - Reason for this callback - -Return Value: - - None. Acknowledge the request so that framework can contiue suspending the - device. - ---*/ -{ - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Queue); - - reqContext = SerialGetRequestContext(Request); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, - "--> SerialEvtIoStop %x %p\n", ActionFlags, Request); - - // - // System suspends all the timers before asking the driver to goto - // sleep. So let us not worry about cancelling the timers. Also the - // framework will disconnect the interrupt before calling our - // D0Exit handler so we can be sure that nobody will touch the hardware. - // So just acknowledge callback to say that we are okay to stop due to - // system suspend. Please note that since we have taken a power reference - // we will never idle out when there is an open handle. Also we have told - // the framework to not stop for resource rebalancing or remove when there are - // open handles, so let us not worry about that either. - // - if (ActionFlags & WdfRequestStopRequestCancelable) { - PFN_WDF_REQUEST_CANCEL cancelRoutine; - - // - // Request is in a cancelable state. So unmark cancelable before you - // acknowledge. We will mark the request cancelable when we resume. - // - cancelRoutine = reqContext->CancelRoutine; - - SerialClearCancelRoutine(Request, TRUE); - - // - // SerialClearCancelRoutine clears the cancel-routine. So set it back - // in the context. We will need that when we resume. - // - reqContext->CancelRoutine = cancelRoutine; - - reqContext->MarkCancelableOnResume = TRUE; - - ActionFlags &= ~WdfRequestStopRequestCancelable; - } - - ASSERT(ActionFlags == WdfRequestStopActionSuspend); - - WdfRequestStopAcknowledge(Request, FALSE); // Don't requeue the request - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, - "<-- SerialEvtIoStop \n"); -} - -VOID -SerialEvtIoResume( - IN WDFQUEUE Queue, - IN WDFREQUEST Request - ) -/*++ - -Routine Description: - - This callback is invoked for every request pending in the driver - in-flight - request - to notify that the hardware is ready for contiuing the processing - of the request. - -Arguments: - - Queue - Queue the request currently belongs to - Request - Request that is currently out of queue and being processed by the driver - -Return Value: - - None. - ---*/ -{ - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Queue); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, - "--> SerialEvtIoResume %p \n", Request); - - reqContext = SerialGetRequestContext(Request); - - // - // If we unmarked cancelable on suspend, let us mark it cancelable again. - // - if (reqContext->MarkCancelableOnResume) { - SerialSetCancelRoutine(Request, reqContext->CancelRoutine); - reqContext->MarkCancelableOnResume = FALSE; - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, - "<-- SerialEvtIoResume \n"); -} - -VOID -SerialRundownIrpRefs( - IN WDFREQUEST *CurrentOpRequest, - IN WDFTIMER IntervalTimer OPTIONAL, - IN WDFTIMER TotalTimer OPTIONAL, - IN PSERIAL_DEVICE_EXTENSION PDevExt, - IN LONG RefType - ) - -/*++ - -Routine Description: - - This routine runs through the various items that *could* - have a reference to the current read/write. It try's to remove - the reason. If it does succeed in removing the reason it - will decrement the reference count on the request. - - NOTE: This routine assumes that it is called with the cancel - spin lock held. - -Arguments: - - CurrentOpRequest - Pointer to a pointer to current request for the - particular operation. - - IntervalTimer - Pointer to the interval timer for the operation. - NOTE: This could be null. - - TotalTimer - Pointer to the total timer for the operation. - NOTE: This could be null. - - PDevExt - Pointer to device extension - -Return Value: - - None. - ---*/ - - -{ - PREQUEST_CONTEXT reqContext; - WDFREQUEST request = *CurrentOpRequest; - - reqContext = SerialGetRequestContext(request); - - if(RefType == SERIAL_REF_CANCEL) { - // - // Caller is a cancel routine. So just clear the reference. - // - SERIAL_CLEAR_REFERENCE( reqContext, SERIAL_REF_CANCEL ); - reqContext->CancelRoutine = NULL; - - } else { - // - // Try to clear the cancelable state. - // - SerialClearCancelRoutine(request, TRUE); - } - if (IntervalTimer) { - - // - // Try to cancel the operations interval timer. If the operation - // returns true then the timer did have a reference to the - // request. Since we've canceled this timer that reference is - // no longer valid and we can decrement the reference count. - // - // If the cancel returns false then this means either of two things: - // - // a) The timer has already fired. - // - // b) There never was an interval timer. - // - // In the case of "b" there is no need to decrement the reference - // count since the "timer" never had a reference to it. - // - // In the case of "a", then the timer itself will be coming - // along and decrement it's reference. Note that the caller - // of this routine might actually be the this timer, so - // decrement the reference. - // - - if (SerialCancelTimer(IntervalTimer, PDevExt)) { - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_INT_TIMER - ); - - } else if(RefType == SERIAL_REF_INT_TIMER) { // caller is the timer - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_INT_TIMER - ); - } - - } - - if (TotalTimer) { - - // - // Try to cancel the operations total timer. If the operation - // returns true then the timer did have a reference to the - // request. Since we've canceled this timer that reference is - // no longer valid and we can decrement the reference count. - // - // If the cancel returns false then this means either of two things: - // - // a) The timer has already fired. - // - // b) There never was an total timer. - // - // In the case of "b" there is no need to decrement the reference - // count since the "timer" never had a reference to it. - // - // In the case of "a", then the timer itself will be coming - // along and decrement it's reference. Note that the caller - // of this routine might actually be the this timer, so - // decrement the reference. - // - - if (SerialCancelTimer(TotalTimer, PDevExt)) { - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_TOTAL_TIMER - ); - - } else if(RefType == SERIAL_REF_TOTAL_TIMER) { // caller is the timer - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_TOTAL_TIMER - ); - } - } -} - - -VOID -SerialStartOrQueue( - IN PSERIAL_DEVICE_EXTENSION Extension, - IN WDFREQUEST Request, - IN WDFQUEUE QueueToExamine, - IN WDFREQUEST *CurrentOpRequest, - IN PSERIAL_START_ROUTINE Starter - ) - -/*++ - -Routine Description: - - This routine is used to either start or queue any requst - that can be queued in the driver. - -Arguments: - - Extension - Points to the serial device extension. - - Request - The request to either queue or start. In either - case the request will be marked pending. - - QueueToExamine - The queue the request will be place on if there - is already an operation in progress. - - CurrentOpRequest - Pointer to a pointer to the request the is current - for the queue. The pointer pointed to will be - set with to Request if what CurrentOpRequest points to - is NULL. - - Starter - The routine to call if the queue is empty. - -Return Value: - - ---*/ - -{ - - NTSTATUS status; - PREQUEST_CONTEXT reqContext; - WDF_REQUEST_PARAMETERS params; - - reqContext = SerialGetRequestContext(Request); - - WDF_REQUEST_PARAMETERS_INIT(¶ms); - - WdfRequestGetParameters( - Request, - ¶ms); - - // - // If this is a write request then take the amount of characters - // to write and add it to the count of characters to write. - // - - if (params.Type == WdfRequestTypeWrite) { - - Extension->TotalCharsQueued += reqContext->Length; - - } else if ((params.Type == WdfRequestTypeDeviceControl) && - ((params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) || - (params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER))) { - - reqContext->IoctlCode = params.Parameters.DeviceIoControl.IoControlCode; // We need this in the destroy callback - - Extension->TotalCharsQueued++; - - } - - if (IsQueueEmpty(QueueToExamine) && !(*CurrentOpRequest)) { - - // - // There were no current operation. Mark this one as - // current and start it up. - // - - *CurrentOpRequest = Request; - - Starter(Extension); - - return; - - } else { - - // - // We don't know how long the request will be in the - // queue. If it gets cancelled while waiting in the queue, we will - // be notified by EvtCanceledOnQueue callback so that we can readjust - // the lenght or free the buffer. - // - reqContext->Extension = Extension; // We need this in the destroy callback - - status = WdfRequestForwardToIoQueue(Request, QueueToExamine); - if(!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestForwardToIoQueue failed%X\n", status); - ASSERTMSG("WdfRequestForwardToIoQueue failed ", FALSE); - SerialCompleteRequest(Request, status, 0); - } - - return; - } -} - -VOID -SerialEvtCanceledOnQueue( - IN WDFQUEUE Queue, - IN WDFREQUEST Request - ) - -/*++ - -Routine Description: - - Called when the request is cancelled while it's waiting - on the queue. This callback is used instead of EvtCleanupCallback - on the request because this one will be called with the - presentation lock held. - - -Arguments: - - Queue - Queue in which the request currently waiting - Request - Request being cancelled - - -Return Value: - - None. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION extension = NULL; - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Queue); - - reqContext = SerialGetRequestContext(Request); - - extension = reqContext->Extension; - - // - // If this is a write request then take the amount of characters - // to write and subtract it from the count of characters to write. - // - - if (reqContext->MajorFunction == IRP_MJ_WRITE) { - - extension->TotalCharsQueued -= reqContext->Length; - - } else if (reqContext->MajorFunction == IRP_MJ_DEVICE_CONTROL) { - - // - // If it's an immediate then we need to decrement the - // count of chars queued. If it's a resize then we - // need to deallocate the pool that we're passing on - // to the "resizing" routine. - // - - if (( reqContext->IoctlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) || - (reqContext->IoctlCode == IOCTL_SERIAL_XOFF_COUNTER)) { - - extension->TotalCharsQueued--; - - } else if (reqContext->IoctlCode == IOCTL_SERIAL_SET_QUEUE_SIZE) { - - // - // We shoved the pointer to the memory into the - // the type 3 buffer pointer which we KNOW we - // never use. - // - - ASSERT(reqContext->Type3InputBuffer); - - ExFreePool(reqContext->Type3InputBuffer); - - reqContext->Type3InputBuffer = NULL; - - } - - } - - SerialCompleteRequest(Request, WdfRequestGetStatus(Request), 0); -} - - -NTSTATUS -SerialCompleteIfError( - PSERIAL_DEVICE_EXTENSION extension, - WDFREQUEST Request - ) - -/*++ - -Routine Description: - - If the current request is not an IOCTL_SERIAL_GET_COMMSTATUS request and - there is an error and the application requested abort on errors, - then cancel the request. - -Arguments: - - extension - Pointer to the device context - - Request - Pointer to the WDFREQUEST to test. - -Return Value: - - STATUS_SUCCESS or STATUS_CANCELLED. - ---*/ - -{ - - WDF_REQUEST_PARAMETERS params; - NTSTATUS status = STATUS_SUCCESS; - - if ((extension->HandFlow.ControlHandShake & - SERIAL_ERROR_ABORT) && extension->ErrorWord) { - - WDF_REQUEST_PARAMETERS_INIT(¶ms); - - WdfRequestGetParameters( - Request, - ¶ms - ); - - - // - // There is a current error in the driver. No requests should - // come through except for the GET_COMMSTATUS. - // - - if ((params.Type != WdfRequestTypeDeviceControl) || - (params.Parameters.DeviceIoControl.IoControlCode != IOCTL_SERIAL_GET_COMMSTATUS)) { - status = STATUS_CANCELLED; - SerialCompleteRequest(Request, status, 0); - } - - } - - return status; - -} - -NTSTATUS -SerialCreateTimersAndDpcs( - IN PSERIAL_DEVICE_EXTENSION pDevExt - ) -/*++ - -Routine Description: - - This function creates all the timers and DPC objects. All the objects - are associated with the WDFDEVICE and the callbacks are serialized - with the device callbacks. Also these objects will be deleted automatically - when the device is deleted, so there is no need for the driver to explicitly - delete the objects. - -Arguments: - - PDevExt - Pointer to the device extension for the device - -Return Value: - - return NTSTATUS - ---*/ -{ - WDF_DPC_CONFIG dpcConfig; - WDF_TIMER_CONFIG timerConfig; - NTSTATUS status; - WDF_OBJECT_ATTRIBUTES dpcAttributes; - WDF_OBJECT_ATTRIBUTES timerAttributes; - - // - // Initialize all the timers used to timeout operations. - // - // - // This timer dpc is fired off if the timer for the total timeout - // for the read expires. It will cause the current read to complete. - // - - WDF_TIMER_CONFIG_INIT(&timerConfig, SerialReadTimeout); - - timerConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &pDevExt->ReadRequestTotalTimer); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ReadRequestTotalTimer) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if the timer for the interval timeout - // expires. If no more characters have been read then the - // dpc routine will cause the read to complete. However, if - // more characters have been read then the dpc routine will - // resubmit the timer. - // - WDF_TIMER_CONFIG_INIT(&timerConfig, SerialIntervalReadTimeout); - - timerConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &pDevExt->ReadRequestIntervalTimer); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ReadRequestIntervalTimer) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if the timer for the total timeout - // for the write expires. It will queue a dpc routine that - // will cause the current write to complete. - // - // - - WDF_TIMER_CONFIG_INIT(&timerConfig, SerialWriteTimeout); - - timerConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &pDevExt->WriteRequestTotalTimer); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(WriteRequestTotalTimer) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if the transmit immediate char - // character times out. The dpc routine will "grab" the - // request from the isr and time it out. - // - WDF_TIMER_CONFIG_INIT(&timerConfig, SerialTimeoutImmediate); - - timerConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &pDevExt->ImmediateTotalTimer); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ImmediateTotalTimer) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if the timer used to "timeout" counting - // the number of characters received after the Xoff ioctl is started - // expired. - // - - WDF_TIMER_CONFIG_INIT(&timerConfig, SerialTimeoutXoff); - - timerConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &pDevExt->XoffCountTimer); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(XoffCountTimer) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off when a timer expires (after one - // character time), so that code can be invoked that will - // check to see if we should lower the RTS line when - // doing transmit toggling. - // - WDF_TIMER_CONFIG_INIT(&timerConfig, SerialInvokePerhapsLowerRTS); - - timerConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfTimerCreate(&timerConfig, - &timerAttributes, - &pDevExt->LowerRTSTimer); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(LowerRTSTimer) failed [%#08lx]\n", status); - return status; - } - - // - // Create a DPC to complete read requests. - // - - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteWrite); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->CompleteWriteDpc); - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteWriteDpc) failed [%#08lx]\n", status); - return status; - } - - - // - // Create a DPC to complete read requests. - // - - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteRead); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->CompleteReadDpc); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteReadDpc) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if a comm error occurs. It will - // cancel all pending reads and writes. - // - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCommError); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->CommErrorDpc); - - - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CommErrorDpc) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off when the transmit immediate char - // character is given to the hardware. It will simply complete - // the request. - // - - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteImmediate); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->CompleteImmediateDpc); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteImmediateDpc) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if an event occurs and there was - // a request waiting on that event. A dpc routine will execute - // that completes the request. - // - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteWait); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->CommWaitDpc); - if (!NT_SUCCESS(status)) { - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CommWaitDpc) failed [%#08lx]\n", status); - return status; - } - - // - // This dpc is fired off if the xoff counter actually runs down - // to zero. - // - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteXoff); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->XoffCountCompleteDpc); - - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(XoffCountCompleteDpc) failed [%#08lx]\n", status); - return status; - } - - - // - // This dpc is fired off only from device level to start off - // a timer that will queue a dpc to check if the RTS line - // should be lowered when we are doing transmit toggling. - // - WDF_DPC_CONFIG_INIT(&dpcConfig, SerialStartTimerLowerRTS); - - dpcConfig.AutomaticSerialization = TRUE; - - WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); - dpcAttributes.ParentObject = pDevExt->WdfDevice; - - status = WdfDpcCreate(&dpcConfig, - &dpcAttributes, - &pDevExt->StartTimerLowerRTSDpc); - if (!NT_SUCCESS(status)) { - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(StartTimerLowerRTSDpc) failed [%#08lx]\n", status); - return status; - } - - return status; -} - - - - -BOOLEAN -SerialInsertQueueDpc(IN WDFDPC PDpc) -/*++ - -Routine Description: - - This function must be called to queue DPC's for the serial driver. - -Arguments: - - PDpc - Pointer to the Dpc object - -Return Value: - - Kicks up return value from KeInsertQueueDpc() - ---*/ -{ - // - // If the specified DPC object is not currently in the queue, WdfDpcEnqueue - // queues the DPC and returns TRUE. - // - - return WdfDpcEnqueue(PDpc); -} - - - -BOOLEAN -SerialSetTimer(IN WDFTIMER Timer, IN LARGE_INTEGER DueTime) -/*++ - -Routine Description: - - This function must be called to set timers for the serial driver. - -Arguments: - - Timer - pointer to timer dispatcher object - - DueTime - time at which the timer should expire - - -Return Value: - - Kicks up return value from KeSetTimerEx() - ---*/ -{ - BOOLEAN result; - // - // If the timer object was already in the system timer queue, WdfTimerStart returns TRUE - // - result = WdfTimerStart(Timer, DueTime.QuadPart); - - return result; - -} - - -VOID -SerialDrainTimersAndDpcs( - IN PSERIAL_DEVICE_EXTENSION PDevExt - ) -/*++ - -Routine Description: - - This function cancels all the timers and Dpcs and waits for them - to run to completion if they are already fired. - -Arguments: - - PDevExt - Pointer to the device extension for the device that needs to - set a timer - -Return Value: - ---*/ -{ - WdfTimerStop(PDevExt->ReadRequestTotalTimer, TRUE); - - WdfTimerStop(PDevExt->ReadRequestIntervalTimer, TRUE); - - WdfTimerStop(PDevExt->WriteRequestTotalTimer, TRUE); - - WdfTimerStop(PDevExt->ImmediateTotalTimer, TRUE); - - WdfTimerStop(PDevExt->XoffCountTimer, TRUE); - - WdfTimerStop(PDevExt->LowerRTSTimer, TRUE); - - WdfDpcCancel(PDevExt->CompleteWriteDpc, TRUE); - - WdfDpcCancel(PDevExt->CompleteReadDpc, TRUE); - - WdfDpcCancel(PDevExt->CommErrorDpc, TRUE); - - WdfDpcCancel(PDevExt->CompleteImmediateDpc, TRUE); - - WdfDpcCancel(PDevExt->CommWaitDpc, TRUE); - - WdfDpcCancel(PDevExt->XoffCountCompleteDpc, TRUE); - - WdfDpcCancel(PDevExt->StartTimerLowerRTSDpc, TRUE); - - return; -} - - - -BOOLEAN -SerialCancelTimer( - IN WDFTIMER Timer, - IN PSERIAL_DEVICE_EXTENSION PDevExt - ) -/*++ - -Routine Description: - - This function must be called to cancel timers for the serial driver. - -Arguments: - - Timer - pointer to timer dispatcher object - - PDevExt - Pointer to the device extension for the device that needs to - set a timer - -Return Value: - - True if timer was cancelled - ---*/ -{ - UNREFERENCED_PARAMETER(PDevExt); - - return WdfTimerStop(Timer, FALSE); -} - -SERIAL_MEM_COMPARES -SerialMemCompare( - IN PHYSICAL_ADDRESS A, - IN ULONG SpanOfA, - IN PHYSICAL_ADDRESS B, - IN ULONG SpanOfB - ) -/*++ - -Routine Description: - - Compare two phsical address. - -Arguments: - - A - One half of the comparison. - - SpanOfA - In units of bytes, the span of A. - - B - One half of the comparison. - - SpanOfB - In units of bytes, the span of B. - - -Return Value: - - The result of the comparison. - ---*/ -{ - LARGE_INTEGER a; - LARGE_INTEGER b; - - LARGE_INTEGER lower; - ULONG lowerSpan; - LARGE_INTEGER higher; - - PAGED_CODE(); - - a = A; - b = B; - - if (a.QuadPart == b.QuadPart) { - - return AddressesAreEqual; - - } - - if (a.QuadPart > b.QuadPart) { - - higher = a; - lower = b; - lowerSpan = SpanOfB; - - } else { - - higher = b; - lower = a; - lowerSpan = SpanOfA; - - } - - if ((higher.QuadPart - lower.QuadPart) >= lowerSpan) { - - return AddressesAreDisjoint; - - } - - return AddressesOverlap; - -} - - -VOID -SerialLogError( - _In_ PDRIVER_OBJECT DriverObject, - _In_opt_ PDEVICE_OBJECT DeviceObject, - _In_ PHYSICAL_ADDRESS P1, - _In_ PHYSICAL_ADDRESS P2, - _In_ ULONG SequenceNumber, - _In_ UCHAR MajorFunctionCode, - _In_ UCHAR RetryCount, - _In_ ULONG UniqueErrorValue, - _In_ NTSTATUS FinalStatus, - _In_ NTSTATUS SpecificIOStatus, - _In_ ULONG LengthOfInsert1, - _In_reads_bytes_opt_(LengthOfInsert1) PWCHAR Insert1, - _In_ ULONG LengthOfInsert2, - _In_reads_bytes_opt_(LengthOfInsert2) PWCHAR Insert2 - ) -/*++ - -Routine Description: - - This routine allocates an error log entry, copies the supplied data - to it, and requests that it be written to the error log file. - -Arguments: - - DriverObject - A pointer to the driver object for the device. - - DeviceObject - A pointer to the device object associated with the - device that had the error, early in initialization, one may not - yet exist. - - P1,P2 - If phyical addresses for the controller ports involved - with the error are available, put them through as dump data. - - SequenceNumber - A ulong value that is unique to an WDFREQUEST over the - life of the request in this driver - 0 generally means an error not - associated with an request. - - MajorFunctionCode - If there is an error associated with the request, - this is the major function code of that request. - - RetryCount - The number of times a particular operation has been - retried. - - UniqueErrorValue - A unique long word that identifies the particular - call to this function. - - FinalStatus - The final status given to the request that was associated - with this error. If this log entry is being made during one of - the retries this value will be STATUS_SUCCESS. - - SpecificIOStatus - The IO status for a particular error. - - LengthOfInsert1 - The length in bytes (including the terminating NULL) - of the first insertion string. - - Insert1 - The first insertion string. - - LengthOfInsert2 - The length in bytes (including the terminating NULL) - of the second insertion string. NOTE, there must - be a first insertion string for their to be - a second insertion string. - - Insert2 - The second insertion string. - -Return Value: - - None. - ---*/ - -{ - PIO_ERROR_LOG_PACKET errorLogEntry; - - PVOID objectToUse; - SHORT dumpToAllocate = 0; - PUCHAR ptrToFirstInsert; - PUCHAR ptrToSecondInsert; - - PAGED_CODE(); - - if (Insert1 == NULL) { - LengthOfInsert1 = 0; - } - - if (Insert2 == NULL) { - LengthOfInsert2 = 0; - } - - - if (ARGUMENT_PRESENT(DeviceObject)) { - - objectToUse = DeviceObject; - - } else { - - objectToUse = DriverObject; - - } - - if (SerialMemCompare( - P1, - (ULONG)1, - SerialPhysicalZero, - (ULONG)1 - ) != AddressesAreEqual) { - - dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS); - - } - - if (SerialMemCompare( - P2, - (ULONG)1, - SerialPhysicalZero, - (ULONG)1 - ) != AddressesAreEqual) { - - dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS); - - } - - errorLogEntry = IoAllocateErrorLogEntry( - objectToUse, - (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + - dumpToAllocate - + LengthOfInsert1 + - LengthOfInsert2) - ); - - if ( errorLogEntry != NULL ) { - - errorLogEntry->ErrorCode = SpecificIOStatus; - errorLogEntry->SequenceNumber = SequenceNumber; - errorLogEntry->MajorFunctionCode = MajorFunctionCode; - errorLogEntry->RetryCount = RetryCount; - errorLogEntry->UniqueErrorValue = UniqueErrorValue; - errorLogEntry->FinalStatus = FinalStatus; - errorLogEntry->DumpDataSize = dumpToAllocate; - - if (dumpToAllocate) { - - RtlCopyMemory( - &errorLogEntry->DumpData[0], - &P1, - sizeof(PHYSICAL_ADDRESS) - ); - - if (dumpToAllocate > sizeof(PHYSICAL_ADDRESS)) { - - RtlCopyMemory( - ((PUCHAR)&errorLogEntry->DumpData[0]) - +sizeof(PHYSICAL_ADDRESS), - &P2, - sizeof(PHYSICAL_ADDRESS) - ); - - ptrToFirstInsert = - ((PUCHAR)&errorLogEntry->DumpData[0])+(2*sizeof(PHYSICAL_ADDRESS)); - - } else { - - ptrToFirstInsert = - ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS); - - - } - - } else { - - ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0]; - - } - - ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1; - - if (LengthOfInsert1) { - - errorLogEntry->NumberOfStrings = 1; - errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert - - (PUCHAR)errorLogEntry); - RtlCopyMemory( - ptrToFirstInsert, - Insert1, - LengthOfInsert1 - ); - - if (LengthOfInsert2) { - - errorLogEntry->NumberOfStrings = 2; - RtlCopyMemory( - ptrToSecondInsert, - Insert2, - LengthOfInsert2 - ); - - } - - } - - IoWriteErrorLogEntry(errorLogEntry); - - } - -} - -VOID -SerialMarkHardwareBroken(IN PSERIAL_DEVICE_EXTENSION PDevExt) -/*++ - -Routine Description: - - Marks a UART as broken. This causes the driver stack to stop accepting - requests and eventually be removed. - -Arguments: - PDevExt - Device extension attached to PDevObj - -Return Value: - - None. - ---*/ -{ - PAGED_CODE(); - - // - // Write a log entry - // - - SerialLogError(PDevExt->DriverObject, NULL, SerialPhysicalZero, - SerialPhysicalZero, 0, 0, 0, 88, STATUS_SUCCESS, - SERIAL_HARDWARE_FAILURE, PDevExt->DeviceName.Length - + sizeof(WCHAR), PDevExt->DeviceName.Buffer, 0, NULL); - - SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_INIT, "Device is broken. Request a restart...\n"); - WdfDeviceSetFailed(PDevExt->WdfDevice, WdfDeviceFailedAttemptRestart); -} - -NTSTATUS -SerialGetDivisorFromBaud( - IN ULONG ClockRate, - IN LONG DesiredBaud, - OUT PSHORT AppropriateDivisor - ) - -/*++ - -Routine Description: - - This routine will determine a divisor based on an unvalidated - baud rate. - -Arguments: - - ClockRate - The clock input to the controller. - - DesiredBaud - The baud rate for whose divisor we seek. - - AppropriateDivisor - Given that the DesiredBaud is valid, the - LONG pointed to by this parameter will be set to the appropriate - value. NOTE: The long is undefined if the DesiredBaud is not - supported. - -Return Value: - - This function will return STATUS_SUCCESS if the baud is supported. - If the value is not supported it will return a status such that - NT_ERROR(Status) == FALSE. - ---*/ - -{ - - NTSTATUS status = STATUS_SUCCESS; - SHORT calculatedDivisor; - ULONG denominator; - ULONG remainder; - - // - // Allow up to a 1 percent error - // - - ULONG maxRemain18 = 18432; - ULONG maxRemain30 = 30720; - ULONG maxRemain42 = 42336; - ULONG maxRemain80 = 80000; - ULONG maxRemain; - - - - // - // Reject any non-positive bauds. - // - - denominator = DesiredBaud*(ULONG)16; - - if (DesiredBaud <= 0) { - - *AppropriateDivisor = -1; - - } else if ((LONG)denominator < DesiredBaud) { - - // - // If the desired baud was so huge that it cause the denominator - // calculation to wrap, don't support it. - // - - *AppropriateDivisor = -1; - - } else { - - if (ClockRate == 1843200) { - maxRemain = maxRemain18; - } else if (ClockRate == 3072000) { - maxRemain = maxRemain30; - } else if (ClockRate == 4233600) { - maxRemain = maxRemain42; - } else { - maxRemain = maxRemain80; - } - - calculatedDivisor = (SHORT)(ClockRate / denominator); - remainder = ClockRate % denominator; - - // - // Round up. - // - - if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) { - - calculatedDivisor++; - } - - - // - // Only let the remainder calculations effect us if - // the baud rate is > 9600. - // - - if (DesiredBaud >= 9600) { - - // - // If the remainder is less than the maximum remainder (wrt - // the ClockRate) or the remainder + the maximum remainder is - // greater than or equal to the ClockRate then assume that the - // baud is ok. - // - - if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) { - calculatedDivisor = -1; - } - - } - - // - // Don't support a baud that causes the denominator to - // be larger than the clock. - // - - if (denominator > ClockRate) { - - calculatedDivisor = -1; - - } - - // - // Ok, Now do some special casing so that things can actually continue - // working on all platforms. - // - - if (ClockRate == 1843200) { - - if (DesiredBaud == 56000) { - calculatedDivisor = 2; - } - - } else if (ClockRate == 3072000) { - - if (DesiredBaud == 14400) { - calculatedDivisor = 13; - } - - } else if (ClockRate == 4233600) { - - if (DesiredBaud == 9600) { - calculatedDivisor = 28; - } else if (DesiredBaud == 14400) { - calculatedDivisor = 18; - } else if (DesiredBaud == 19200) { - calculatedDivisor = 14; - } else if (DesiredBaud == 38400) { - calculatedDivisor = 7; - } else if (DesiredBaud == 56000) { - calculatedDivisor = 5; - } - - } else if (ClockRate == 8000000) { - - if (DesiredBaud == 14400) { - calculatedDivisor = 35; - } else if (DesiredBaud == 56000) { - calculatedDivisor = 9; - } - - } - - *AppropriateDivisor = calculatedDivisor; - - } - - - if (*AppropriateDivisor == -1) { - - status = STATUS_INVALID_PARAMETER; - - } - - return status; - -} - - -BOOLEAN -IsQueueEmpty( - IN WDFQUEUE Queue - ) -{ - WDF_IO_QUEUE_STATE queueStatus; - - queueStatus = WdfIoQueueGetState( Queue, NULL, NULL ); - - return (WDF_IO_QUEUE_IDLE(queueStatus)) ? TRUE : FALSE; -} - -VOID -SerialSetCancelRoutine( - IN WDFREQUEST Request, - IN PFN_WDF_REQUEST_CANCEL CancelRoutine) -{ - PREQUEST_CONTEXT reqContext = SerialGetRequestContext(Request); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "-->SerialSetCancelRoutine %p \n", Request); - - WdfRequestMarkCancelable(Request, CancelRoutine); - SERIAL_SET_REFERENCE(reqContext, SERIAL_REF_CANCEL); - reqContext->CancelRoutine = CancelRoutine; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "<-- SerialSetCancelRoutine \n"); - - return; -} - -NTSTATUS -SerialClearCancelRoutine( - IN WDFREQUEST Request, - IN BOOLEAN ClearReference - ) -{ - NTSTATUS status = STATUS_SUCCESS; - PREQUEST_CONTEXT reqContext = SerialGetRequestContext(Request); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "-->SerialClearCancelRoutine %p %x\n", - Request, ClearReference); - - if(SERIAL_TEST_REFERENCE(reqContext, SERIAL_REF_CANCEL)) - { - status = WdfRequestUnmarkCancelable(Request); - if (NT_SUCCESS(status)) { - - reqContext->CancelRoutine = NULL; - if(ClearReference) { - - SERIAL_CLEAR_REFERENCE( reqContext, SERIAL_REF_CANCEL ); - - } - } else { - ASSERT(status == STATUS_CANCELLED); - } - } - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "-->SerialClearCancelRoutine %p\n", Request); - - return status; -} - - -VOID -SerialCompleteRequest( - IN WDFREQUEST Request, - IN NTSTATUS Status, - IN ULONG_PTR Info - ) -{ - PREQUEST_CONTEXT reqContext; - - reqContext = SerialGetRequestContext(Request); - - ASSERT(reqContext->RefCount == 0); - - SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, - "Complete Request: %p %X 0x%I64x\n", - (Request), (Status), (Info)); - - WdfRequestCompleteWithInformation((Request), (Status), (Info)); - -} - - diff --git a/tests/projects/wdk/kmdf/serial/waitmask.c b/tests/projects/wdk/kmdf/serial/waitmask.c deleted file mode 100644 index c3139679e..000000000 --- a/tests/projects/wdk/kmdf/serial/waitmask.c +++ /dev/null @@ -1,574 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - waitmask.c - -Abstract: - - This module contains the code that is very specific to get/set/wait - on event mask operations in the serial driver - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "waitmask.tmh" -#endif - -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabWaitFromIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGiveWaitToIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialFinishOldWait; - - -VOID -SerialStartMask( - IN PSERIAL_DEVICE_EXTENSION Extension - ) - -/*++ - -Routine Description: - - This routine is used to process the set mask and wait - mask ioctls. Calls to this routine are serialized by - placing irps in the list under the protection of the - cancel spin lock. - -Arguments: - - Extension - A pointer to the serial device extension. - -Return Value: - - Will return pending for everything put the first - request that we actually process. Even in that - case it will return pending unless it can complete - it right away. - - ---*/ - -{ - - - WDFREQUEST NewRequest; - PREQUEST_CONTEXT reqContext; - WDF_REQUEST_PARAMETERS params; - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "In SerialStartMask\n"); - - ASSERT(Extension->CurrentMaskRequest); - - - do { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "STARTMASK - CurrentMaskRequest: %p\n", - Extension->CurrentMaskRequest); - - WDF_REQUEST_PARAMETERS_INIT(¶ms); - - WdfRequestGetParameters( - Extension->CurrentMaskRequest, - ¶ms - ); - - - reqContext = SerialGetRequestContext(Extension->CurrentMaskRequest); - - ASSERT((params.Parameters.DeviceIoControl.IoControlCode == - IOCTL_SERIAL_WAIT_ON_MASK) || - (params.Parameters.DeviceIoControl.IoControlCode == - IOCTL_SERIAL_SET_WAIT_MASK)); - - if (params.Parameters.DeviceIoControl.IoControlCode == - IOCTL_SERIAL_SET_WAIT_MASK) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "SERIAL - %p is a SETMASK request\n", - Extension->CurrentMaskRequest); - - // - // Complete the old wait if there is one. - // - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialFinishOldWait, - Extension - ); - - // - // Any current waits should be on its way to completion - // at this point. There certainly shouldn't be any - // request mask location. - // - - ASSERT(!Extension->IrpMaskLocation); - - reqContext->Status = STATUS_SUCCESS; - - // - // The following call will also cause the current - // call to be completed. - // - - SerialGetNextRequest( - &Extension->CurrentMaskRequest, - Extension->MaskQueue, - &NewRequest, - TRUE, - Extension - ); - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Perhaps another mask request was found in " - "the queue\n" - "------- %p/%p <- values should be the same\n", - Extension->CurrentMaskRequest, NewRequest); - - - } else { - - // - // First make sure that we have a non-zero mask. - // If the app queues a wait on a zero mask it can't - // be statisfied so it makes no sense to start it. - // - - if ((!Extension->IsrWaitMask) || (Extension->CurrentWaitRequest)) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "WaitIrp is invalid\n" - "------- IsrWaitMask: %x\n" - "------- CurrentWaitRequest: %p\n", - Extension->IsrWaitMask, - Extension->CurrentWaitRequest); - - reqContext->Status = STATUS_INVALID_PARAMETER; - - SerialGetNextRequest(&Extension->CurrentMaskRequest, - Extension->MaskQueue, &NewRequest, TRUE, - Extension); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Perhaps another mask request was found " - "in the queue\n" - "------- %p/%p <- values should be the same\n", - Extension->CurrentMaskRequest,NewRequest); - - } else { - - // - // Make the current mask request the current wait request and - // get a new current mask request. Note that when we get - // the new current mask request we DO NOT complete the - // old current mask request (which is now the current wait - // request. - // - // Then under the protection of the cancel spin lock - // we check to see if the current wait request needs to - // be canceled - // - - SERIAL_INIT_REFERENCE(reqContext); - - SerialSetCancelRoutine(Extension->CurrentMaskRequest, - SerialCancelWait); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "%p will become the current " - "wait request\n", - Extension->CurrentMaskRequest); - // - // There should never be a mask location when - // there isn't a current wait request. At this point - // there shouldn't be a current wait request also. - // - - ASSERT(!Extension->IrpMaskLocation); - ASSERT(!Extension->CurrentWaitRequest); - - Extension->CurrentWaitRequest = Extension->CurrentMaskRequest; - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGiveWaitToIsr, - Extension - ); - - // - // Since it isn't really the mask request anymore, - // null out that pointer. - // - Extension->CurrentMaskRequest = NULL; - - // - // This will release the cancel spinlock for us - // - - SerialGetNextRequest(&Extension->CurrentMaskRequest, - Extension->MaskQueue, &NewRequest, - FALSE, Extension); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Perhaps another mask request was " - "found in the queue\n" - "------- %p/%p <- values should be the " - "same\n", Extension->CurrentMaskRequest, - NewRequest); - } - - } - - } while (NewRequest); - - return; - -} - -BOOLEAN -SerialGrabWaitFromIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine will check to see if the ISR still knows about - a wait request by checking to see if the IrpMaskLocation is non-null. - If it is then it will zero the Irpmasklocation (which in effect - grabs the request away from the isr). This routine is only called - buy the cancel code for the wait. - - NOTE: This is called by WdfInterruptSynchronize. - -Arguments: - - Context - A pointer to the device extension - -Return Value: - - Always FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = Context; - - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "In SerialGrabWaitFromIsr\n"); - - if (Extension->IrpMaskLocation) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "The isr still owns the request %p, mask " - "location is %p\n" - "------- and system buffer is %p\n", - Extension->CurrentWaitRequest,Extension->IrpMaskLocation, - reqContext->SystemBuffer); - - // - // The isr still "owns" the request. - // - - *Extension->IrpMaskLocation = 0; - Extension->IrpMaskLocation = NULL; - - reqContext->Information = sizeof(ULONG); - - // - // Since the isr no longer references the request we need to - // decrement the reference count. - // - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - } - - return FALSE; -} - -BOOLEAN -SerialGiveWaitToIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine simply sets a variable in the device extension - so that the isr knows that we have a wait request. - - NOTE: This is called by WdfInterruptSynchronize. - - NOTE: This routine assumes that it is called with the - cancel spinlock held. - -Arguments: - - Context - Simply a pointer to the device extension. - -Return Value: - - Always FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "In SerialGiveWaitToIsr\n"); - // - // There certainly shouldn't be a current mask location at - // this point since we have a new current wait request. - // - - ASSERT(!Extension->IrpMaskLocation); - - // - // The isr may or may not actually reference this request. It - // won't if the wait can be satisfied immediately. However, - // since it will then go through the normal completion sequence, - // we need to have an incremented reference count anyway. - // - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - if (!Extension->HistoryMask) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "No events occured prior to the wait call" - "\n"); - - // - // Although this wait might not be for empty transmit - // queue, it doesn't hurt anything to set it to false. - // - - Extension->EmptiedTransmit = FALSE; - - // - // Record where the "completion mask" should be set. - // - - Extension->IrpMaskLocation = reqContext->SystemBuffer; - SerialDbgPrintEx( TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "The isr owns the request %p, mask location is " - "%p\n" - "------- and system buffer is %p\n", - Extension->CurrentWaitRequest,Extension->IrpMaskLocation, - reqContext->SystemBuffer); - - } else { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "%x occurred prior to the wait - starting " - "the\n" - "------- completion code for %p\n", - Extension->HistoryMask,Extension->CurrentWaitRequest); - - *((ULONG *)reqContext->SystemBuffer) = - Extension->HistoryMask; - Extension->HistoryMask = 0; - reqContext->Information = sizeof(ULONG); - reqContext->Status = STATUS_SUCCESS; - - SerialInsertQueueDpc(Extension->CommWaitDpc); - - } - - return FALSE; -} - -BOOLEAN -SerialFinishOldWait( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine will check to see if the ISR still knows about - a wait request by checking to see if the Irpmasklocation is non-null. - If it is then it will zero the Irpmasklocation (which in effect - grabs the request away from the isr). This routine is only called - buy the cancel code for the wait. - - NOTE: This is called by WdfInterruptSynchronize. - -Arguments: - - Context - A pointer to the device extension - -Return Value: - - Always FALSE. - ---*/ - -{ - PSERIAL_DEVICE_EXTENSION Extension = Context; - - PREQUEST_CONTEXT reqContext = NULL; - PREQUEST_CONTEXT reqContextMask; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContextMask = SerialGetRequestContext(Extension->CurrentMaskRequest); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "In SerialFinishOldWait\n"); - - if (Extension->IrpMaskLocation) { - - reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "The isr still owns the request %p, mask " - "location is %p\n" - "------- and system buffer is %p\n", - Extension->CurrentWaitRequest,Extension->IrpMaskLocation, - reqContext->SystemBuffer); - // - // The isr still "owns" the request. - // - - *Extension->IrpMaskLocation = 0; - Extension->IrpMaskLocation = NULL; - - reqContext->Information = sizeof(ULONG); - - // - // We don't decrement the reference since the completion routine - // will do that. - // - - SerialInsertQueueDpc(Extension->CommWaitDpc); - - } - - // - // Don't wipe out any historical data we are still interested in. - // - - Extension->HistoryMask &= *((ULONG *)reqContextMask->SystemBuffer); - - Extension->IsrWaitMask = *((ULONG *)reqContextMask->SystemBuffer); - SerialDbgPrintEx( TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Set mask location of %p, in request %p, with " - "system buffer of %p\n", - Extension->IrpMaskLocation, Extension->CurrentMaskRequest, - reqContextMask->SystemBuffer); - return FALSE; -} - -VOID -SerialCancelWait( - IN WDFREQUEST Request - ) - -/*++ - -Routine Description: - - This routine is used to cancel a request that is waiting on - a comm event. - -Arguments: - - Device - Wdf handle for the device - - Request - Pointer to the WDFREQUEST for the current request - -Return Value: - - None. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension; - WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); - - UNREFERENCED_PARAMETER(Request); - - Extension = SerialGetDeviceExtension(device); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Canceling wait for request %p\n", - Extension->CurrentWaitRequest); - - SerialTryToCompleteCurrent(Extension, - SerialGrabWaitFromIsr, - STATUS_CANCELLED, - &Extension->CurrentWaitRequest, - NULL, NULL, NULL, - NULL, NULL, SERIAL_REF_CANCEL); - -} - - -VOID -SerialCompleteWait( - IN WDFDPC Dpc - ) - -{ - - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - ">SerialCompleteWait(%p)\n", - Extension); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - "Completing wait for request %p\n", - Extension->CurrentWaitRequest); - - SerialTryToCompleteCurrent(Extension, NULL, STATUS_SUCCESS, - &Extension->CurrentWaitRequest, NULL, NULL, NULL, - NULL, NULL, SERIAL_REF_ISR); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, - " - -#if defined(EVENT_TRACING) -#include "wmi.tmh" -#endif - -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortName; -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortCommData; -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortHWData; -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortPerfData; -EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortPropData; - -NTSTATUS -SerialWmiRegisterInstance( - WDFDEVICE Device, - const GUID* Guid, - ULONG MinInstanceBufferSize, - PFN_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceQueryInstance - ); - -#ifdef ALLOC_PRAGMA -#pragma alloc_text(PAGESRP0, SerialWmiRegistration) -#pragma alloc_text(PAGESRP0, SerialWmiRegisterInstance) -#pragma alloc_text(PAGESRP0, EvtWmiQueryPortName) -#pragma alloc_text(PAGESRP0, EvtWmiQueryPortCommData) -#pragma alloc_text(PAGESRP0, EvtWmiQueryPortHWData) -#pragma alloc_text(PAGESRP0, EvtWmiQueryPortPerfData) -#pragma alloc_text(PAGESRP0, EvtWmiQueryPortPropData) -#endif - -NTSTATUS -SerialWmiRegisterInstance( - WDFDEVICE Device, - const GUID* Guid, - ULONG MinInstanceBufferSize, - PFN_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceQueryInstance - ) -{ - WDF_WMI_PROVIDER_CONFIG providerConfig; - WDF_WMI_INSTANCE_CONFIG instanceConfig; - - PAGED_CODE(); - - // - // Create and register WMI providers and instances blocks - // - WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, Guid); - providerConfig.MinInstanceBufferSize = MinInstanceBufferSize; - - WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig); - instanceConfig.Register = TRUE; - instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceQueryInstance; - - return WdfWmiInstanceCreate(Device, - &instanceConfig, - WDF_NO_OBJECT_ATTRIBUTES, - WDF_NO_HANDLE); -} - -NTSTATUS -SerialWmiRegistration( - WDFDEVICE Device -) -/*++ -Routine Description - - Registers with WMI as a data provider for this - instance of the device - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSERIAL_DEVICE_EXTENSION pDevExt; - - PAGED_CODE(); - - pDevExt = SerialGetDeviceExtension (Device); - - // - // Fill in wmi perf data (all zero's) - // - RtlZeroMemory(&pDevExt->WmiPerfData, sizeof(pDevExt->WmiPerfData)); - - status = SerialWmiRegisterInstance(Device, - &MSSerial_PortName_GUID, - 0, - EvtWmiQueryPortName); - if (!NT_SUCCESS(status)) { - return status; - } - - status = SerialWmiRegisterInstance(Device, - &MSSerial_CommInfo_GUID, - sizeof(SERIAL_WMI_COMM_DATA), - EvtWmiQueryPortCommData); - if (!NT_SUCCESS(status)) { - return status; - } - - status = SerialWmiRegisterInstance(Device, - &MSSerial_HardwareConfiguration_GUID, - sizeof(SERIAL_WMI_HW_DATA), - EvtWmiQueryPortHWData); - if (!NT_SUCCESS(status)) { - return status; - } - - status = SerialWmiRegisterInstance(Device, - &MSSerial_PerformanceInformation_GUID, - sizeof(SERIAL_WMI_PERF_DATA), - EvtWmiQueryPortPerfData); - if (!NT_SUCCESS(status)) { - return status; - } - - status = SerialWmiRegisterInstance(Device, - &MSSerial_CommProperties_GUID, - sizeof(SERIAL_COMMPROP) + sizeof(ULONG), - EvtWmiQueryPortPropData); - - if (!NT_SUCCESS(status)) { - return status; - } - - return status; -} - -// -// WMI Call back functions -// - -NTSTATUS -EvtWmiQueryPortName( - IN WDFWMIINSTANCE WmiInstance, - IN ULONG OutBufferSize, - IN PVOID OutBuffer, - OUT PULONG BufferUsed - ) -{ - WDFDEVICE device; - WCHAR pRegName[SYMBOLIC_NAME_LENGTH]; - UNICODE_STRING string; - USHORT nameSize = sizeof(pRegName); - NTSTATUS status; - - PAGED_CODE(); - - device = WdfWmiInstanceGetDevice(WmiInstance); - - status = SerialReadSymName(device, pRegName, &nameSize); - if (!NT_SUCCESS(status)) { - return status; - } - - RtlInitUnicodeString(&string, pRegName); - - return WDF_WMI_BUFFER_APPEND_STRING(OutBuffer, - OutBufferSize, - &string, - BufferUsed); -} - -NTSTATUS -EvtWmiQueryPortCommData( - IN WDFWMIINSTANCE WmiInstance, - IN ULONG OutBufferSize, - IN PVOID OutBuffer, - OUT PULONG BufferUsed - ) -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - - UNREFERENCED_PARAMETER(OutBufferSize); - - PAGED_CODE(); - - pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); - - *BufferUsed = sizeof(SERIAL_WMI_COMM_DATA); - - if (OutBufferSize < *BufferUsed) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - *(PSERIAL_WMI_COMM_DATA)OutBuffer = pDevExt->WmiCommData; - - return STATUS_SUCCESS; -} - -NTSTATUS -EvtWmiQueryPortHWData( - IN WDFWMIINSTANCE WmiInstance, - IN ULONG OutBufferSize, - IN PVOID OutBuffer, - OUT PULONG BufferUsed - ) -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - - UNREFERENCED_PARAMETER(OutBufferSize); - - PAGED_CODE(); - - pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); - - *BufferUsed = sizeof(SERIAL_WMI_HW_DATA); - - if (OutBufferSize < *BufferUsed) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - *(PSERIAL_WMI_HW_DATA)OutBuffer = pDevExt->WmiHwData; - - return STATUS_SUCCESS; -} - -NTSTATUS -EvtWmiQueryPortPerfData( - IN WDFWMIINSTANCE WmiInstance, - IN ULONG OutBufferSize, - IN PVOID OutBuffer, - OUT PULONG BufferUsed - ) -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - - UNREFERENCED_PARAMETER(OutBufferSize); - - PAGED_CODE(); - - pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); - - *BufferUsed = sizeof(SERIAL_WMI_PERF_DATA); - - if (OutBufferSize < *BufferUsed) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - *(PSERIAL_WMI_PERF_DATA)OutBuffer = pDevExt->WmiPerfData; - - return STATUS_SUCCESS; -} - -NTSTATUS -EvtWmiQueryPortPropData( - IN WDFWMIINSTANCE WmiInstance, - IN ULONG OutBufferSize, - IN PVOID OutBuffer, - OUT PULONG BufferUsed - ) -{ - PSERIAL_DEVICE_EXTENSION pDevExt; - - UNREFERENCED_PARAMETER(OutBufferSize); - - PAGED_CODE(); - - pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); - - *BufferUsed = sizeof(SERIAL_COMMPROP) + sizeof(ULONG); - - if (OutBufferSize < *BufferUsed) { - return STATUS_INSUFFICIENT_RESOURCES; - } - - SerialGetProperties( - pDevExt, - (PSERIAL_COMMPROP)OutBuffer - ); - - *((PULONG)(((PSERIAL_COMMPROP)OutBuffer)->ProvChar)) = 0; - - return STATUS_SUCCESS; -} - diff --git a/tests/projects/wdk/kmdf/serial/write.c b/tests/projects/wdk/kmdf/serial/write.c deleted file mode 100644 index c67c062b4..000000000 --- a/tests/projects/wdk/kmdf/serial/write.c +++ /dev/null @@ -1,1195 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - write.c - -Abstract: - - This module contains the code that is very specific to write - operations in the serial driver - -Environment: - - Kernel mode - ---*/ - -#include "precomp.h" - -#if defined(EVENT_TRACING) -#include "write.tmh" -#endif - -EVT_WDF_REQUEST_CANCEL SerialCancelCurrentWrite; -EVT_WDF_REQUEST_CANCEL SerialCancelCurrentXoff; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGiveWriteToIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGiveXoffToIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabWriteFromIsr; -EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabXoffFromIsr; - - -VOID -SerialEvtIoWrite( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t Length - ) - -/*++ - -Routine Description: - - This is the dispatch routine for write. It validates the parameters - for the write request and if all is ok then it places the request - on the work queue. - -Arguments: - - Queue - Handle to the framework queue object that is associated - with the I/O request. - Request - Pointer to the WDFREQUEST for the current request - - Length - Length of the IO operation - The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get - a zero length request. - -Return Value: - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION extension; - NTSTATUS status; - WDFDEVICE hDevice; - WDF_REQUEST_PARAMETERS params; - PREQUEST_CONTEXT reqContext; - size_t bufLen; - - hDevice = WdfIoQueueGetDevice(Queue); - extension = SerialGetDeviceExtension(hDevice); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, - ">SerialEvtIoWrite(%p, 0x%I64x)\n", Request, Length); - - if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) { - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "MajorFunction = params.Type; - reqContext->Length = (ULONG) Length; - - status = WdfRequestRetrieveInputBuffer (Request, Length, &reqContext->SystemBuffer, &bufLen); - - if (!NT_SUCCESS (status)) { - - SerialCompleteRequest(Request , status, 0); - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "WriteQueue, - &extension->CurrentWriteRequest, - SerialStartWrite); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialStartWrite(%p)\n", Extension); - - TotalTime.QuadPart = 0; - - do { - - reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); - - // - // If there is an xoff counter then complete it. - // - - // - // We see if there is a actually an Xoff counter request. - // - // If there is, we put the write request back on the head - // of the write list. We then complete the xoff counter. - // The xoff counter completing code will actually make the - // xoff counter back into the current write request, and - // in the course of completing the xoff (which is now - // the current write) we will restart this request. - // - - if (Extension->CurrentXoffRequest) { - - reqContextXoff = - SerialGetRequestContext(Extension->CurrentXoffRequest); - - if (SERIAL_REFERENCE_COUNT(reqContextXoff)) { - - // - // The reference count is non-zero. This implies that - // the xoff request has not made it through the completion - // path yet. We will increment the reference count - // and attempt to complete it ourseleves. - // - - SERIAL_SET_REFERENCE( - reqContextXoff, - SERIAL_REF_XOFF_REF - ); - - reqContextXoff->Information = 0; - - // - // The following call will actually release the - // cancel spin lock. - // - - SerialTryToCompleteCurrent( - Extension, - SerialGrabXoffFromIsr, - STATUS_SERIAL_MORE_WRITES, - &Extension->CurrentXoffRequest, - NULL, - NULL, - Extension->XoffCountTimer, - NULL, - NULL, - SERIAL_REF_XOFF_REF - ); - - } else { - - // - // The request is well on its way to being finished. - // We can let the regular completion code do the - // work. Just release the spin lock. - // - - } - - } - - UseATimer = FALSE; - - // - // Calculate the timeout value needed for the - // request. Note that the values stored in the - // timeout record are in milliseconds. Note that - // if the timeout values are zero then we won't start - // the timer. - // - - Timeouts = Extension->Timeouts; - - if (Timeouts.WriteTotalTimeoutConstant || - Timeouts.WriteTotalTimeoutMultiplier) { - - UseATimer = TRUE; - - // - // We have some timer values to calculate. - // - // Take care, we might have an xoff counter masquerading - // as a write. - // - - TotalTime.QuadPart = - ((LONGLONG)((UInt32x32To64( - (reqContext->MajorFunction == IRP_MJ_WRITE)? - (reqContext->Length) : (1), - Timeouts.WriteTotalTimeoutMultiplier - ) - + Timeouts.WriteTotalTimeoutConstant))) - * -10000; - - } - - // - // The request may be going to the isr shortly. Now - // is a good time to initialize its reference counts. - // - - SERIAL_INIT_REFERENCE(reqContext); - - // - // We give the request to to the isr to write out. - // We set a cancel routine that knows how to - // grab the current write away from the isr. - // - SerialSetCancelRoutine(Extension->CurrentWriteRequest, - SerialCancelCurrentWrite); - - if (UseATimer) { - BOOLEAN result; - - result = SerialSetTimer( - Extension->WriteRequestTotalTimer, - TotalTime - ); - if(result == FALSE) { - // - // This timer now has a reference to the request. - // - - SERIAL_SET_REFERENCE( reqContext, SERIAL_REF_TOTAL_TIMER ); - } - } - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGiveWriteToIsr, - Extension - ); - - } WHILE (FALSE); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialGetNextWrite\n"); - - - do { - - reqContext = SerialGetRequestContext(*CurrentOpRequest); - - // - // We could be completing a flush. - // - - if (reqContext->MajorFunction == IRP_MJ_WRITE) { - - ASSERT(Extension->TotalCharsQueued >= reqContext->Length); - - Extension->TotalCharsQueued -= reqContext->Length; - - } else if (reqContext->MajorFunction == IRP_MJ_DEVICE_CONTROL) { - - WDFREQUEST request = *CurrentOpRequest; - PSERIAL_XOFF_COUNTER Xc; - - Xc = reqContext->SystemBuffer; - - // - // We should never have a xoff counter when we - // get to this point. - // - - ASSERT(!Extension->CurrentXoffRequest); - - // - // This could only be a xoff counter masquerading as - // a write request. - // - - Extension->TotalCharsQueued--; - - // - // Check to see of the xoff request has been set with success. - // This means that the write completed normally. If that - // is the case, and it hasn't been set to cancel in the - // meanwhile, then go on and make it the CurrentXoffRequest. - // - - if (reqContext->Status != STATUS_SUCCESS || reqContext->Cancelled) { - - // TODO: I see Xoff request getting abandoned due to loss of - // Total timer - SERIAL_REF_TOTAL_TIMER - // - // Oh well, we can just finish it off. - // - NOTHING; - - } else { - - SerialSetCancelRoutine(request, SerialCancelCurrentXoff); - - // - // We don't want to complete the current request now. This - // will now get completed by the Xoff counter code. - // - - CompleteCurrent = FALSE; - - // - // Give the counter to the isr. - // - - Extension->CurrentXoffRequest = request; - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialGiveXoffToIsr, - Extension - ); - - // - // Start the timer for the counter and increment - // the reference count since the timer has a - // reference to the request. - // - - if (Xc->Timeout) { - - LARGE_INTEGER delta; - BOOLEAN result; - - delta.QuadPart = -((LONGLONG)UInt32x32To64( - 1000, - Xc->Timeout - )); - - result = SerialSetTimer( - Extension->XoffCountTimer, - delta - - ); - if(result == FALSE) { - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_TOTAL_TIMER - ); - } - } - - } - - - } - - // - // Note that the following call will (probably) also cause - // the current request to be completed. - // - - SerialGetNextRequest( - CurrentOpRequest, - QueueToProcess, - NewRequest, - CompleteCurrent, - Extension - ); - - if (!*NewRequest) { - - - WdfInterruptSynchronize( - Extension->WdfInterrupt, - SerialProcessEmptyTransmit, - Extension - ); - - break; - - } else if (SerialGetRequestContext(*NewRequest)->MajorFunction - == IRP_MJ_FLUSH_BUFFERS) { - - // - // If we encounter a flush request we just want to get - // the next request and complete the flush. - // - // Note that if NewRequest is non-null then it is also - // equal to CurrentWriteRequest. - // - - - ASSERT((*NewRequest) == (*CurrentOpRequest)); - SerialGetRequestContext(*NewRequest)->Status = STATUS_SUCCESS; - - } else { - - break; - - } - - } WHILE (TRUE); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialCompleteWrite(%p)\n", - Extension); - - - SerialTryToCompleteCurrent(Extension, NULL, STATUS_SUCCESS, - &Extension->CurrentWriteRequest, - Extension->WriteQueue, NULL, - Extension->WriteRequestTotalTimer, - SerialStartWrite, SerialGetNextWrite, - SERIAL_REF_ISR); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "IsrWaitMask && (Extension->IsrWaitMask & SERIAL_EV_TXEMPTY) && - Extension->EmptiedTransmit && (!Extension->TransmitImmediate) && - (!Extension->CurrentWriteRequest) && IsQueueEmpty(Extension->WriteQueue)) { - - Extension->HistoryMask |= SERIAL_EV_TXEMPTY; - if (Extension->IrpMaskLocation) { - - *Extension->IrpMaskLocation = Extension->HistoryMask; - Extension->IrpMaskLocation = NULL; - Extension->HistoryMask = 0; - - SerialGetRequestContext(Extension->CurrentWaitRequest)->Information = sizeof(ULONG); - SerialInsertQueueDpc( - Extension->CommWaitDpc - ); - - } - - Extension->CountOfTryingToLowerRTS++; - SerialPerhapsLowerRTS(Extension->WdfInterrupt, Extension); - - } - - return FALSE; - -} - - -BOOLEAN -SerialGiveWriteToIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - Try to start off the write by slipping it in behind - a transmit immediate char, or if that isn't available - and the transmit holding register is empty, "tickle" - the UART into interrupting with a transmit buffer - empty. - - NOTE: This routine is called by WdfInterruptSynchronize. - - NOTE: This routine assumes that it is called with the - cancel spin lock held. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - // - // The current stack location. This contains all of the - // information we need to process this particular request. - // - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); - - // - // We might have a xoff counter request masquerading as a - // write. The length of these requests will always be one - // and we can get a pointer to the actual character from - // the data supplied by the user. - // - - if (reqContext->MajorFunction == IRP_MJ_WRITE) { - - Extension->WriteLength = reqContext->Length; - Extension->WriteCurrentChar = reqContext->SystemBuffer; - - } else { - - Extension->WriteLength = 1; - Extension->WriteCurrentChar = - ((PUCHAR)reqContext->SystemBuffer) + - FIELD_OFFSET( - SERIAL_XOFF_COUNTER, - XoffChar - ); - - } - - // - // The isr now has a reference to the request. - // - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - // - // Check first to see if an immediate char is transmitting. - // If it is then we'll just slip in behind it when its - // done. - // - - if (!Extension->TransmitImmediate) { - - // - // If there is no immediate char transmitting then we - // will "re-enable" the transmit holding register empty - // interrupt. The 8250 family of devices will always - // signal a transmit holding register empty interrupt - // *ANY* time this bit is set to one. By doing things - // this way we can simply use the normal interrupt code - // to start off this write. - // - // We've been keeping track of whether the transmit holding - // register is empty so it we only need to do this - // if the register is empty. - // - - if (Extension->HoldingEmpty) { - - DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); - - } - - } - - // - // The rts line may already be up from previous writes, - // however, it won't take much additional time to turn - // on the RTS line if we are doing transmit toggling. - // - - if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == - SERIAL_TRANSMIT_TOGGLE) { - - SerialSetRTS(Extension->WdfInterrupt, Extension); - - } - - return FALSE; - -} - - -VOID -SerialCancelCurrentWrite( - IN WDFREQUEST Request - ) - -/*++ - -Routine Description: - - This routine is used to cancel the current write. - -Arguments: - - Device - Wdf handle for the device - - Request - Pointer to the WDFREQUEST to be canceled. - -Return Value: - - None. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension; - WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); - - UNREFERENCED_PARAMETER(Request); - - Extension = SerialGetDeviceExtension(device); - - SerialTryToCompleteCurrent( - Extension, - SerialGrabWriteFromIsr, - STATUS_CANCELLED, - &Extension->CurrentWriteRequest, - Extension->WriteQueue, - NULL, - Extension->WriteRequestTotalTimer, - SerialStartWrite, - SerialGetNextWrite, - SERIAL_REF_CANCEL - ); - -} - - -VOID -SerialWriteTimeout( - IN WDFTIMER Timer - ) - -/*++ - -Routine Description: - - This routine will try to timeout the current write. - -Arguments: - -Return Value: - - None. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - Extension = SerialGetDeviceExtension(WdfTimerGetParentObject(Timer)); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, ">SerialWriteTimeout(%p)\n", - Extension); - - SerialTryToCompleteCurrent(Extension, SerialGrabWriteFromIsr, - STATUS_TIMEOUT, &Extension->CurrentWriteRequest, - Extension->WriteQueue, NULL, - Extension->WriteRequestTotalTimer, - SerialStartWrite, SerialGetNextWrite, - SERIAL_REF_TOTAL_TIMER); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "CurrentWriteRequest); - - // - // Check if the write length is non-zero. If it is non-zero - // then the ISR still owns the request. We calculate the the number - // of characters written and update the information field of the - // request with the characters written. We then clear the write length - // the isr sees. - // - - if (Extension->WriteLength) { - - // - // We could have an xoff counter masquerading as a - // write request. If so, don't update the write length. - // - - if (reqContext->MajorFunction == IRP_MJ_WRITE) { - - reqContext->Information = reqContext->Length -Extension->WriteLength; - - } else { - - reqContext->Information = 0; - - } - - // - // Since the isr no longer references this request, we can - // decrement it's reference count. - // - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - Extension->WriteLength = 0; - - } - - return FALSE; - -} - - -BOOLEAN -SerialGrabXoffFromIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - This routine is used to grab an xoff counter request from the - isr when it is no longer masquerading as a write request. This - routine is called by the cancel and timeout code for the - xoff counter ioctl. - - - NOTE: This routine is being called from WdfInterruptSynchronize. - - NOTE: This routine assumes that the cancel spin lock is held - when this routine is called. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - Always false. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - - PREQUEST_CONTEXT reqContext; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentXoffRequest); - - if (Extension->CountSinceXoff) { - - // - // This is only non-zero when there actually is a Xoff ioctl - // counting down. - // - - Extension->CountSinceXoff = 0; - - // - // We decrement the count since the isr no longer owns - // the request. - // - - SERIAL_CLEAR_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - } - - return FALSE; - -} - - -VOID -SerialCompleteXoff( - IN WDFDPC Dpc - ) - -/*++ - -Routine Description: - - This routine is merely used to truely complete an xoff counter request. It - assumes that the status and the information fields of the request are - already correctly filled in. - -Arguments: - - Dpc - Not Used. - - DeferredContext - Really points to the device extension. - - SystemContext1 - Not Used. - - SystemContext2 - Not Used. - -Return Value: - - None. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = NULL; - - Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, ">SerialCompleteXoff(%p)\n", - Extension); - - - SerialTryToCompleteCurrent(Extension, NULL, STATUS_SUCCESS, - &Extension->CurrentXoffRequest, NULL, NULL, - Extension->XoffCountTimer, NULL, NULL, - SERIAL_REF_ISR); - - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialTimeoutXoff(%p)\n", Extension); - - SerialTryToCompleteCurrent(Extension, SerialGrabXoffFromIsr, - STATUS_SERIAL_COUNTER_TIMEOUT, - &Extension->CurrentXoffRequest, NULL, NULL, NULL, - NULL, NULL, SERIAL_REF_TOTAL_TIMER); - - SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "CurrentXoffRequest, - NULL, - NULL, - Extension->XoffCountTimer, - NULL, - NULL, - SERIAL_REF_CANCEL - ); - -} - - -BOOLEAN -SerialGiveXoffToIsr( - IN WDFINTERRUPT Interrupt, - IN PVOID Context - ) - -/*++ - -Routine Description: - - - This routine starts off the xoff counter. It merely - has to set the xoff count and increment the reference - count to denote that the isr has a reference to the request. - - NOTE: This routine is called by WdfInterruptSynchronize. - - NOTE: This routine assumes that it is called with the - cancel spin lock held. - -Arguments: - - Context - Really a pointer to the device extension. - -Return Value: - - This routine always returns FALSE. - ---*/ - -{ - - PSERIAL_DEVICE_EXTENSION Extension = Context; - PREQUEST_CONTEXT reqContext; - PSERIAL_XOFF_COUNTER Xc = NULL; - - UNREFERENCED_PARAMETER(Interrupt); - - reqContext = SerialGetRequestContext(Extension->CurrentXoffRequest); - Xc = reqContext->SystemBuffer; - - // - // The current stack location. This contains all of the - // information we need to process this particular request. - // - - ASSERT(Extension->CurrentXoffRequest); - Extension->CountSinceXoff = Xc->Counter; - - // - // The isr now has a reference to the request. - // - - SERIAL_SET_REFERENCE( - reqContext, - SERIAL_REF_ISR - ); - - return FALSE; - -} - - diff --git a/tests/projects/wdk/kmdf/serial/xmake.lua b/tests/projects/wdk/kmdf/serial/xmake.lua deleted file mode 100644 index 53d59c650..000000000 --- a/tests/projects/wdk/kmdf/serial/xmake.lua +++ /dev/null @@ -1,9 +0,0 @@ -add_rules("mode.debug", "mode.release") - -target("wdfserial") - add_rules("wdk.env.kmdf", "wdk.driver") - add_values("wdk.tracewpp.flags", "-func:SerialDbgPrintEx(LEVEL,FLAGS,MSG,...)") - add_values("wdk.mc.header", "serlog.h") - add_files("*.c", {rule = "wdk.tracewpp"}) - add_files("*.mc", "*.rc", "*.inx") - diff --git a/tests/projects/wdk/umdf/echo/driver/device.c b/tests/projects/wdk/umdf/echo/driver/device.c deleted file mode 100644 index bd522565f..000000000 --- a/tests/projects/wdk/umdf/echo/driver/device.c +++ /dev/null @@ -1,202 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation - -Module Name: - - device.c - Device handling events for example driver. - -Abstract: - - This is a C version of a very simple sample driver that illustrates - how to use the driver framework and demonstrates best practices. - ---*/ - -#include "driver.h" - -NTSTATUS -EchoDeviceCreate( - PWDFDEVICE_INIT DeviceInit - ) -/*++ - -Routine Description: - - Worker routine called to create a device and its software resources. - -Arguments: - - DeviceInit - Pointer to an opaque init structure. Memory for this - structure will be freed by the framework when the WdfDeviceCreate - succeeds. So don't access the structure after that point. - -Return Value: - - NTSTATUS - ---*/ -{ - WDF_OBJECT_ATTRIBUTES deviceAttributes; - PDEVICE_CONTEXT deviceContext; - WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; - WDFDEVICE device; - NTSTATUS status; - - WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); - - // - // Register pnp/power callbacks so that we can start and stop the timer as the device - // gets started and stopped. - // - pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = EchoEvtDeviceSelfManagedIoStart; - pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend = EchoEvtDeviceSelfManagedIoSuspend; - - #pragma prefast(suppress: 28024, "Function used for both Init and Restart Callbacks") - pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = EchoEvtDeviceSelfManagedIoStart; - - // - // Register the PnP and power callbacks. Power policy related callbacks will be registered - // later in SotwareInit. - // - WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); - - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); - - status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); - - if (NT_SUCCESS(status)) { - // - // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an - // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the - // device.h header file. This function will do the type checking and return - // the device context. If you pass a wrong object handle - // it will return NULL and assert if run under framework verifier mode. - // - deviceContext = WdfObjectGet_DEVICE_CONTEXT(device); - deviceContext->PrivateDeviceData = 0; - - // - // Create a device interface so that application can find and talk - // to us. - // - status = WdfDeviceCreateDeviceInterface( - device, - &GUID_DEVINTERFACE_ECHO, - NULL // ReferenceString - ); - - if (NT_SUCCESS(status)) { - // - // Initialize the I/O Package and any Queues - // - status = EchoQueueInitialize(device); - } - } - - return status; -} - - -NTSTATUS -EchoEvtDeviceSelfManagedIoStart( - IN WDFDEVICE Device - ) -/*++ - -Routine Description: - - This event is called by the Framework when the device is started - or restarted after a suspend operation. - - This function is not marked pageable because this function is in the - device power up path. When a function is marked pagable and the code - section is paged out, it will generate a page fault which could impact - the fast resume behavior because the client driver will have to wait - until the system drivers can service this page fault. - -Arguments: - - Device - Handle to a framework device object. - -Return Value: - - NTSTATUS - Failures will result in the device stack being torn down. - ---*/ -{ - PQUEUE_CONTEXT queueContext = QueueGetContext(WdfDeviceGetDefaultQueue(Device)); - LARGE_INTEGER DueTime; - - KdPrint(("--> EchoEvtDeviceSelfManagedIoInit\n")); - - // - // Restart the queue and the periodic timer. We stopped them before going - // into low power state. - // - WdfIoQueueStart(WdfDeviceGetDefaultQueue(Device)); - - DueTime.QuadPart = WDF_REL_TIMEOUT_IN_MS(100); - - WdfTimerStart(queueContext->Timer, DueTime.QuadPart); - - KdPrint(( "<-- EchoEvtDeviceSelfManagedIoInit\n")); - - return STATUS_SUCCESS; -} - -NTSTATUS -EchoEvtDeviceSelfManagedIoSuspend( - IN WDFDEVICE Device - ) -/*++ - -Routine Description: - - This event is called by the Framework when the device is stopped - for resource rebalance or suspended when the system is entering - Sx state. - - -Arguments: - - Device - Handle to a framework device object. - -Return Value: - - NTSTATUS - The driver is not allowed to fail this function. If it does, the - device stack will be torn down. - ---*/ -{ - PQUEUE_CONTEXT queueContext = QueueGetContext(WdfDeviceGetDefaultQueue(Device)); - - PAGED_CODE(); - - KdPrint(("--> EchoEvtDeviceSelfManagedIoSuspend\n")); - - // - // Before we stop the timer we should make sure there are no outstanding - // i/o. We need to do that because framework cannot suspend the device - // if there are requests owned by the driver. There are two ways to solve - // this issue: 1) We can wait for the outstanding I/O to be complete by the - // periodic timer 2) Register EvtIoStop callback on the queue and acknowledge - // the request to inform the framework that it's okay to suspend the device - // with outstanding I/O. In this sample we will use the 1st approach - // because it's pretty easy to do. We will restart the queue when the - // device is restarted. - // - WdfIoQueueStopSynchronously(WdfDeviceGetDefaultQueue(Device)); - - // - // Stop the watchdog timer and wait for DPC to run to completion if it's already fired. - // - WdfTimerStop(queueContext->Timer, TRUE); - - KdPrint(( "<-- EchoEvtDeviceSelfManagedIoSuspend\n")); - - return STATUS_SUCCESS; -} - - - diff --git a/tests/projects/wdk/umdf/echo/driver/device.h b/tests/projects/wdk/umdf/echo/driver/device.h deleted file mode 100644 index 1e2c1f28e..000000000 --- a/tests/projects/wdk/umdf/echo/driver/device.h +++ /dev/null @@ -1,48 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation - -Module Name: - - device.h - -Abstract: - - This is a C version of a very simple sample driver that illustrates - how to use the driver framework and demonstrates best practices. - ---*/ - -#include "public.h" - -// -// The device context performs the same job as -// a WDM device extension in the driver frameworks -// -typedef struct _DEVICE_CONTEXT -{ - ULONG PrivateDeviceData; // just a placeholder - -} DEVICE_CONTEXT, *PDEVICE_CONTEXT; - -// -// This macro will generate an inline function called WdfObjectGet_DEVICE_CONTEXT -// which will be used to get a pointer to the device context memory -// in a type safe manner. -// -WDF_DECLARE_CONTEXT_TYPE(DEVICE_CONTEXT) - -// -// Function to initialize the device and its callbacks -// -NTSTATUS -EchoDeviceCreate( - PWDFDEVICE_INIT DeviceInit - ); - -// -// Device events -// -EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT EchoEvtDeviceSelfManagedIoStart; -EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND EchoEvtDeviceSelfManagedIoSuspend; - diff --git a/tests/projects/wdk/umdf/echo/driver/driver.c b/tests/projects/wdk/umdf/echo/driver/driver.c deleted file mode 100644 index 2835aa1dd..000000000 --- a/tests/projects/wdk/umdf/echo/driver/driver.c +++ /dev/null @@ -1,192 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation - -Module Name: - - driver.c - -Abstract: - - This driver demonstrates use of a default I/O Queue, its - request start events, cancellation event, and a synchronized DPC. - - To demonstrate asynchronous operation, the I/O requests are not completed - immediately, but stored in the drivers private data structure, and a timer - will complete it next time the Timer callback runs. - - During the time the request is waiting for the timer callback to run, it is - made cancellable by the call WdfRequestMarkCancelable. This - allows the test program to cancel the request and exit instantly. - - This rather complicated set of events is designed to demonstrate - the driver frameworks synchronization of access to a device driver - data structure, and a pointer which can be a proxy for device hardware - registers or resources. - - This common data structure, or resource is accessed by new request - events arriving, the Timer callback that completes it, and cancel processing. - - Notice the lack of specific lock/unlock operations. - - Even though this example utilizes a serial queue, a parallel queue - would not need any additional explicit synchronization, just a - strategy for managing multiple requests outstanding. - ---*/ - -#include "driver.h" - -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - DriverEntry initializes the driver and is the first routine called by the - system after the driver is loaded. DriverEntry specifies the other entry - points in the function driver, such as EvtDevice and DriverUnload. - -Parameters Description: - - DriverObject - represents the instance of the function driver that is loaded - into memory. DriverEntry must initialize members of DriverObject before it - returns to the caller. DriverObject is allocated by the system before the - driver is loaded, and it is released by the system after the system unloads - the function driver from memory. - - RegistryPath - represents the driver specific path in the Registry. - The function driver can use the path to store driver related data between - reboots. The path does not store hardware instance specific data. - -Return Value: - - STATUS_SUCCESS if successful, - STATUS_UNSUCCESSFUL otherwise. - ---*/ -{ - WDF_DRIVER_CONFIG config; - NTSTATUS status; - - WDF_DRIVER_CONFIG_INIT(&config, - EchoEvtDeviceAdd - ); - - status = WdfDriverCreate(DriverObject, - RegistryPath, - WDF_NO_OBJECT_ATTRIBUTES, - &config, - WDF_NO_HANDLE); - if (!NT_SUCCESS(status)) { - KdPrint(("Error: WdfDriverCreate failed 0x%x\n", status)); - return status; - } - -#if DBG - EchoPrintDriverVersion(); -#endif - - return status; -} - -NTSTATUS -EchoEvtDeviceAdd( - IN WDFDRIVER Driver, - IN PWDFDEVICE_INIT DeviceInit - ) -/*++ -Routine Description: - - EvtDeviceAdd is called by the framework in response to AddDevice - call from the PnP manager. We create and initialize a device object to - represent a new instance of the device. - -Arguments: - - Driver - Handle to a framework driver object created in DriverEntry - - DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - - UNREFERENCED_PARAMETER(Driver); - - KdPrint(("Enter EchoEvtDeviceAdd\n")); - - status = EchoDeviceCreate(DeviceInit); - - return status; -} - -NTSTATUS -EchoPrintDriverVersion( - ) -/*++ -Routine Description: - - This routine shows how to retrieve framework version string and - also how to find out to which version of framework library the - client driver is bound to. - -Arguments: - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS status; - WDFSTRING string; - UNICODE_STRING us; - WDF_DRIVER_VERSION_AVAILABLE_PARAMS ver; - - // - // 1) Retreive version string and print that in the debugger. - // - status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &string); - if (!NT_SUCCESS(status)) { - KdPrint(("Error: WdfStringCreate failed 0x%x\n", status)); - return status; - } - - status = WdfDriverRetrieveVersionString(WdfGetDriver(), string); - if (!NT_SUCCESS(status)) { - // - // No need to worry about delete the string object because - // by default it's parented to the driver and it will be - // deleted when the driverobject is deleted when the DriverEntry - // returns a failure status. - // - KdPrint(("Error: WdfDriverRetrieveVersionString failed 0x%x\n", status)); - return status; - } - - WdfStringGetUnicodeString(string, &us); - KdPrint(("Echo Sample %wZ\n", &us)); - - WdfObjectDelete(string); - string = NULL; // To avoid referencing a deleted object. - - // - // 2) Find out to which version of framework this driver is bound to. - // - WDF_DRIVER_VERSION_AVAILABLE_PARAMS_INIT(&ver, 1, 0); - if (WdfDriverIsVersionAvailable(WdfGetDriver(), &ver) == TRUE) { - KdPrint(("Yes, framework version is 1.0\n")); - }else { - KdPrint(("No, framework verison is not 1.0\n")); - } - - return STATUS_SUCCESS; -} - diff --git a/tests/projects/wdk/umdf/echo/driver/driver.h b/tests/projects/wdk/umdf/echo/driver/driver.h deleted file mode 100644 index 6539d6cf5..000000000 --- a/tests/projects/wdk/umdf/echo/driver/driver.h +++ /dev/null @@ -1,46 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation - -Module Name: - - driver.h - -Abstract: - - This is a C version of a very simple sample driver that illustrates - how to use the driver framework and demonstrates best practices. - ---*/ - -#define INITGUID - -#include -#include -#include "device.h" -#include "queue.h" - -#ifndef ASSERT -#if DBG -#define ASSERT( exp ) \ - ((!(exp)) ? \ - (KdPrint(( "\n*** Assertion failed: " #exp "\n\n")), \ - DebugBreak(), \ - FALSE) : \ - TRUE) -#else -#define ASSERT( exp ) -#endif // DBG -#endif // ASSERT - -// -// WDFDRIVER Events -// - -DRIVER_INITIALIZE DriverEntry; -EVT_WDF_DRIVER_DEVICE_ADD EchoEvtDeviceAdd; - -NTSTATUS -EchoPrintDriverVersion( - ); - diff --git a/tests/projects/wdk/umdf/echo/driver/echoum.inx b/tests/projects/wdk/umdf/echo/driver/echoum.inx deleted file mode 100644 index cae8b45fe..000000000 Binary files a/tests/projects/wdk/umdf/echo/driver/echoum.inx and /dev/null differ diff --git a/tests/projects/wdk/umdf/echo/driver/queue.c b/tests/projects/wdk/umdf/echo/driver/queue.c deleted file mode 100644 index e0f3d7b6b..000000000 --- a/tests/projects/wdk/umdf/echo/driver/queue.c +++ /dev/null @@ -1,538 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation - -Module Name: - - queue.c - -Abstract: - - This is a C version of a very simple sample driver that illustrates - how to use the driver framework and demonstrates best practices. - ---*/ - -#include "driver.h" - -NTSTATUS -EchoQueueInitialize( - WDFDEVICE Device - ) -/*++ - -Routine Description: - - - The I/O dispatch callbacks for the frameworks device object - are configured in this function. - - A single default I/O Queue is configured for serial request - processing, and a driver context memory allocation is created - to hold our structure QUEUE_CONTEXT. - - This memory may be used by the driver automatically synchronized - by the Queue's presentation lock. - - The lifetime of this memory is tied to the lifetime of the I/O - Queue object, and we register an optional destructor callback - to release any private allocations, and/or resources. - - -Arguments: - - Device - Handle to a framework device object. - -Return Value: - - NTSTATUS - ---*/ -{ - WDFQUEUE queue; - NTSTATUS status; - PQUEUE_CONTEXT queueContext; - WDF_IO_QUEUE_CONFIG queueConfig; - WDF_OBJECT_ATTRIBUTES queueAttributes; - - // - // Configure a default queue so that requests that are not - // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto - // other queues get dispatched here. - // - WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( - &queueConfig, - WdfIoQueueDispatchSequential - ); - - queueConfig.EvtIoRead = EchoEvtIoRead; - queueConfig.EvtIoWrite = EchoEvtIoWrite; - - // - // Fill in a callback for destroy, and our QUEUE_CONTEXT size - // - WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_CONTEXT); - - // - // Set synchronization scope on queue and have the timer to use queue as - // the parent object so that queue and timer callbacks are synchronized - // with the same lock. - // - queueAttributes.SynchronizationScope = WdfSynchronizationScopeQueue; - - queueAttributes.EvtDestroyCallback = EchoEvtIoQueueContextDestroy; - - status = WdfIoQueueCreate( - Device, - &queueConfig, - &queueAttributes, - &queue - ); - - if( !NT_SUCCESS(status) ) { - KdPrint(("WdfIoQueueCreate failed 0x%x\n",status)); - return status; - } - - // Get our Driver Context memory from the returned Queue handle - queueContext = QueueGetContext(queue); - - queueContext->WriteMemory = NULL; - queueContext->Timer = NULL; - - queueContext->CurrentRequest = NULL; - queueContext->CurrentStatus = STATUS_INVALID_DEVICE_REQUEST; - - // - // Create the Queue timer - // - status = EchoTimerCreate(&queueContext->Timer, queue); - if (!NT_SUCCESS(status)) { - KdPrint(("Error creating timer 0x%x\n",status)); - return status; - } - - return status; -} - - -NTSTATUS -EchoTimerCreate( - IN WDFTIMER* Timer, - IN WDFQUEUE Queue - ) -/*++ - -Routine Description: - - Subroutine to create timer. By associating the timerobject with - the queue, we are basically telling the framework to serialize the queue - callbacks with the timer callback. By doing so, we don't have to worry - about protecting queue-context structure from multiple threads accessing - it simultaneously. - -Arguments: - - -Return Value: - - NTSTATUS - ---*/ -{ - NTSTATUS Status; - WDF_TIMER_CONFIG timerConfig; - WDF_OBJECT_ATTRIBUTES timerAttributes; - - // - // Create a non-periodic timer since WDF does not allow periodic timer - // at passive level, which is the level UMDF callbacks are invoked at. - // The workaround is to always restart the timer in the timer callback. - // - // WDF_TIMER_CONFIG_INIT sets AutomaticSerialization to TRUE by default. - // - WDF_TIMER_CONFIG_INIT(&timerConfig, EchoEvtTimerFunc); - - WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); - timerAttributes.ParentObject = Queue; // Synchronize with the I/O Queue - timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; - - Status = WdfTimerCreate(&timerConfig, - &timerAttributes, - Timer // Output handle - ); - - return Status; -} - - - -VOID -EchoEvtIoQueueContextDestroy( - WDFOBJECT Object -) -/*++ - -Routine Description: - - This is called when the Queue that our driver context memory - is associated with is destroyed. - -Arguments: - - Context - Context that's being freed. - -Return Value: - - VOID - ---*/ -{ - PQUEUE_CONTEXT queueContext = QueueGetContext(Object); - - // - // Release any resources pointed to in the queue context. - // - // The body of the queue context will be released after - // this callback handler returns - // - - // - // If Queue context has an I/O buffer, release it - // - if( queueContext->WriteMemory != NULL ) { - WdfObjectDelete(queueContext->WriteMemory); - queueContext->WriteMemory = NULL; - } - - return; -} - - -VOID -EchoEvtRequestCancel( - IN WDFREQUEST Request - ) -/*++ - -Routine Description: - - - Called when an I/O request is cancelled after the driver has marked - the request cancellable. This callback is automatically synchronized - with the I/O callbacks since we have chosen to use frameworks Device - level locking. - -Arguments: - - Request - Request being cancelled. - -Return Value: - - VOID - ---*/ -{ - PQUEUE_CONTEXT queueContext = QueueGetContext(WdfRequestGetIoQueue(Request)); - - KdPrint(("EchoEvtRequestCancel called on Request 0x%p\n", Request)); - - // - // The following is race free by the callside or DPC side - // synchronizing completion by calling - // WdfRequestMarkCancelable(Queue, Request, FALSE) before - // completion and not calling WdfRequestComplete if the - // return status == STATUS_CANCELLED. - // - WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); - - // - // This book keeping is synchronized by the common - // Queue presentation lock - // - ASSERT(queueContext->CurrentRequest == Request); - queueContext->CurrentRequest = NULL; - - return; -} - -VOID -EchoEvtIoRead( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t Length - ) -/*++ - -Routine Description: - - This event is called when the framework receives IRP_MJ_READ request. - It will copy the content from the queue-context buffer to the request buffer. - If the driver hasn't received any write request earlier, the read returns zero. - -Arguments: - - Queue - Handle to the framework queue object that is associated with the - I/O request. - - Request - Handle to a framework request object. - - Length - number of bytes to be read. - The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get - a zero length request. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS Status; - PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); - WDFMEMORY memory; - size_t writeMemoryLength; - - _Analysis_assume_(Length > 0); - - KdPrint(("EchoEvtIoRead Called! Queue 0x%p, Request 0x%p Length %d\n", - Queue,Request,Length)); - // - // No data to read - // - if( (queueContext->WriteMemory == NULL) ) { - WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)0L); - return; - } - - // - // Read what we have - // - WdfMemoryGetBuffer(queueContext->WriteMemory, &writeMemoryLength); - _Analysis_assume_(writeMemoryLength > 0); - - if( writeMemoryLength < Length ) { - Length = writeMemoryLength; - } - - // - // Get the request memory - // - Status = WdfRequestRetrieveOutputMemory(Request, &memory); - if( !NT_SUCCESS(Status) ) { - KdPrint(("EchoEvtIoRead Could not get request memory buffer 0x%x\n", Status)); - WdfVerifierDbgBreakPoint(); - WdfRequestCompleteWithInformation(Request, Status, 0L); - return; - } - - // Copy the memory out - Status = WdfMemoryCopyFromBuffer( memory, // destination - 0, // offset into the destination memory - WdfMemoryGetBuffer(queueContext->WriteMemory, NULL), - Length ); - if( !NT_SUCCESS(Status) ) { - KdPrint(("EchoEvtIoRead: WdfMemoryCopyFromBuffer failed 0x%x\n", Status)); - WdfRequestComplete(Request, Status); - return; - } - - // Set transfer information - WdfRequestSetInformation(Request, (ULONG_PTR)Length); - - // Mark the request is cancelable - WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); - - - // Defer the completion to another thread from the timer dpc - queueContext->CurrentRequest = Request; - queueContext->CurrentStatus = Status; - - return; -} - -VOID -EchoEvtIoWrite( - IN WDFQUEUE Queue, - IN WDFREQUEST Request, - IN size_t Length - ) -/*++ - -Routine Description: - - This event is invoked when the framework receives IRP_MJ_WRITE request. - This routine allocates memory buffer, copies the data from the request to it, - and stores the buffer pointer in the queue-context with the length variable - representing the buffers length. The actual completion of the request - is defered to the periodic timer dpc. - -Arguments: - - Queue - Handle to the framework queue object that is associated with the - I/O request. - - Request - Handle to a framework request object. - - Length - number of bytes to be read. - The default property of the queue is to not dispatch - zero lenght read & write requests to the driver and - complete is with status success. So we will never get - a zero length request. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS Status; - WDFMEMORY memory; - PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); - PVOID writeBuffer = NULL; - - _Analysis_assume_(Length > 0); - - KdPrint(("EchoEvtIoWrite Called! Queue 0x%p, Request 0x%p Length %d\n", - Queue,Request,Length)); - - if( Length > MAX_WRITE_LENGTH ) { - KdPrint(("EchoEvtIoWrite Buffer Length to big %d, Max is %d\n", - Length,MAX_WRITE_LENGTH)); - WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_OVERFLOW, 0L); - return; - } - - // Get the memory buffer - Status = WdfRequestRetrieveInputMemory(Request, &memory); - if( !NT_SUCCESS(Status) ) { - KdPrint(("EchoEvtIoWrite Could not get request memory buffer 0x%x\n", - Status)); - WdfVerifierDbgBreakPoint(); - WdfRequestComplete(Request, Status); - return; - } - - // Release previous buffer if set - if( queueContext->WriteMemory != NULL ) { - WdfObjectDelete(queueContext->WriteMemory); - queueContext->WriteMemory = NULL; - } - - Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, - NonPagedPoolNx, - 'sam1', - Length, - &queueContext->WriteMemory, - &writeBuffer - ); - - if(!NT_SUCCESS(Status)) { - KdPrint(("EchoEvtIoWrite: Could not allocate %d byte buffer\n", Length)); - WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); - return; - } - - - // Copy the memory in - Status = WdfMemoryCopyToBuffer( memory, - 0, // offset into the source memory - writeBuffer, - Length ); - if( !NT_SUCCESS(Status) ) { - KdPrint(("EchoEvtIoWrite WdfMemoryCopyToBuffer failed 0x%x\n", Status)); - WdfVerifierDbgBreakPoint(); - - WdfObjectDelete(queueContext->WriteMemory); - queueContext->WriteMemory = NULL; - - WdfRequestComplete(Request, Status); - return; - } - - // Set transfer information - WdfRequestSetInformation(Request, (ULONG_PTR)Length); - - // Specify the request is cancelable - WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); - - // Defer the completion to another thread from the timer dpc - queueContext->CurrentRequest = Request; - queueContext->CurrentStatus = Status; - - return; -} - - -VOID -EchoEvtTimerFunc( - IN WDFTIMER Timer - ) -/*++ - -Routine Description: - - This is the TimerDPC the driver sets up to complete requests. - This function is registered when the WDFTIMER object is created, and - will automatically synchronize with the I/O Queue callbacks - and cancel routine. - -Arguments: - - Timer - Handle to a framework Timer object. - -Return Value: - - VOID - ---*/ -{ - NTSTATUS Status; - WDFREQUEST Request; - WDFQUEUE queue; - PQUEUE_CONTEXT queueContext ; - - queue = WdfTimerGetParentObject(Timer); - queueContext = QueueGetContext(queue); - - // - // DPC is automatically synchronized to the Queue lock, - // so this is race free without explicit driver managed locking. - // - Request = queueContext->CurrentRequest; - if( Request != NULL ) { - - // - // Attempt to remove cancel status from the request. - // - // The request is not completed if it is already cancelled - // since the EchoEvtIoCancel function has run, or is about to run - // and we are racing with it. - // - Status = WdfRequestUnmarkCancelable(Request); - if( Status != STATUS_CANCELLED ) { - - queueContext->CurrentRequest = NULL; - Status = queueContext->CurrentStatus; - - KdPrint(("CustomTimerDPC Completing request 0x%p, Status 0x%x \n", Request,Status)); - - WdfRequestComplete(Request, Status); - } - else { - KdPrint(("CustomTimerDPC Request 0x%p is STATUS_CANCELLED, not completing\n", - Request)); - } - } - - // - // Restart the Timer since WDF does not allow periodic timer - // with autosynchronization at passive level - // - WdfTimerStart(Timer, WDF_REL_TIMEOUT_IN_MS(TIMER_PERIOD)); - - return; -} - - diff --git a/tests/projects/wdk/umdf/echo/driver/queue.h b/tests/projects/wdk/umdf/echo/driver/queue.h deleted file mode 100644 index 5c04dc8f7..000000000 --- a/tests/projects/wdk/umdf/echo/driver/queue.h +++ /dev/null @@ -1,62 +0,0 @@ -/*++ - -Copyright (c) 1990-2000 Microsoft Corporation - -Module Name: - - queue.h - -Abstract: - - This is a C version of a very simple sample driver that illustrates - how to use the driver framework and demonstrates best practices. - ---*/ - -// Set max write length for testing -#define MAX_WRITE_LENGTH 1024*40 - -// Set timer period in ms -#define TIMER_PERIOD 1000*2 - -// -// This is the context that can be placed per queue -// and would contain per queue information. -// -typedef struct _QUEUE_CONTEXT { - - // Here we allocate a buffer from a test write so it can be read back - WDFMEMORY WriteMemory; - - // Timer DPC for this queue - WDFTIMER Timer; - - // Virtual I/O - WDFREQUEST CurrentRequest; - NTSTATUS CurrentStatus; - -} QUEUE_CONTEXT, *PQUEUE_CONTEXT; - -WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext) - -NTSTATUS -EchoQueueInitialize( - WDFDEVICE hDevice - ); - -EVT_WDF_IO_QUEUE_CONTEXT_DESTROY_CALLBACK EchoEvtIoQueueContextDestroy; - -// -// Events from the IoQueue object -// -EVT_WDF_REQUEST_CANCEL EchoEvtRequestCancel; -EVT_WDF_IO_QUEUE_IO_READ EchoEvtIoRead; -EVT_WDF_IO_QUEUE_IO_WRITE EchoEvtIoWrite; - -NTSTATUS -EchoTimerCreate( - IN WDFTIMER* pTimer, - IN WDFQUEUE Queue - ); - -EVT_WDF_TIMER EchoEvtTimerFunc; diff --git a/tests/projects/wdk/umdf/echo/exe/echoapp.cpp b/tests/projects/wdk/umdf/echo/exe/echoapp.cpp deleted file mode 100644 index 47c0ae0a1..000000000 --- a/tests/projects/wdk/umdf/echo/exe/echoapp.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation - -Module Name: - - EchoApp.cpp - -Abstract: - - An application to exercise the WDF "echo" sample driver. - - -Environment: - - user mode only - ---*/ - - -#include -_Analysis_mode_(_Analysis_code_type_user_code_) - -#define INITGUID - -#include -#include -#include -#include -#include -#include "public.h" - -#define NUM_ASYNCH_IO 100 -#define BUFFER_SIZE (40*1024) - -#define READER_TYPE 1 -#define WRITER_TYPE 2 - -#define MAX_DEVPATH_LENGTH 256 - -BOOLEAN G_PerformAsyncIo; -BOOLEAN G_LimitedLoops; -ULONG G_AsyncIoLoopsNum; -WCHAR G_DevicePath[MAX_DEVPATH_LENGTH]; - - -ULONG -AsyncIo( - PVOID ThreadParameter - ); - -BOOLEAN -PerformWriteReadTest( - IN HANDLE hDevice, - IN ULONG TestLength - ); - -BOOL -GetDevicePath( - IN LPGUID InterfaceGuid, - _Out_writes_(BufLen) PWCHAR DevicePath, - _In_ size_t BufLen - ); - - -int __cdecl -main( - _In_ int argc, - _In_reads_(argc) char* argv[] - ) -{ - HANDLE hDevice = INVALID_HANDLE_VALUE; - HANDLE th1 = NULL; - BOOLEAN result = TRUE; - - - if (argc > 1) { - if(!_strnicmp (argv[1], "-Async", 6) ) { - G_PerformAsyncIo = TRUE; - if (argc > 2) { - G_AsyncIoLoopsNum = atoi(argv[2]); - G_LimitedLoops = TRUE; - } - else { - G_LimitedLoops = FALSE; - } - - } else { - printf("Usage:\n"); - printf(" Echoapp.exe --- Send single write and read request synchronously\n"); - printf(" Echoapp.exe -Async --- Send reads and writes asynchronously without terminating\n"); - printf(" Echoapp.exe -Async --- Send reads and writes asynchronously\n"); - printf("Exit the app anytime by pressing Ctrl-C\n"); - result = FALSE; - goto exit; - } - } - - if ( !GetDevicePath( - (LPGUID) &GUID_DEVINTERFACE_ECHO, - G_DevicePath, - sizeof(G_DevicePath)/sizeof(G_DevicePath[0])) ) - { - result = FALSE; - goto exit; - } - - printf("DevicePath: %ws\n", G_DevicePath); - - hDevice = CreateFile(G_DevicePath, - GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL ); - - if (hDevice == INVALID_HANDLE_VALUE) { - printf("Failed to open device. Error %d\n",GetLastError()); - result = FALSE; - goto exit; - } - - printf("Opened device successfully\n"); - - if(G_PerformAsyncIo) { - - printf("Starting AsyncIo\n"); - - // - // Create a reader thread - // - th1 = CreateThread( NULL, // Default Security Attrib. - 0, // Initial Stack Size, - (LPTHREAD_START_ROUTINE) AsyncIo, // Thread Func - (LPVOID)READER_TYPE, - 0, // Creation Flags - NULL ); // Don't need the Thread Id. - - if (th1 == NULL) { - printf("Couldn't create reader thread - error %d\n", GetLastError()); - result = FALSE; - goto exit; - } - - // - // Use this thread for peforming write. - // - result = (BOOLEAN)AsyncIo((PVOID)WRITER_TYPE); - - }else { - // - // Write pattern buffers and read them back, then verify them - // - result = PerformWriteReadTest(hDevice, 512); - if(!result) { - goto exit; - } - - result = PerformWriteReadTest(hDevice, 30*1024); - if(!result) { - goto exit; - } - - } - -exit: - - if (th1 != NULL) { - WaitForSingleObject(th1, INFINITE); - CloseHandle(th1); - } - - if (hDevice != INVALID_HANDLE_VALUE) { - CloseHandle(hDevice); - } - - return ((result == TRUE) ? 0 : 1); - -} - -PUCHAR -CreatePatternBuffer( - IN ULONG Length - ) -{ - unsigned int i; - PUCHAR p, pBuf; - - pBuf = (PUCHAR)malloc(Length); - if( pBuf == NULL ) { - printf("Could not allocate %d byte buffer\n",Length); - return NULL; - } - - p = pBuf; - - for(i=0; i < Length; i++ ) { - *p = (UCHAR)i; - p++; - } - - return pBuf; -} - -BOOLEAN -VerifyPatternBuffer( - _In_reads_bytes_(Length) PUCHAR pBuffer, - _In_ ULONG Length - ) -{ - unsigned int i; - PUCHAR p = pBuffer; - - for( i=0; i < Length; i++ ) { - - if( *p != (UCHAR)(i & 0xFF) ) { - printf("Pattern changed. SB 0x%x, Is 0x%x\n", - (UCHAR)(i & 0xFF), *p); - return FALSE; - } - - p++; - } - - return TRUE; -} - -BOOLEAN -PerformWriteReadTest( - IN HANDLE hDevice, - IN ULONG TestLength - ) -/* -*/ -{ - ULONG bytesReturned =0; - PUCHAR WriteBuffer = NULL, - ReadBuffer = NULL; - BOOLEAN result = TRUE; - - WriteBuffer = CreatePatternBuffer(TestLength); - if( WriteBuffer == NULL ) { - - result = FALSE; - goto Cleanup; - } - - ReadBuffer = (PUCHAR)malloc(TestLength); - if( ReadBuffer == NULL ) { - - printf("PerformWriteReadTest: Could not allocate %d " - "bytes ReadBuffer\n",TestLength); - - result = FALSE; - goto Cleanup; - - } - - // - // Write the pattern to the device - // - bytesReturned = 0; - - if (!WriteFile ( hDevice, - WriteBuffer, - TestLength, - &bytesReturned, - NULL)) { - - printf ("PerformWriteReadTest: WriteFile failed: " - "Error %d\n", GetLastError()); - - result = FALSE; - goto Cleanup; - - } else { - - if( bytesReturned != TestLength ) { - - printf("bytes written is not test length! Written %d, " - "SB %d\n",bytesReturned, TestLength); - - result = FALSE; - goto Cleanup; - } - - printf ("%d Pattern Bytes Written successfully\n", - bytesReturned); - } - - bytesReturned = 0; - - if ( !ReadFile (hDevice, - ReadBuffer, - TestLength, - &bytesReturned, - NULL)) { - - printf ("PerformWriteReadTest: ReadFile failed: " - "Error %d\n", GetLastError()); - - result = FALSE; - goto Cleanup; - - } else { - - if( bytesReturned != TestLength ) { - - printf("bytes Read is not test length! Read %d, " - "SB %d\n",bytesReturned, TestLength); - - // - // Note: Is this a Failure Case?? - // - result = FALSE; - goto Cleanup; - } - - printf ("%d Pattern Bytes Read successfully\n",bytesReturned); - } - - // - // Now compare - // - if( !VerifyPatternBuffer(ReadBuffer, TestLength) ) { - - printf("Verify failed\n"); - - result = FALSE; - goto Cleanup; - } - - printf("Pattern Verified successfully\n"); - -Cleanup: - - // - // Free WriteBuffer if non NULL. - // - if (WriteBuffer) { - free (WriteBuffer); - } - - // - // Free ReadBuffer if non NULL - // - if (ReadBuffer) { - free (ReadBuffer); - } - - return result; -} - -ULONG -AsyncIo( - PVOID ThreadParameter - ) -{ - HANDLE hDevice = INVALID_HANDLE_VALUE; - HANDLE hCompletionPort = NULL; - OVERLAPPED *pOvList = NULL; - PUCHAR buf = NULL; - ULONG numberOfBytesTransferred; - OVERLAPPED *completedOv; - ULONG_PTR i; - ULONG ioType = (ULONG)(ULONG_PTR)ThreadParameter; - ULONG_PTR key; - ULONG error; - BOOLEAN result = TRUE; - ULONG maxPendingRequests = NUM_ASYNCH_IO; - ULONG remainingRequestsToSend = 0; - ULONG remainingRequestsToReceive = 0; - - hDevice = CreateFile(G_DevicePath, - GENERIC_WRITE|GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL ); - - - if (hDevice == INVALID_HANDLE_VALUE) { - printf("Cannot open %ws error %d\n", G_DevicePath, GetLastError()); - result = FALSE; - goto Error; - } - - hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0); - if (hCompletionPort == NULL) { - printf("Cannot open completion port %d \n",GetLastError()); - result = FALSE; - goto Error; - } - - // - // We will only have NUM_ASYNCH_IO or G_AsyncIoLoopsNum pending at any - // time (whichever is less) - // - if (G_LimitedLoops == TRUE) { - remainingRequestsToReceive = G_AsyncIoLoopsNum; - if (G_AsyncIoLoopsNum > NUM_ASYNCH_IO) { - // - // After we send the initial NUM_ASYNCH_IO, we will have additional - // (G_AsyncIoLoopsNum - NUM_ASYNCH_IO) I/Os to send - // - maxPendingRequests = NUM_ASYNCH_IO; - remainingRequestsToSend = G_AsyncIoLoopsNum - NUM_ASYNCH_IO; - } - else { - maxPendingRequests = G_AsyncIoLoopsNum; - remainingRequestsToSend = 0; - - } - } - - pOvList = (OVERLAPPED *)malloc(maxPendingRequests * sizeof(OVERLAPPED)); - if (pOvList == NULL) { - printf("Cannot allocate overlapped array \n"); - result = FALSE; - goto Error; - } - - buf = (PUCHAR)malloc(maxPendingRequests * BUFFER_SIZE); - if (buf == NULL) { - printf("Cannot allocate buffer \n"); - result = FALSE; - goto Error; - } - - ZeroMemory(pOvList, maxPendingRequests * sizeof(OVERLAPPED)); - ZeroMemory(buf, maxPendingRequests * BUFFER_SIZE); - - // - // Issue asynch I/O - // - - for (i = 0; i < maxPendingRequests; i++) { - if (ioType == READER_TYPE) { - if ( ReadFile( hDevice, - buf + (i* BUFFER_SIZE), - BUFFER_SIZE, - NULL, - &pOvList[i]) == 0) { - - error = GetLastError(); - if (error != ERROR_IO_PENDING) { - printf(" %dth Read failed %d \n", (ULONG) i, GetLastError()); - result = FALSE; - goto Error; - } - } - - } else { - if ( WriteFile( hDevice, - buf + (i* BUFFER_SIZE), - BUFFER_SIZE, - NULL, - &pOvList[i]) == 0) { - error = GetLastError(); - if (error != ERROR_IO_PENDING) { - printf(" %dth Write failed %d \n", (ULONG) i, GetLastError()); - result = FALSE; - goto Error; - } - } - } - } - - // - // Wait for the I/Os to complete. If one completes then reissue the I/O - // - - WHILE (1) { - - if ( GetQueuedCompletionStatus(hCompletionPort, &numberOfBytesTransferred, &key, &completedOv, INFINITE) == 0) { - printf("GetQueuedCompletionStatus failed %d\n", GetLastError()); - result = FALSE; - goto Error; - } - - // - // Read successfully completed. If we're doing unlimited I/Os then Issue another one. - // - - if (ioType == READER_TYPE) { - - i = completedOv - pOvList; - printf("Number of bytes read by request number %Id is %d\n", i, numberOfBytesTransferred); - - // - // If we're done with the I/Os, then exit - // - if (G_LimitedLoops == TRUE) { - if ((--remainingRequestsToReceive) == 0) { - break; - } - - if (remainingRequestsToSend == 0) { - continue; - } - else { - remainingRequestsToSend--; - } - } - - - if ( ReadFile( hDevice, - buf + (i * BUFFER_SIZE), - BUFFER_SIZE, - NULL, - completedOv) == 0) { - error = GetLastError(); - if (error != ERROR_IO_PENDING) { - printf("%Idth Read failed %d \n", i, GetLastError()); - result = FALSE; - goto Error; - } - } - } else { - - i = completedOv - pOvList; - - printf("Number of bytes written by request number %Id is %d\n", i, numberOfBytesTransferred); - - // - // If we're done with the I/Os, then exit - // - if (G_LimitedLoops == TRUE) { - if ((--remainingRequestsToReceive) == 0) { - break; - } - - if (remainingRequestsToSend == 0) { - continue; - } - else { - remainingRequestsToSend--; - } - } - - - if ( WriteFile( hDevice, - buf + (i * BUFFER_SIZE), - BUFFER_SIZE, - NULL, - completedOv) == 0) { - error = GetLastError(); - if (error != ERROR_IO_PENDING) { - - printf("%Idth write failed %d \n", i, GetLastError()); - result = FALSE; - goto Error; - } - } - } - } - -Error: - if(hDevice != INVALID_HANDLE_VALUE) { - CloseHandle(hDevice); - } - - if(hCompletionPort) { - CloseHandle(hCompletionPort); - } - - if(buf) { - free(buf); - } - if(pOvList) { - free(pOvList); - } - - return (ULONG)result; - -} - -BOOL -GetDevicePath( - _In_ LPGUID InterfaceGuid, - _Out_writes_(BufLen) PWCHAR DevicePath, - _In_ size_t BufLen - ) -{ - CONFIGRET cr = CR_SUCCESS; - PWSTR deviceInterfaceList = NULL; - ULONG deviceInterfaceListLength = 0; - PWSTR nextInterface; - HRESULT hr = E_FAIL; - BOOL bRet = TRUE; - - cr = CM_Get_Device_Interface_List_Size( - &deviceInterfaceListLength, - InterfaceGuid, - NULL, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (cr != CR_SUCCESS) { - printf("Error 0x%x retrieving device interface list size.\n", cr); - goto clean0; - } - - if (deviceInterfaceListLength <= 1) { - bRet = FALSE; - printf("Error: No active device interfaces found.\n" - " Is the sample driver loaded?"); - goto clean0; - } - - deviceInterfaceList = (PWSTR)malloc(deviceInterfaceListLength * sizeof(WCHAR)); - if (deviceInterfaceList == NULL) { - printf("Error allocating memory for device interface list.\n"); - goto clean0; - } - ZeroMemory(deviceInterfaceList, deviceInterfaceListLength * sizeof(WCHAR)); - - cr = CM_Get_Device_Interface_List( - InterfaceGuid, - NULL, - deviceInterfaceList, - deviceInterfaceListLength, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT); - if (cr != CR_SUCCESS) { - printf("Error 0x%x retrieving device interface list.\n", cr); - goto clean0; - } - - nextInterface = deviceInterfaceList + wcslen(deviceInterfaceList) + 1; - if (*nextInterface != UNICODE_NULL) { - printf("Warning: More than one device interface instance found. \n" - "Selecting first matching device.\n\n"); - } - - hr = StringCchCopy(DevicePath, BufLen, deviceInterfaceList); - if (FAILED(hr)) { - bRet = FALSE; - printf("Error: StringCchCopy failed with HRESULT 0x%x", hr); - goto clean0; - } - -clean0: - if (deviceInterfaceList != NULL) { - free(deviceInterfaceList); - } - if (CR_SUCCESS != cr) { - bRet = FALSE; - } - - return bRet; -} - diff --git a/tests/projects/wdk/umdf/echo/exe/public.h b/tests/projects/wdk/umdf/echo/exe/public.h deleted file mode 100644 index defcded56..000000000 --- a/tests/projects/wdk/umdf/echo/exe/public.h +++ /dev/null @@ -1,30 +0,0 @@ -/*++ -Copyright (c) 1990-2000 Microsoft Corporation All Rights Reserved - -Module Name: - - public.h - -Abstract: - - This module contains the common declarations shared by driver - and user applications. - - -Environment: - - user and kernel - ---*/ - -#define WHILE(a) \ -__pragma(warning(suppress:4127)) while(a) - -// -// Define an Interface Guid so that app can find the device and talk to it. -// - -DEFINE_GUID (GUID_DEVINTERFACE_ECHO, - 0xcdc35b6e, 0xbe4, 0x4936, 0xbf, 0x5f, 0x55, 0x37, 0x38, 0xa, 0x7c, 0x1a); -// {CDC35B6E-0BE4-4936-BF5F-5537380A7C1A} - diff --git a/tests/projects/wdk/umdf/echo/xmake.lua b/tests/projects/wdk/umdf/echo/xmake.lua deleted file mode 100644 index 0a5ec9517..000000000 --- a/tests/projects/wdk/umdf/echo/xmake.lua +++ /dev/null @@ -1,22 +0,0 @@ -add_rules("mode.debug", "mode.release") - -add_defines("_UNICODE", "UNICODE") - -target("echo") - add_rules("wdk.env.umdf", "wdk.driver") - - -- set test sign --- set_values("wdk.sign.mode", "test") - - -- set release sign --- set_values("wdk.sign.mode", "release") --- set_values("wdk.sign.certfile", path.join(os.projectdir(), "xxx.cer")) - - add_files("driver/*.c") - add_files("driver/*.inx") - add_includedirs("exe") - -target("app") - add_rules("wdk.env.umdf", "wdk.binary") - add_files("exe/*.cpp") - diff --git a/tests/projects/wdk/umdf/skeleton/Skeleton.rc b/tests/projects/wdk/umdf/skeleton/Skeleton.rc deleted file mode 100644 index 0e202c4f5..000000000 --- a/tests/projects/wdk/umdf/skeleton/Skeleton.rc +++ /dev/null @@ -1,21 +0,0 @@ -//--------------------------------------------------------------------------- -// Skeleton.rc -// -// Copyright (c) Microsoft Corporation, All Rights Reserved -//--------------------------------------------------------------------------- - - -#include -#include - -// -// TODO: Change the file description and file names to match your binary. -// - -#define VER_FILETYPE VFT_DLL -#define VER_FILESUBTYPE VFT_UNKNOWN -#define VER_FILEDESCRIPTION_STR "WDF:UMDF Skeleton User-Mode Driver Sample" -#define VER_INTERNALNAME_STR "UMDFSkeleton" -#define VER_ORIGINALFILENAME_STR "UMDFSkeleton.dll" - -#include "common.ver" diff --git a/tests/projects/wdk/umdf/skeleton/UMDFSkeleton_OSR.inx b/tests/projects/wdk/umdf/skeleton/UMDFSkeleton_OSR.inx deleted file mode 100644 index 3da01ae62..000000000 Binary files a/tests/projects/wdk/umdf/skeleton/UMDFSkeleton_OSR.inx and /dev/null differ diff --git a/tests/projects/wdk/umdf/skeleton/UMDFSkeleton_Root.inx b/tests/projects/wdk/umdf/skeleton/UMDFSkeleton_Root.inx deleted file mode 100644 index 63d9f94c5..000000000 Binary files a/tests/projects/wdk/umdf/skeleton/UMDFSkeleton_Root.inx and /dev/null differ diff --git a/tests/projects/wdk/umdf/skeleton/comsup.cpp b/tests/projects/wdk/umdf/skeleton/comsup.cpp deleted file mode 100644 index fb0b0807c..000000000 --- a/tests/projects/wdk/umdf/skeleton/comsup.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved - -Module Name: - - ComSup.cpp - -Abstract: - - This module contains implementations for the functions and methods - used for providing COM support. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#include "internal.h" - -#include "comsup.tmh" - -// -// Implementation of CUnknown methods. -// - -CUnknown::CUnknown( - VOID - ) : m_ReferenceCount(1) -/*++ - - Routine Description: - - Constructor for an instance of the CUnknown class. This simply initializes - the reference count of the object to 1. The caller is expected to - call Release() if it wants to delete the object once it has been allocated. - - Arguments: - - None - - Return Value: - - None - ---*/ -{ - // do nothing. -} - -HRESULT -STDMETHODCALLTYPE -CUnknown::QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ) -/*++ - - Routine Description: - - This method provides the basic support for query interface on CUnknown. - If the interface requested is IUnknown it references the object and - returns an interface pointer. Otherwise it returns an error. - - Arguments: - - InterfaceId - the IID being requested - - Object - a location to store the interface pointer to return. - - Return Value: - - S_OK or E_NOINTERFACE - ---*/ -{ - if (IsEqualIID(InterfaceId, __uuidof(IUnknown))) - { - *Object = QueryIUnknown(); - return S_OK; - } - else - { - *Object = NULL; - return E_NOINTERFACE; - } -} - -IUnknown * -CUnknown::QueryIUnknown( - VOID - ) -/*++ - - Routine Description: - - This helper method references the object and returns a pointer to the - object's IUnknown interface. - - This allows other methods to convert a CUnknown pointer into an IUnknown - pointer without a typecast and without calling QueryInterface and dealing - with the return value. - - Arguments: - - None - - Return Value: - - A pointer to the object's IUnknown interface. - ---*/ -{ - AddRef(); - return static_cast(this); -} - -ULONG -STDMETHODCALLTYPE -CUnknown::AddRef( - VOID - ) -/*++ - - Routine Description: - - This method adds one to the object's reference count. - - Arguments: - - None - - Return Value: - - The new reference count. The caller should only use this for debugging - as the object's actual reference count can change while the caller - examines the return value. - ---*/ -{ - return InterlockedIncrement(&m_ReferenceCount); -} - -ULONG -STDMETHODCALLTYPE -CUnknown::Release( - VOID - ) -/*++ - - Routine Description: - - This method subtracts one to the object's reference count. If the count - goes to zero, this method deletes the object. - - Arguments: - - None - - Return Value: - - The new reference count. If the caller uses this value it should only be - to check for zero (i.e. this call caused or will cause deletion) or - non-zero (i.e. some other call may have caused deletion, but this one - didn't). - ---*/ -{ - ULONG count = InterlockedDecrement(&m_ReferenceCount); - - if (count == 0) - { - delete this; - } - return count; -} - -// -// Implementation of CClassFactory methods. -// - -// -// Define storage for the factory's static lock count variable. -// - -LONG CClassFactory::s_LockCount = 0; - -IClassFactory * -CClassFactory::QueryIClassFactory( - VOID - ) -/*++ - - Routine Description: - - This helper method references the object and returns a pointer to the - object's IClassFactory interface. - - This allows other methods to convert a CClassFactory pointer into an - IClassFactory pointer without a typecast and without dealing with the - return value QueryInterface. - - Arguments: - - None - - Return Value: - - A referenced pointer to the object's IClassFactory interface. - ---*/ -{ - AddRef(); - return static_cast(this); -} - -HRESULT -CClassFactory::QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ) -/*++ - - Routine Description: - - This method attempts to retrieve the requested interface from the object. - - If the interface is found then the reference count on that interface (and - thus the object itself) is incremented. - - Arguments: - - InterfaceId - the interface the caller is requesting. - - Object - a location to store the interface pointer. - - Return Value: - - S_OK or E_NOINTERFACE - ---*/ -{ - // - // This class only supports IClassFactory so check for that. - // - - if (IsEqualIID(InterfaceId, __uuidof(IClassFactory))) - { - *Object = QueryIClassFactory(); - return S_OK; - } - else - { - // - // See if the base class supports the interface. - // - - return CUnknown::QueryInterface(InterfaceId, Object); - } -} - -HRESULT -STDMETHODCALLTYPE -CClassFactory::CreateInstance( - _In_opt_ IUnknown * /* OuterObject */, - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ) -/*++ - - Routine Description: - - This COM method is the factory routine - it creates instances of the driver - callback class and returns the specified interface on them. - - Arguments: - - OuterObject - only used for aggregation, which our driver callback class - does not support. - - InterfaceId - the interface ID the caller would like to get from our - new object. - - Object - a location to store the referenced interface pointer to the new - object. - - Return Value: - - Status. - ---*/ -{ - HRESULT hr; - - PCMyDriver driver; - - *Object = NULL; - - hr = CMyDriver::CreateInstance(&driver); - - if (SUCCEEDED(hr)) - { - hr = driver->QueryInterface(InterfaceId, Object); - driver->Release(); - } - - return hr; -} - -HRESULT -STDMETHODCALLTYPE -CClassFactory::LockServer( - _In_ BOOL Lock - ) -/*++ - - Routine Description: - - This COM method can be used to keep the DLL in memory. However since the - driver's DllCanUnloadNow function always returns false, this has little - effect. Still it tracks the number of lock and unlock operations. - - Arguments: - - Lock - Whether the caller wants to lock or unlock the "server" - - Return Value: - - S_OK - ---*/ -{ - if (Lock) - { - InterlockedIncrement(&s_LockCount); - } - else - { - InterlockedDecrement(&s_LockCount); - } - return S_OK; -} - diff --git a/tests/projects/wdk/umdf/skeleton/comsup.h b/tests/projects/wdk/umdf/skeleton/comsup.h deleted file mode 100644 index ba4cd89c3..000000000 --- a/tests/projects/wdk/umdf/skeleton/comsup.h +++ /dev/null @@ -1,215 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved - -Module Name: - - ComSup.h - -Abstract: - - This module contains classes and functions use for providing COM support - code. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// Forward type declarations. They are here rather than in internal.h as -// you only need them if you choose to use these support classes. -// - -typedef class CUnknown *PCUnknown; -typedef class CClassFactory *PCClassFactory; - -// -// Base class to implement IUnknown. You can choose to derive your COM -// classes from this class, or simply implement IUnknown in each of your -// classes. -// - -class CUnknown : public IUnknown -{ - -// -// Private data members and methods. These are only accessible by the methods -// of this class. -// -private: - - // - // The reference count for this object. Initialized to 1 in the - // constructor. - // - - LONG m_ReferenceCount; - -// -// Protected data members and methods. These are accessible by the subclasses -// but not by other classes. -// -protected: - - // - // The constructor and destructor are protected to ensure that only the - // subclasses of CUnknown can create and destroy instances. - // - - CUnknown( - VOID - ); - - // - // The destructor MUST be virtual. Since any instance of a CUnknown - // derived class should only be deleted from within CUnknown::Release, - // the destructor MUST be virtual or only CUnknown::~CUnknown will get - // invoked on deletion. - // - // If you see that your CMyDevice specific destructor is never being - // called, make sure you haven't deleted the virtual destructor here. - // - - virtual - ~CUnknown( - VOID - ) - { - // Do nothing - } - -// -// Public Methods. These are accessible by any class. -// -public: - - IUnknown * - QueryIUnknown( - VOID - ); - -// -// COM Methods. -// -public: - - // - // IUnknown methods - // - - virtual - ULONG - STDMETHODCALLTYPE - AddRef( - VOID - ); - - virtual - ULONG - STDMETHODCALLTYPE - Release( - VOID - ); - - virtual - HRESULT - STDMETHODCALLTYPE - QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ); -}; - -// -// Class factory support class. Create an instance of this from your -// DllGetClassObject method and modify the implementation to create -// an instance of your driver event handler class. -// - -class CClassFactory : public CUnknown, public IClassFactory -{ -// -// Private data members and methods. These are only accessible by the methods -// of this class. -// -private: - - // - // The lock count. This is shared across all instances of IClassFactory - // and can be queried through the public IsLocked method. - // - - static LONG s_LockCount; - -// -// Public Methods. These are accessible by any class. -// -public: - - IClassFactory * - QueryIClassFactory( - VOID - ); - -// -// COM Methods. -// -public: - - // - // IUnknown methods - // - - virtual - ULONG - STDMETHODCALLTYPE - AddRef( - VOID - ) - { - return __super::AddRef(); - } - - _At_(this, __drv_freesMem(object)) - virtual - ULONG - STDMETHODCALLTYPE - Release( - VOID - ) - { - return __super::Release(); - } - - virtual - HRESULT - STDMETHODCALLTYPE - QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ); - - // - // IClassFactory methods. - // - - virtual - HRESULT - STDMETHODCALLTYPE - CreateInstance( - _In_opt_ IUnknown *OuterObject, - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ); - - virtual - HRESULT - STDMETHODCALLTYPE - LockServer( - _In_ BOOL Lock - ); -}; diff --git a/tests/projects/wdk/umdf/skeleton/device.cpp b/tests/projects/wdk/umdf/skeleton/device.cpp deleted file mode 100644 index 2efcd36f0..000000000 --- a/tests/projects/wdk/umdf/skeleton/device.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved. - -Module Name: - - Device.cpp - -Abstract: - - This module contains the implementation of the UMDF Skeleton sample driver's - device callback object. - - The skeleton sample device does very little. It does not implement either - of the PNP interfaces so once the device is setup, it won't ever get any - callbacks until the device is removed. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#include "internal.h" -#include "device.tmh" - -HRESULT -CMyDevice::CreateInstance( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize * FxDeviceInit, - _Out_ PCMyDevice *Device - ) -/*++ - - Routine Description: - - This method creates and initializs an instance of the skeleton driver's - device callback object. - - Arguments: - - FxDeviceInit - the settings for the device. - - Device - a location to store the referenced pointer to the device object. - - Return Value: - - Status - ---*/ -{ - PCMyDevice device; - HRESULT hr; - - // - // Allocate a new instance of the device class. - // - - device = new CMyDevice(); - - if (NULL == device) - { - return E_OUTOFMEMORY; - } - - // - // Initialize the instance. - // - - hr = device->Initialize(FxDriver, FxDeviceInit); - - if (SUCCEEDED(hr)) - { - *Device = device; - } - else - { - device->Release(); - } - - return hr; -} - -HRESULT -CMyDevice::Initialize( - _In_ IWDFDriver * FxDriver, - _In_ IWDFDeviceInitialize * FxDeviceInit - ) -/*++ - - Routine Description: - - This method initializes the device callback object and creates the - partner device object. - - The method should perform any device-specific configuration that: - * could fail (these can't be done in the constructor) - * must be done before the partner object is created -or- - * can be done after the partner object is created and which aren't - influenced by any device-level parameters the parent (the driver - in this case) might set. - - Arguments: - - FxDeviceInit - the settings for this device. - - Return Value: - - status. - ---*/ -{ - IWDFDevice *fxDevice; - HRESULT hr; - - // - // Configure things like the locking model before we go to create our - // partner device. - // - - // - // Set no locking unless you need an automatic callbacks synchronization - // - - FxDeviceInit->SetLockingConstraint(None); - - // - // TODO: If you're writing a filter driver then indicate that here. - // - // FxDeviceInit->SetFilter(); - // - - // - // TODO: Any per-device initialization which must be done before - // creating the partner object. - // - - // - // Create a new FX device object and assign the new callback object to - // handle any device level events that occur. - // - - // - // QueryIUnknown references the IUnknown interface that it returns - // (which is the same as referencing the device). We pass that to - // CreateDevice, which takes its own reference if everything works. - // - - { - IUnknown *unknown = this->QueryIUnknown(); - - hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &fxDevice); - - unknown->Release(); - } - - // - // If that succeeded then set our FxDevice member variable. - // - - if (SUCCEEDED(hr)) - { - m_FxDevice = fxDevice; - - // - // Drop the reference we got from CreateDevice. Since this object - // is partnered with the framework object they have the same - // lifespan - there is no need for an additional reference. - // - - fxDevice->Release(); - } - - return hr; -} - -HRESULT -CMyDevice::Configure( - VOID - ) -/*++ - - Routine Description: - - This method is called after the device callback object has been initialized - and returned to the driver. It would setup the device's queues and their - corresponding callback objects. - - Arguments: - - FxDevice - the framework device object for which we're handling events. - - Return Value: - - status - ---*/ -{ - // - // TODO: Setup your device queues and I/O forwarding. - // - - return S_OK; -} - -HRESULT -CMyDevice::QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ) -/*++ - - Routine Description: - - This method is called to get a pointer to one of the object's callback - interfaces. - - Since the skeleton driver doesn't support any of the device events, this - method simply calls the base class's BaseQueryInterface. - - If the skeleton is extended to include device event interfaces then this - method must be changed to check the IID and return pointers to them as - appropriate. - - Arguments: - - InterfaceId - the interface being requested - - Object - a location to store the interface pointer if successful - - Return Value: - - S_OK or E_NOINTERFACE - ---*/ -{ - return CUnknown::QueryInterface(InterfaceId, Object); -} diff --git a/tests/projects/wdk/umdf/skeleton/device.h b/tests/projects/wdk/umdf/skeleton/device.h deleted file mode 100644 index 26dd0e329..000000000 --- a/tests/projects/wdk/umdf/skeleton/device.h +++ /dev/null @@ -1,115 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved - -Module Name: - - Device.h - -Abstract: - - This module contains the type definitions for the UMDF Skeleton sample - driver's device callback class. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// Class for the iotrace driver. -// - -class CMyDevice : public CUnknown -{ - -// -// Private data members. -// -private: - - IWDFDevice *m_FxDevice; - -// -// Private methods. -// - -private: - - CMyDevice( - VOID - ) - { - m_FxDevice = NULL; - } - - HRESULT - Initialize( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit - ); - -// -// Public methods -// -public: - - // - // The factory method used to create an instance of this driver. - // - - static - HRESULT - CreateInstance( - _In_ IWDFDriver *FxDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit, - _Out_ PCMyDevice *Device - ); - - HRESULT - Configure( - VOID - ); - -// -// COM methods -// -public: - - // - // IUnknown methods. - // - - virtual - ULONG - STDMETHODCALLTYPE - AddRef( - VOID - ) - { - return __super::AddRef(); - } - - _At_(this, __drv_freesMem(object)) - virtual - ULONG - STDMETHODCALLTYPE - Release( - VOID - ) - { - return __super::Release(); - } - - virtual - HRESULT - STDMETHODCALLTYPE - QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ); - -}; diff --git a/tests/projects/wdk/umdf/skeleton/dllsup.cpp b/tests/projects/wdk/umdf/skeleton/dllsup.cpp deleted file mode 100644 index e540452d9..000000000 --- a/tests/projects/wdk/umdf/skeleton/dllsup.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved. - -Module Name: - - dllsup.cpp - -Abstract: - - This module contains the implementation of the UMDF Skeleton Sample - Driver's entry point and its exported functions for providing COM support. - - This module can be copied without modification to a new UMDF driver. It - depends on some of the code in comsup.cpp & comsup.h to handle DLL - registration and creating the first class factory. - - This module is dependent on the following defines: - - MYDRIVER_TRACING_ID - A wide string passed to WPP when initializing - tracing. For example the skeleton uses - L"Microsoft\\UMDF\\Skeleton" - - MYDRIVER_CLASS_ID - A GUID encoded in struct format used to - initialize the driver's ClassID. - - These are defined in internal.h for the sample. If you choose - to use a different primary include file, you should ensure they are - defined there as well. - -Environment: - - WDF User-Mode Driver Framework (WDF:UMDF) - ---*/ - -#include "internal.h" -#include "dllsup.tmh" - -const GUID CLSID_MyDriverCoClass = MYDRIVER_CLASS_ID; - -BOOL -WINAPI -DllMain( - HINSTANCE ModuleHandle, - DWORD Reason, - PVOID /* Reserved */ - ) -/*++ - - Routine Description: - - This is the entry point and exit point for the I/O trace driver. This - does very little as the I/O trace driver has minimal global data. - - This method initializes tracing. - - Arguments: - - ModuleHandle - the DLL handle for this module. - - Reason - the reason this entry point was called. - - Reserved - unused - - Return Value: - - TRUE - ---*/ -{ - - UNREFERENCED_PARAMETER( ModuleHandle ); - - if (DLL_PROCESS_ATTACH == Reason) - { - // - // Initialize tracing. - // - - WPP_INIT_TRACING(MYDRIVER_TRACING_ID); - - } - else if (DLL_PROCESS_DETACH == Reason) - { - // - // Cleanup tracing. - // - - WPP_CLEANUP(); - } - - return TRUE; -} - -HRESULT -STDAPICALLTYPE -DllGetClassObject( - _In_ REFCLSID ClassId, - _In_ REFIID InterfaceId, - _Outptr_ LPVOID *Interface - ) -/*++ - - Routine Description: - - This routine is called by COM in order to instantiate the - driver callback object and do an initial query interface on it. - - This method only creates an instance of the driver's class factory, as this - is the minimum required to support UMDF. - - Arguments: - - ClassId - the CLSID of the object being "gotten" - - InterfaceId - the interface the caller wants from that object. - - Interface - a location to store the referenced interface pointer - - Return Value: - - S_OK if the function succeeds or error indicating the cause of the - failure. - ---*/ -{ - PCClassFactory factory; - - HRESULT hr = S_OK; - - *Interface = NULL; - - // - // If the CLSID doesn't match that of our "coclass" (defined in the IDL - // file) then we can't create the object the caller wants. This may - // indicate that the COM registration is incorrect, and another CLSID - // is referencing this drvier. - // - - if (IsEqualCLSID(ClassId, CLSID_MyDriverCoClass) == false) - { - Trace( - TRACE_LEVEL_ERROR, - L"ERROR: Called to create instance of unrecognized class (%!GUID!)", - &ClassId - ); - - return CLASS_E_CLASSNOTAVAILABLE; - } - - // - // Create an instance of the class factory for the caller. - // - - factory = new CClassFactory(); - - if (NULL == factory) - { - hr = E_OUTOFMEMORY; - } - - // - // Query the object we created for the interface the caller wants. After - // that we release the object. This will drive the reference count to - // 1 (if the QI succeeded an referenced the object) or 0 (if the QI failed). - // In the later case the object is automatically deleted. - // - - if (SUCCEEDED(hr)) - { - hr = factory->QueryInterface(InterfaceId, Interface); - factory->Release(); - } - - return hr; -} diff --git a/tests/projects/wdk/umdf/skeleton/driver.cpp b/tests/projects/wdk/umdf/skeleton/driver.cpp deleted file mode 100644 index d91b4b0b5..000000000 --- a/tests/projects/wdk/umdf/skeleton/driver.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved. - -Module Name: - - Driver.cpp - -Abstract: - - This module contains the implementation of the UMDF Skeleton Sample's - core driver callback object. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#include "internal.h" -#include "driver.tmh" - -HRESULT -CMyDriver::CreateInstance( - _Out_ PCMyDriver *Driver - ) -/*++ - - Routine Description: - - This static method is invoked in order to create and initialize a new - instance of the driver class. The caller should arrange for the object - to be released when it is no longer in use. - - Arguments: - - Driver - a location to store a referenced pointer to the new instance - - Return Value: - - S_OK if successful, or error otherwise. - ---*/ -{ - PCMyDriver driver; - HRESULT hr; - - // - // Allocate the callback object. - // - - driver = new CMyDriver(); - - if (NULL == driver) - { - return E_OUTOFMEMORY; - } - - // - // Initialize the callback object. - // - - hr = driver->Initialize(); - - if (SUCCEEDED(hr)) - { - // - // Store a pointer to the new, initialized object in the output - // parameter. - // - - *Driver = driver; - } - else - { - - // - // Release the reference on the driver object to get it to delete - // itself. - // - - driver->Release(); - } - - return hr; -} - -HRESULT -CMyDriver::Initialize( - VOID - ) -/*++ - - Routine Description: - - This method is called to initialize a newly created driver callback object - before it is returned to the creator. Unlike the constructor, the - Initialize method contains operations which could potentially fail. - - Arguments: - - None - - Return Value: - - None - ---*/ -{ - return S_OK; -} - -HRESULT -CMyDriver::QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Interface - ) -/*++ - - Routine Description: - - This method returns a pointer to the requested interface on the callback - object.. - - Arguments: - - InterfaceId - the IID of the interface to query/reference - - Interface - a location to store the interface pointer. - - Return Value: - - S_OK if the interface is supported. - E_NOINTERFACE if it is not supported. - ---*/ -{ - if (IsEqualIID(InterfaceId, __uuidof(IDriverEntry))) - { - *Interface = QueryIDriverEntry(); - return S_OK; - } - else - { - return CUnknown::QueryInterface(InterfaceId, Interface); - } -} - -HRESULT -CMyDriver::OnDeviceAdd( - _In_ IWDFDriver *FxWdfDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit - ) -/*++ - - Routine Description: - - The FX invokes this method when it wants to install our driver on a device - stack. This method creates a device callback object, then calls the Fx - to create an Fx device object and associate the new callback object with - it. - - Arguments: - - FxWdfDriver - the Fx driver object. - - FxDeviceInit - the initialization information for the device. - - Return Value: - - status - ---*/ -{ - HRESULT hr; - - PCMyDevice device = NULL; - - // - // TODO: Do any per-device initialization (reading settings from the - // registry for example) that's necessary before creating your - // device callback object here. Otherwise you can leave such - // initialization to the initialization of the device event - // handler. - // - - // - // Create a new instance of our device callback object - // - - hr = CMyDevice::CreateInstance(FxWdfDriver, FxDeviceInit, &device); - - // - // TODO: Change any per-device settings that the object exposes before - // calling Configure to let it complete its initialization. - // - - // - // If that succeeded then call the device's construct method. This - // allows the device to create any queues or other structures that it - // needs now that the corresponding fx device object has been created. - // - - if (SUCCEEDED(hr)) - { - hr = device->Configure(); - } - - // - // Release the reference on the device callback object now that it's been - // associated with an fx device object. - // - - if (NULL != device) - { - device->Release(); - } - - return hr; -} diff --git a/tests/projects/wdk/umdf/skeleton/driver.h b/tests/projects/wdk/umdf/skeleton/driver.h deleted file mode 100644 index e764f517d..000000000 --- a/tests/projects/wdk/umdf/skeleton/driver.h +++ /dev/null @@ -1,149 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved - -Module Name: - - Driver.h - -Abstract: - - This module contains the type definitions for the UMDF Skeleton sample's - driver callback class. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -// -// This class handles driver events for the skeleton sample. In particular -// it supports the OnDeviceAdd event, which occurs when the driver is called -// to setup per-device handlers for a new device stack. -// - -class CMyDriver : public CUnknown, public IDriverEntry -{ -// -// Private data members. -// -private: - -// -// Private methods. -// -private: - - // - // Returns a refernced pointer to the IDriverEntry interface. - // - - IDriverEntry * - QueryIDriverEntry( - VOID - ) - { - AddRef(); - return static_cast(this); - } - - HRESULT - Initialize( - VOID - ); - -// -// Public methods -// -public: - - // - // The factory method used to create an instance of this driver. - // - - static - HRESULT - CreateInstance( - _Out_ PCMyDriver *Driver - ); - -// -// COM methods -// -public: - - // - // IDriverEntry methods - // - - virtual - HRESULT - STDMETHODCALLTYPE - OnInitialize( - _In_ IWDFDriver *FxWdfDriver - ) - { - UNREFERENCED_PARAMETER( FxWdfDriver ); - - return S_OK; - } - - virtual - HRESULT - STDMETHODCALLTYPE - OnDeviceAdd( - _In_ IWDFDriver *FxWdfDriver, - _In_ IWDFDeviceInitialize *FxDeviceInit - ); - - virtual - VOID - STDMETHODCALLTYPE - OnDeinitialize( - _In_ IWDFDriver *FxWdfDriver - ) - { - UNREFERENCED_PARAMETER( FxWdfDriver ); - - return; - } - - // - // IUnknown methods. - // - // We have to implement basic ones here that redirect to the - // base class becuase of the multiple inheritance. - // - - virtual - ULONG - STDMETHODCALLTYPE - AddRef( - VOID - ) - { - return __super::AddRef(); - } - - _At_(this, __drv_freesMem(object)) - virtual - ULONG - STDMETHODCALLTYPE - Release( - VOID - ) - { - return __super::Release(); - } - - virtual - HRESULT - STDMETHODCALLTYPE - QueryInterface( - _In_ REFIID InterfaceId, - _Out_ PVOID *Object - ); -}; diff --git a/tests/projects/wdk/umdf/skeleton/exports.def b/tests/projects/wdk/umdf/skeleton/exports.def deleted file mode 100644 index 7d46558b7..000000000 --- a/tests/projects/wdk/umdf/skeleton/exports.def +++ /dev/null @@ -1,10 +0,0 @@ -; Skeleton.def : Declares the module parameters. - -; -; TODO: Change the library name here to match your binary name. -; - -LIBRARY "UMDFSkeleton.DLL" - -EXPORTS - DllGetClassObject PRIVATE diff --git a/tests/projects/wdk/umdf/skeleton/internal.h b/tests/projects/wdk/umdf/skeleton/internal.h deleted file mode 100644 index f338a9b6c..000000000 --- a/tests/projects/wdk/umdf/skeleton/internal.h +++ /dev/null @@ -1,90 +0,0 @@ -/*++ - -Copyright (C) Microsoft Corporation, All Rights Reserved - -Module Name: - - Internal.h - -Abstract: - - This module contains the local type definitions for the UMDF Skeleton - driver sample. - -Environment: - - Windows User-Mode Driver Framework (WUDF) - ---*/ - -#pragma once - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) -#endif - -// -// Include the WUDF DDI -// - -#include "wudfddi.h" - -// -// Use specstrings for in/out annotation of function parameters. -// - -#include "specstrings.h" - -// -// Forward definitions of classes in the other header files. -// - -typedef class CMyDriver *PCMyDriver; -typedef class CMyDevice *PCMyDevice; - -// -// Define the tracing flags. -// -// TODO: Choose a different trace control GUID -// - -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID( \ - MyDriverTraceControl, (e7541cdd,30e8,4b50,aeb0,51927330ae64), \ - \ - WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ - ) - -#define WPP_FLAG_LEVEL_LOGGER(flag, level) \ - WPP_LEVEL_LOGGER(flag) - -#define WPP_FLAG_LEVEL_ENABLED(flag, level) \ - (WPP_LEVEL_ENABLED(flag) && \ - WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) - -// -// This comment block is scanned by the trace preprocessor to define our -// Trace function. -// -// begin_wpp config -// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); -// end_wpp -// - -// -// Driver specific #defines -// -// TODO: Change these values to be appropriate for your driver. -// - -#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF\\Skeleton" -#define MYDRIVER_CLASS_ID { 0xd4112073, 0xd09b, 0x458f, { 0xa5, 0xaa, 0x35, 0xef, 0x21, 0xee, 0xf5, 0xde } } - - -// -// Include the type specific headers. -// - -#include "comsup.h" -#include "driver.h" -#include "device.h" diff --git a/tests/projects/wdk/umdf/skeleton/xmake.lua b/tests/projects/wdk/umdf/skeleton/xmake.lua deleted file mode 100644 index 8a48274ca..000000000 --- a/tests/projects/wdk/umdf/skeleton/xmake.lua +++ /dev/null @@ -1,13 +0,0 @@ -add_rules("mode.debug", "mode.release") - -add_defines("_UNICODE", "UNICODE") - -target("UMDFSkeleton") - add_rules("wdk.env.umdf", "wdk.driver") - add_values("wdk.tracewpp.flags", "-scan:internal.h") - add_files("*.cpp", {rule = "wdk.tracewpp"}) - add_files("*.rc", "*.inx") - set_values("wdk.umdf.sdkver", "1.9") - add_shflags("/DEF:exports.def", {force = true}) - add_shflags("/ENTRY:_DllMainCRTStartup" .. (is_arch("x86") and "@12" or ""), {force = true}) - diff --git a/tests/projects/wdk/wdm/msdsm/SampleDSM.inf b/tests/projects/wdk/wdm/msdsm/SampleDSM.inf deleted file mode 100644 index f632f6e50..000000000 Binary files a/tests/projects/wdk/wdm/msdsm/SampleDSM.inf and /dev/null differ diff --git a/tests/projects/wdk/wdm/msdsm/dsmmain.c b/tests/projects/wdk/wdm/msdsm/dsmmain.c deleted file mode 100644 index bdf875184..000000000 --- a/tests/projects/wdk/wdm/msdsm/dsmmain.c +++ /dev/null @@ -1,9752 +0,0 @@ -/*++ - -Copyright (C) 2004-2010 Microsoft Corporation - -Module Name: - - dsmmain.c - -Abstract: - - This driver is the Microsoft Device Specific Module (DSM). - It exports behaviours that mpio.sys will use to determine how to - multipath SPC-3 conforming devices. - - This file contains routines that are internal to MSDSM. - -Environment: - - kernel mode only - -Notes: - ---*/ - -#include "precomp.h" - -#ifdef DEBUG_USE_WPP -#include "dsmmain.tmh" -#endif - -#pragma warning (disable:4305) - -extern BOOLEAN DoAssert; - -#ifdef ALLOC_PRAGMA - #pragma alloc_text(PAGE, DsmpRegisterPersistentReservationKeys) -#endif - -VOID -DsmpFreeDSMResources( - _In_ IN PDSM_CONTEXT DsmContext - ) -/*++ - -Routine Description: - - This routine will free the resources allocated by the DSM. This routine - should be called when the DSM is being unloaded. - -Arguements: - - DsmContext - DSM context given to MPIO during initialization - -Return Value: - - None ---*/ -{ - PDSM_WMILIB_CONTEXT wmiInfo; - PVOID tempAddress = (PVOID)DsmContext; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmpFreeDSMResources (DsmCtxt %p): Entering function.\n", - DsmContext)); - - // - // First free the buffer allocated for storing the registry path. - // - wmiInfo = &gDsmInitData.DsmWmiInfo; - - if (wmiInfo->RegistryPath.Buffer) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_INIT, - "DsmpFreeDSMResources (DsmCtxt %p): Freeing wmiInfo's registry buffer.\n", - DsmContext)); - - DsmpFreePool(wmiInfo->RegistryPath.Buffer); - } - - if (DsmContext) { - PLIST_ENTRY entry; - PDSM_DEVICE_INFO deviceInfo; - PDSM_GROUP_ENTRY groupEntry; - PDSM_FAILOVER_GROUP failGroup; - PDSM_CONTROLLER_LIST_ENTRY controllerEntry; - - ExDeleteNPagedLookasideList(&(DsmContext->CompletionContextList)); - - // - // Free up the devices (DeviceInfo) list. - // - while (!IsListEmpty(&DsmContext->DeviceList)) { - - entry = DsmContext->DeviceList.Flink; - - NT_ASSERT(entry); - - deviceInfo = CONTAINING_RECORD(entry, DSM_DEVICE_INFO, ListEntry); - - if (deviceInfo) { - - DsmpRemoveDeviceFailGroup(DsmContext, deviceInfo->FailGroup, deviceInfo, TRUE); - DsmpRemoveDeviceEntry(DsmContext, deviceInfo->Group, deviceInfo); - } - } - - NT_ASSERT(!DsmContext->NumberDevices && - !DsmContext->NumberFOGroups && - !DsmContext->NumberGroups); - - // - // By now, there should be no group entries left but play it safe and - // free up the GROUP list. - // - while (!IsListEmpty(&DsmContext->GroupList)) { - - entry = DsmContext->GroupList.Flink; - - NT_ASSERT(entry); - - groupEntry = CONTAINING_RECORD(entry, DSM_GROUP_ENTRY, ListEntry); - - if (groupEntry) { - - DsmpRemoveGroupEntry(DsmContext, groupEntry, TRUE); - - DsmpFreePool(groupEntry); - } - } - - // - // By now there should be no FOG entries left but we play it safe and - // free up the FOG list. - // - while (!IsListEmpty(&DsmContext->FailGroupList)) { - - entry = RemoveHeadList(&DsmContext->FailGroupList); - - if (entry) { - - failGroup = CONTAINING_RECORD(entry, DSM_FAILOVER_GROUP, ListEntry); - - if (failGroup) { - - PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry = NULL; - PLIST_ENTRY deviceEntry = NULL; - - while (!IsListEmpty(&failGroup->FOG_DeviceList)) { - - deviceEntry = RemoveHeadList(&failGroup->FOG_DeviceList); - - if (deviceEntry) { - - fogDeviceListEntry = CONTAINING_RECORD(deviceEntry, DSM_FOG_DEVICELIST_ENTRY, ListEntry); - - if (!fogDeviceListEntry) { - continue; - } - - (fogDeviceListEntry->DeviceInfo)->FailGroup = NULL; - - DsmpFreePool(fogDeviceListEntry); - InterlockedDecrement((LONG volatile*)&failGroup->Count); - } - } - - DsmpFreeZombieGroupList(failGroup); - DsmpFreePool(failGroup); - InterlockedDecrement((LONG volatile*)&DsmContext->NumberFOGroups); - } - } - } - - // - // Free up the controller list. - // - while (!IsListEmpty(&DsmContext->ControllerList)) { - - entry = RemoveHeadList(&DsmContext->ControllerList); - - if (entry) { - - controllerEntry = CONTAINING_RECORD(entry, DSM_CONTROLLER_LIST_ENTRY, ListEntry); - - if (controllerEntry) { - - DsmpFreeControllerEntry(DsmContext, controllerEntry); - - InterlockedDecrement((LONG volatile*)&DsmContext->NumberControllers); - } - } - } - - NT_ASSERT(!DsmContext->NumberControllers); - - // - // Free up the stale FOG list. - // - while (!IsListEmpty(&DsmContext->StaleFailGroupList)) { - - entry = RemoveHeadList(&DsmContext->StaleFailGroupList); - - if (entry) { - - failGroup = CONTAINING_RECORD(entry, DSM_FAILOVER_GROUP, ListEntry); - - if (failGroup) { - - InterlockedDecrement((LONG volatile*)&DsmContext->NumberStaleFOGroups); - NT_ASSERT(IsListEmpty(&failGroup->FOG_DeviceList)); - DsmpFreeZombieGroupList(failGroup); - DsmpFreePool(failGroup); - } - } - } - - // - // Free up the supported devices list buffer. - // - DsmpFreePool(DsmContext->SupportedDevices.Buffer); - - // - // It's the responsibility of the mpio bus driver to have already - // destroyed all devices and paths. As those functions free allocations - // for the objects, the only thing needed here is to free the DsmContext. - // - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_INIT, - "DsmpFreeDSMResources (DsmCtxt %p): Freeing the DsmContext.\n", - DsmContext)); - - DsmpFreePool(DsmContext); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmpFreeDSMResources (DsmCtxt %p): Exiting function.\n", - tempAddress)); - - return; -} - - -PDSM_GROUP_ENTRY -DsmpFindDevice( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN BOOLEAN AcquireDSMLockExclusive - ) -/*++ - -Routine Description: - - This routine searches for a serial number match between DeviceInfo and - the rest of the devices currently being driven by this DSM. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DeviceInfo - The deviceInfo containing serial number for which to search. - AcquireDSMLockExclusive - If TRUE this routine should acquire DsmContextLock Exclusively - -Return Value: - - The multi-path group entry in which the device resides. - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo; - PLIST_ENTRY entry; - PDSM_GROUP_ENTRY groupEntry = NULL; - ULONG i; - KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFindDevice (DevInfo %p): Entering function.\n", - DeviceInfo)); - - if (AcquireDSMLockExclusive) { - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - } - - // - // Run through the DeviceInfo List - // - entry = DsmContext->DeviceList.Flink; - for (i = 0; i < DsmContext->NumberDevices; i++, entry = entry->Flink) { - - // - // Extract the deviceInfo structure. - // - deviceInfo = CONTAINING_RECORD(entry, DSM_DEVICE_INFO, ListEntry); - DSM_ASSERT(deviceInfo); - - if (deviceInfo) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpFindDevice (DevInfo %p): Comparing with %p.\n", - DeviceInfo, - deviceInfo)); - - // - // Call the Serial Number compare routine. - // - if (DsmCompareDevices(DsmContext, - DeviceInfo, - deviceInfo)) { - - groupEntry = deviceInfo->Group; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpFindDevice (DevInfo %p): Found matching multi-path group %p.\n", - DeviceInfo, - groupEntry)); - - break; - } - } - } - - if (AcquireDSMLockExclusive) { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFindDevice (DevInfo %p): Exiting function with groupEntry %p.\n", - DeviceInfo, - groupEntry)); - - return groupEntry; -} - - -PDSM_GROUP_ENTRY -DsmpBuildGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - This will allocate and partially initialise a multi-path group entry. - - N.B: This routine must be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DeviceInfo - The first device to be added to the group. - -Return Value: - - The new group entry. - ---*/ -{ - PDSM_GROUP_ENTRY group; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildGroupEntry (DevInfo %p): Entering function.\n", - DeviceInfo)); - - // - // Allocate the memory for the multi-path group. - // - group = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_GROUP_ENTRY), - DSM_TAG_GROUP_ENTRY); - - if (group) { - - InitializeListHead(&group->FailingDevInfoList); - group->GroupNumber = InterlockedIncrement((LONG volatile*)&DsmContext->NumberGroups); - group->GroupSig = DSM_GROUP_SIG; - group->State = DSM_GP_NORMAL; - - // - // Add it to the list of multi-path groups. - // - InsertTailList(&DsmContext->GroupList, &group->ListEntry); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildGroupEntry (DevInfo %p): Failed to allocate memory for the group.\n", - DeviceInfo)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildGroupEntry (DevInfo %p): Exiting function with group %p.\n", - DeviceInfo, - group)); - - return group; -} - - -NTSTATUS -DsmpParseTargetPortGroupsInformation( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, - _In_ IN ULONG TargetPortGroupsInfoLength - ) -/*++ - -Routine Description: - - This will parse the information returned back from a previously - made call to ReportTargetPortGroups and build new TPG entries or - update old ones. - - N.B: This routine must be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DsmContext - Group - group entry - TargetPortGroupsInfo - Pointer to the ReportTPG returned buffer. - TargetPortGroupsInfoLength - length of the buffer. - -Return Value: - - STATUS_SUCCESS or appropriate error code. - ---*/ -{ - PUCHAR targetPortGroupsInfoIndex; - ULONG bytes = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroupEntry = NULL; - ULONG descriptorSize = 0; - NTSTATUS status = STATUS_SUCCESS; - ULONG index; - DSM_DEVICE_STATE tpgState = DSM_DEV_NOT_USED_STATE; - ULONG bytesLeft; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpParseTargetPortGroupsInformation (Group %p): Entering function.\n", - Group)); - - targetPortGroupsInfoIndex = TargetPortGroupsInfo + bytes; - bytesLeft = TargetPortGroupsInfoLength - bytes; - - while (bytes < TargetPortGroupsInfoLength && NT_SUCCESS(status)) { - - targetPortGroupEntry = DsmpFindTargetPortGroupEntry(DsmContext, - Group, - targetPortGroupsInfoIndex, - bytesLeft); - - if (targetPortGroupEntry) { - - targetPortGroupEntry = DsmpUpdateTargetPortGroupEntry(DsmContext, - targetPortGroupEntry, - targetPortGroupsInfoIndex, - bytesLeft, - &descriptorSize); - } else { - - targetPortGroupEntry = DsmpBuildTargetPortGroupEntry(DsmContext, - Group, - targetPortGroupsInfoIndex, - bytesLeft, - &descriptorSize); - - if (targetPortGroupEntry) { - - // - // Insert this TPG entry into array - // - for (index = 0; index < DSM_MAX_PATHS; index++) { - - if (!Group->TargetPortGroupList[index]) { - - Group->TargetPortGroupList[index] = targetPortGroupEntry; - InterlockedIncrement((LONG volatile*)&Group->NumberTargetPortGroups); - targetPortGroupEntry->Group = Group; - break; - } - } - - if (index == DSM_MAX_PATHS) { - - NT_ASSERT(index < DSM_MAX_PATHS); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpParseTargetPortGroupsInformation (Group %p): Number of paths exceeded max supported.\n", - Group)); - - status = STATUS_UNSUCCESSFUL; - goto __Exit_DsmpParseTargetPortGroupsInformation; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpParseTargetPortGroupsInformation (Group %p): Insufficient resources to build TPG.\n", - Group)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) { - - // - // If this is the first TPG being parsed, save off its AA state. - // - if (tpgState == DSM_DEV_NOT_USED_STATE) { - - tpgState = targetPortGroupEntry->AsymmetricAccessState; - - } else { - - // - // Check if this TPG's AA state differs from the previous one's. - // Symmetric LU access means that TPG access states must be the - // same for TPGs. If this one is different, we know that the - // device supports Asymmetric LU access. - // - if (tpgState != targetPortGroupEntry->AsymmetricAccessState) { - - Group->Symmetric = FALSE; - } - } - } - - if (targetPortGroupEntry) { - - // - // Set the flag to indicate that we've encountered this TPG in the RTPG information. - // - targetPortGroupEntry->Traversed = TRUE; - } - - bytes += descriptorSize; - targetPortGroupsInfoIndex += descriptorSize; - bytesLeft -= descriptorSize; - } - - // - // Since we've gone through the entire information reported by back RTPG, it - // is now time to delete the stale entries. - // - for (index = 0; index < DSM_MAX_PATHS; index++) { - - targetPortGroupEntry = Group->TargetPortGroupList[index]; - - if (targetPortGroupEntry) { - - if (targetPortGroupEntry->Traversed) { - - // - // Entry needs to continue to exist. Reset the flag and continue. - // - targetPortGroupEntry->Traversed = FALSE; - continue; - - } else { - - PLIST_ENTRY entry; - PLIST_ENTRY tempEntry; - PDSM_TARGET_PORT_LIST_ENTRY targetPort; - - // - // For this target port group, clean up all its target ports if - // the port doesn't expose any instance of this device. - // - for (entry = targetPortGroupEntry->TargetPortList.Flink; - entry != NULL && entry != &targetPortGroupEntry->TargetPortList; - entry = entry->Flink) { - - targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); - - if (targetPort) { - - // - // If the TP doesn't expose this device, it is safe - // to delete it. - // - if (IsListEmpty(&targetPort->TP_DeviceList)) { - - tempEntry = entry; - entry = entry->Blink; - - RemoveEntryList(tempEntry); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpParseTargetPortGroupsInformation (Group %p): Deleting empty target port %p from TPG %p list.\n", - Group, - targetPort, - targetPortGroupEntry)); - - DsmpFreePool(targetPort); - - InterlockedDecrement((LONG volatile*)&targetPortGroupEntry->NumberTargetPorts); - } - } - } - - // - // If the TPG doesn't have any TPs, it is safe to delete it. - // - if (!targetPortGroupEntry->NumberTargetPorts) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpParseTargetPortGroupsInformation (Group %p): Deleting target port group %p.\n", - Group, - targetPortGroupEntry)); - - DsmpFreePool(targetPortGroupEntry); - - InterlockedDecrement((LONG volatile*)&Group->NumberTargetPortGroups); - - Group->TargetPortGroupList[index] = NULL; - } - } - } - } - -__Exit_DsmpParseTargetPortGroupsInformation: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpParseTargetPortGroupsInformation (Group %p): Exiting function with status %x\n", - Group, - status)); - - return status; -} - - -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpFindTargetPortGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, - _In_ IN ULONG TPGs_BufferLength - ) -/*++ - -Routine Description: - - This will search the group's TPG array to look for an identifier match. - - N.B: This routine must be called with DsmContextLock held in either Shared - or Exclusive mode. - -Arguments: - - DsmContext - DsmContext - Group - group entry - TargetPortGroupsDescriptor - Pointer to the TPG descriptor. - TPGs_BufferLength - Length of the passed in TargetPortGroupsDescriptor buffer. - -Return Value: - - Pointer to the array element that matches, else NULL. - ---*/ -{ - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = NULL; - PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR descriptor = (PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR)TargetPortGroupsDescriptor; - ULONG index; - BOOLEAN found = FALSE; - USHORT identifier = ((descriptor->TPG_Identifier & 0x00FF) << 8) | ((descriptor->TPG_Identifier & 0xFF00) >> 8); - - UNREFERENCED_PARAMETER(TPGs_BufferLength); - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPortGroupEntry (Group %p): Entering function.\n", - Group)); - - for (index = 0; index < DSM_MAX_PATHS && !found; index++) { - - targetPortGroup = Group->TargetPortGroupList[index]; - - if (targetPortGroup) { - - if (targetPortGroup->Identifier == identifier) { - - found = TRUE; - } - } - } - - if (!found) { - targetPortGroup = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPortGroupEntry (Group %p): Exiting function with targetPortGroup %p.\n", - Group, - targetPortGroup)); - - return targetPortGroup; -} - -_Success_(return!=0) -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpUpdateTargetPortGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, - _In_ IN ULONG TPGs_BufferLength, - _Out_ OUT PULONG DescriptorSize - ) -/*++ - -Routine Description: - - This routine will update the target port group with information contained - in the passed in descriptor. - - N.B: This routine must be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DsmContext - TargetPortGroup - Pointer to the TPG entry to update. - TargetPortGroupsDescriptor - Pointer to the TPG descriptor. - TPGs_BufferLength - Length of the passed in TargetPortGroupsDescriptor buffer. - DescriptorSize - return value of the size of the descriptor. - -Return Value: - - The updated target port group entry on success, NULL in case of failure. - ---*/ -{ - PLIST_ENTRY entry; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = TargetPortGroup; - PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR descriptor = (PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR)TargetPortGroupsDescriptor; - ULONG numberTargetPorts = 0; - PULONG descriptorIndex; - ULONG index; - PDSM_TARGET_PORT_LIST_ENTRY listEntry; - NTSTATUS status = STATUS_SUCCESS; - ULONG identifier; - PLIST_ENTRY tempEntry = NULL; - ULONG delCount; - PUCHAR endOfBuffer = TargetPortGroupsDescriptor + TPGs_BufferLength - 1; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Entering function.\n", - TargetPortGroup)); - - if (DescriptorSize == NULL) { - status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Status %x due to null passed in DescriptorSize pointer\n", - TargetPortGroup, - status)); - - goto __Exit_DsmpUpdateTargetPortGroupEntry; - } - - *DescriptorSize = sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - (targetPortGroup->NumberTargetPorts * sizeof(ULONG)); - - if (((PUCHAR)descriptor + sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) - 1) > endOfBuffer) { - - status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Status %x due to incorrect passed in TPG buffer size (%u).\n", - TargetPortGroup, - status, - TPGs_BufferLength)); - - goto __Exit_DsmpUpdateTargetPortGroupEntry; - } - - identifier = ((descriptor->TPG_Identifier & 0x00FF) << 8) | ((descriptor->TPG_Identifier & 0xFF00) >> 8); - NT_ASSERT(targetPortGroup->Identifier == (USHORT)identifier); - NT_ASSERT(targetPortGroup->ActiveOptimizedSupported == (descriptor->ActiveOptimizedSupported) ? TRUE : FALSE); - NT_ASSERT(targetPortGroup->ActiveUnoptimizedSupported == (descriptor->ActiveUnoptimizedSupported) ? TRUE : FALSE); - NT_ASSERT(targetPortGroup->StandBySupported == (descriptor->StandbySupported) ? TRUE : FALSE); - NT_ASSERT(targetPortGroup->UnavailableSupported == (descriptor->UnavailableSupported) ? TRUE : FALSE); - NT_ASSERT(targetPortGroup->TransitioningSupported == (descriptor->TransitioningSupported) ? TRUE : FALSE); - DSM_ASSERT(targetPortGroup->VendorUnique == descriptor->VendorUnique); - - // - // It is possible that the asymmetric access state, status code and number of port - // may have changed - // - if ((targetPortGroup->AsymmetricAccessState) != (descriptor->AsymmetricAccessState & 0xF)) - { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Asymmetric access state has changed.\n", - TargetPortGroup)); - - - targetPortGroup->AsymmetricAccessState = descriptor->AsymmetricAccessState & 0xF; - } - - targetPortGroup->Preferred = (descriptor->Preferred) ? TRUE : FALSE; - - targetPortGroup->StatusCode = descriptor->StatusCode; - - numberTargetPorts = descriptor->NumberTargetPorts; - - NT_ASSERT(numberTargetPorts > 0); - - // - // Point to first target port identifier - // - descriptorIndex = descriptor->TargetPortIds; - - for (index = 0; index < numberTargetPorts && NT_SUCCESS(status); index++) { - - if (((PUCHAR)descriptorIndex + ((index + 1) * sizeof(ULONG)) - 1) > endOfBuffer) { - - status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Status %x due to incorrect TPG buffer size (%u) passed in.\n", - TargetPortGroup, - status, - TPGs_BufferLength)); - - goto __Exit_DsmpUpdateTargetPortGroupEntry; - } - - GetUlongFrom4ByteArray((PUCHAR)(&descriptorIndex[index]), identifier); - - listEntry = DsmpFindTargetPortListEntry(DsmContext, - targetPortGroup, - identifier); - - if (listEntry) { - - RemoveEntryList(&listEntry->ListEntry); - InsertHeadList(&targetPortGroup->TargetPortList, &listEntry->ListEntry); - - } else { - - listEntry = DsmpBuildTargetPortListEntry(DsmContext, - targetPortGroup, - identifier); - - if (listEntry) { - - InsertHeadList(&targetPortGroup->TargetPortList, &listEntry->ListEntry); - InterlockedIncrement((LONG volatile*)&targetPortGroup->NumberTargetPorts); - - } else { - - status = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Failed to allocate TargetPort (identifier %x).\n", - TargetPortGroup, - identifier)); - } - } - } - - // - // Ignore the status & carry on. Even if we weren't able to build TP entries - // for the new target ports, we are no worse off than before. - // - DSM_ASSERT(NT_SUCCESS(status)); - - *DescriptorSize = sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - (numberTargetPorts * sizeof(ULONG)); - - for (index = 0, entry = targetPortGroup->TargetPortList.Flink; - index < numberTargetPorts; - index++, entry = entry->Flink); - - delCount = targetPortGroup->NumberTargetPorts - numberTargetPorts; - - for (index = 0; index < delCount; index++) { - - tempEntry = entry; - entry = entry->Flink; - - RemoveEntryList(tempEntry); - InterlockedDecrement((LONG volatile*)&targetPortGroup->NumberTargetPorts); - - listEntry = CONTAINING_RECORD(tempEntry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); - NT_ASSERT(listEntry); - - if (listEntry) { - - PLIST_ENTRY deviceEntry; - PDSM_TARGET_PORT_DEVICELIST_ENTRY tp_device; - - while (!IsListEmpty(&listEntry->TP_DeviceList)) { - - deviceEntry = RemoveHeadList(&listEntry->TP_DeviceList); - InterlockedDecrement((LONG volatile*)&listEntry->Count); - - if (deviceEntry) { - - tp_device = CONTAINING_RECORD(deviceEntry, DSM_TARGET_PORT_DEVICELIST_ENTRY, ListEntry); - - if (tp_device) { - - if (tp_device->DeviceInfo) { - - tp_device->DeviceInfo->TargetPort = NULL; - } - - DsmpFreePool(tp_device); - } - } - } - - DsmpFreePool(listEntry); - } - } - -__Exit_DsmpUpdateTargetPortGroupEntry: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupEntry (TPG %p): Exiting function.\n", - targetPortGroup)); - - return targetPortGroup; -} - - -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpBuildTargetPortGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, - _In_ IN ULONG TPGs_BufferLength, - _Out_ OUT PULONG DescriptorSize - ) -/*++ - -Routine Description: - - This will allocate and partially initialise a target port group entry. - - N.B: This routine must be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DsmContext - Group - The group that this newly going to be built TPG belongs to. - TargetPortGroupsDescriptor - Pointer to the TPG descriptor. - TPGs_BufferLength - Length of the passed in TargetPortGroupsDescriptor buffer. - DescriptorSize - return value of the size of the descriptor. - -Return Value: - - The new target port group entry. - ---*/ -{ - PDSM_TARGET_PORT_GROUP_ENTRY entry = NULL; - PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR descriptor = (PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR)TargetPortGroupsDescriptor; - ULONG numberTargetPorts = 0; - PULONG descriptorIndex; - ULONG index = 0; - PDSM_TARGET_PORT_LIST_ENTRY listEntry; - NTSTATUS status = STATUS_SUCCESS; - ULONG identifier; - PUCHAR endOfBuffer = TargetPortGroupsDescriptor + TPGs_BufferLength - 1; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Entering function.\n", - Group)); - - if (DescriptorSize == NULL) { - - status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Status %x due to null passed in DescriptorSize pointer\n", - Group, - status)); - - goto __Exit_DsmpBuildTargetPortGroupEntry; - } - - *DescriptorSize = 0; - - if (((PUCHAR)descriptor + sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) - 1) > endOfBuffer) { - - status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Status %x due to incorrect passed in TPG buffer size (%u).\n", - Group, - status, - TPGs_BufferLength)); - - goto __Exit_DsmpBuildTargetPortGroupEntry; - } - - // - // Allocate the memory for the multi-path group. - // - entry = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_TARGET_PORT_GROUP_ENTRY), - DSM_TAG_TARGET_PORT_GROUP_ENTRY); - - if (entry) { - - entry->TargetPortGroupSig = DSM_TARGET_PORT_GROUP_SIG; - - // - // Target Port Group's access state - // - entry->AsymmetricAccessState = descriptor->AsymmetricAccessState & 0xF; - - // - // Target Port Group's supported states - // - entry->ActiveOptimizedSupported = (descriptor->ActiveOptimizedSupported) ? TRUE : FALSE; - entry->ActiveUnoptimizedSupported = (descriptor->ActiveUnoptimizedSupported) ? TRUE : FALSE; - entry->StandBySupported = (descriptor->StandbySupported) ? TRUE : FALSE; - entry->UnavailableSupported = (descriptor->UnavailableSupported) ? TRUE : FALSE; - - // - // Target Port Group's Preference and support for reporting transitioning - // - entry->Preferred = (descriptor->Preferred) ? TRUE : FALSE; - entry->TransitioningSupported = (descriptor->TransitioningSupported) ? TRUE : FALSE; - - // - // Target Port Group's identifier - // - entry->Identifier = ((descriptor->TPG_Identifier & 0x00FF) << 8) | ((descriptor->TPG_Identifier & 0xFF00) >> 8); - - // - // Target Port Group's status code - // - entry->StatusCode = descriptor->StatusCode; - - // - // Vendor unique - // - entry->VendorUnique = descriptor->VendorUnique; - - // - // Number of target ports - // - numberTargetPorts = descriptor->NumberTargetPorts; - - NT_ASSERT(numberTargetPorts > 0); - - // - // Point to first target port identifier - // - descriptorIndex = descriptor->TargetPortIds; - - InitializeListHead(&entry->TargetPortList); - - for (index = 0; index < numberTargetPorts && NT_SUCCESS(status); index++) { - - if (((PUCHAR)descriptorIndex + ((index + 1) * sizeof(ULONG)) - 1) > endOfBuffer) { - - status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Status %x due to incorrect TPG buffer size (%u) passed in.\n", - Group, - status, - TPGs_BufferLength)); - - break; - } - - GetUlongFrom4ByteArray((PUCHAR)(&descriptorIndex[index]), identifier); - - listEntry = DsmpBuildTargetPortListEntry(DsmContext, - entry, - identifier); - - if (listEntry) { - - InsertTailList(&entry->TargetPortList, &listEntry->ListEntry); - InterlockedIncrement((LONG volatile*)&entry->NumberTargetPorts); - - } else { - - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Failed to allocate memory for TP (identifier %x) of TPG %p.\n", - Group, - identifier, - entry)); - } - } - - if (NT_SUCCESS(status)) { - *DescriptorSize = sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - (numberTargetPorts * sizeof(ULONG)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Failed to allocate memory for the TPG.\n", - Group)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - - if (!NT_SUCCESS(status)) { - - // - // Delete the target port list and the target port group entry - // - numberTargetPorts = index - 1; - - if (entry) { - - PLIST_ENTRY delEntry; - - for (index = 0; index < numberTargetPorts; index++) { - - delEntry = RemoveHeadList(&entry->TargetPortList); - listEntry = CONTAINING_RECORD(delEntry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Cleaning up TPG %p's TP %x.\n", - Group, - entry, - listEntry->Identifier)); - - DsmpFreePool(listEntry); - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Cleaning up TPG %p.\n", - Group, - entry)); - - DsmpFreePool(entry); - entry = NULL; - } - } - -__Exit_DsmpBuildTargetPortGroupEntry: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortGroupEntry (Group %p): Exiting function with entry %p.\n", - Group, - entry)); - - return entry; -} - - -PDSM_TARGET_PORT_LIST_ENTRY -DsmpFindTargetPortListEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN ULONG RelativeTargetPortId - ) -/*++ - -Routine Description: - - This will search the passed in TPG's target port list for an identifier match. - - N.B: This routine must be called with DsmContextLock held in either Shared or - Exclusive mode. - -Arguments: - - DsmContext - DsmContext - TargetPortGroup - The Target Port Group whose target ports need to be searched. - RelativeTargetPortId - Identifier of the target port entry being matched. - -Return Value: - - The target port list entry if match found, else NULL. - ---*/ -{ - PLIST_ENTRY entry = NULL; - PDSM_TARGET_PORT_LIST_ENTRY targetPort = NULL; - BOOLEAN found = FALSE; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPortListEntry (TPG %p): Entering function.\n", - TargetPortGroup)); - - for (entry = TargetPortGroup->TargetPortList.Flink; - entry != &TargetPortGroup->TargetPortList && !found; - entry = entry->Flink) { - - targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); - NT_ASSERT(targetPort); - - if (targetPort) { - - if (targetPort->Identifier == RelativeTargetPortId) { - - NT_ASSERT(targetPort->TargetPortGroup == TargetPortGroup); - - found = TRUE; - } - } - } - - if (!found) { - targetPort = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPortListEntry (TPG %p): Exiting function with target port %p.\n", - TargetPortGroup, - targetPort)); - - return targetPort; -} - - -PDSM_TARGET_PORT_LIST_ENTRY -DsmpBuildTargetPortListEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN ULONG RelativeTargetPortId - ) -/*++ - -Routine Description: - - This will allocate and partially initialize a target port list entry. - - N.B: This routine must be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DsmContext - TargetPortGroup - The Target Port Group that this target port belongs to. - RelativeTargetPortId - Identifier of the target port entry being added. - -Return Value: - - The new target port list entry. - ---*/ -{ - PDSM_TARGET_PORT_LIST_ENTRY entry; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortListEntry (TPG %p): Entering function.\n", - TargetPortGroup)); - - entry = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_TARGET_PORT_LIST_ENTRY), - DSM_TAG_TARGET_PORT_LIST_ENTRY); - - if (entry) { - - InitializeListHead(&entry->TP_DeviceList); - - entry->Identifier = RelativeTargetPortId; - entry->TargetPortGroup = TargetPortGroup; - entry->TargetPortSig = DSM_TARGET_PORT_SIG; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortListEntry (TPG %p): Failed to allocate memory for target port (identifier %x).\n", - TargetPortGroup, - RelativeTargetPortId)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpBuildTargetPortListEntry (TPG %p): Exiting function with entry %p.\n", - TargetPortGroup, - entry)); - - return entry; -} - - -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpFindTargetPortGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PUSHORT TargetPortGroupId - ) -/*++ - -Routine Description: - - This routine searches the list of TargetPortGroups of a Group to - find a match for the passed in TargetPortGroupId. - - N.B: This routine must be called with DsmContextLock held in either Shared or - Exclusive mode. - -Arguments: - - DsmContext - DSM context. - Group - The group whose target port groups to search for a match. - TargetPortGroupId - Identifier of the target port group entry being searched. - -Return Value: - - The target port group entry which matches the passed in identifier. - ---*/ -{ - ULONG index; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroupEntry = NULL; - BOOLEAN found = FALSE; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPortGroup (Group %p): Entering function.\n", - Group)); - - // - // Run through the target port group array - // - for (index = 0; index < DSM_MAX_PATHS && !found; index++) { - - targetPortGroupEntry = Group->TargetPortGroupList[index]; - - if (targetPortGroupEntry) { - - if (targetPortGroupEntry->Identifier == *TargetPortGroupId) { - - found = TRUE; - } - } - } - - if (!found) { - - targetPortGroupEntry = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPortGroup (Group %p): Exiting function with targetPortGroupEntry %p.\n", - Group, - targetPortGroupEntry)); - - return targetPortGroupEntry; -} - - -PDSM_TARGET_PORT_LIST_ENTRY -DsmpFindTargetPort( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN PULONG TargetPortGroupId - ) -/*++ - -Routine Description: - - This routine searches the list of TargetPorts to - find a match for the passed in TargetPortGroup and RelativeTargetPortId. - - N.B. Spin lock must be held by caller. - -Arguments: - - DsmContext - DSM context. - TargetPortGroup - the Target Port Group of which this target port is a member. - RelativeTargetPortId - Identifier of the target port entry being searched. - -Return Value: - - The target port entry which matches the passed in identifier. - ---*/ -{ - PLIST_ENTRY entry; - PDSM_TARGET_PORT_LIST_ENTRY targetPortListEntry = NULL; - BOOLEAN found = FALSE; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPort (TPG %p): Entering function.\n", - TargetPortGroup)); - - // - // Run through the Target Port List - // - for (entry = TargetPortGroup->TargetPortList.Flink; - entry != &TargetPortGroup->TargetPortList && !found; - entry = entry->Flink) { - - // - // Extract the target port group structure. - // - targetPortListEntry = CONTAINING_RECORD(entry, - DSM_TARGET_PORT_LIST_ENTRY, - ListEntry); - NT_ASSERT(targetPortListEntry); - - if (targetPortListEntry) { - - NT_ASSERT(TargetPortGroup == targetPortListEntry->TargetPortGroup); - - // - // Compare with passed in identifier. - // - if (targetPortListEntry->Identifier == *TargetPortGroupId) { - - found = TRUE; - } - } - } - - if (!found) { - - targetPortListEntry = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindTargetPort (TPG %p): Exiting function with targetPortListEntry %p.\n", - TargetPortGroup, - targetPortListEntry)); - - return targetPortListEntry; -} - - -NTSTATUS -DsmpAddDeviceEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - This routine adds DeviceInfo to an existing multi-path group. - - N.B: This routine MUST be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - Group - The multi-path group to which DeviceInfo should be added. - DeviceInfo - The new device. - DeviceState - The initial device state (active, passive,...) - -Return Value: - - UNSUCCESSFUL - If there are too many paths already. - SUCCESS - ---*/ -{ - ULONG numberDevices; - NTSTATUS status = STATUS_SUCCESS; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpAddDeviceEntry (DevInfo %p): Entering function.\n", - DeviceInfo)); - - // - // Ensure that this is a valid config - namely, it hasn't - // exceeded the number of paths supported. - // - numberDevices = * (volatile ULONG *) &Group->NumberDevices; - if (numberDevices < DSM_MAX_PATHS) { - -#if DBG - ULONG i; - - // - // Ensure that this isn't a second copy of the same pdo. - // - for (i = 0; i < numberDevices; i++) { - if (Group->DeviceList[i]->PortPdo == DeviceInfo->PortPdo) { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpAddDeviceEntry (DevInfo %p): Received same PDO %p twice.\n", - DeviceInfo, - DeviceInfo->PortPdo)); - } - } -#endif - - // - // Indicate one more device is present in this group. - // - Group->DeviceList[numberDevices] = DeviceInfo; - - // - // Indicate one more in the list. - // - InterlockedIncrement((LONG volatile*)&Group->NumberDevices); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpAddDeviceEntry (DevInfo %p): Adding Device to Group %p\n", - DeviceInfo, - Group)); - - // - // Set-up this device's group id. - // - DeviceInfo->Group = Group; - - // - // One more deviceInfo entry. - // - InterlockedIncrement((LONG volatile*)&DsmContext->NumberDevices); - - // - // Finally, add it to the global list of devices. - // - InsertTailList(&DsmContext->DeviceList, - &DeviceInfo->ListEntry); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpAddDeviceEntry (DevInfo %p): Max Paths already added for Group %p.\n", - DeviceInfo, - Group)); - - status = STATUS_UNSUCCESSFUL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpAddDeviceEntry (DevInfo %p): Exiting function with status %x.\n", - DeviceInfo, - status)); - - return status; -} - - -PDSM_CONTROLLER_LIST_ENTRY -DsmpFindControllerEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDEVICE_OBJECT PortObject, - _In_ IN PSCSI_ADDRESS ScsiAddress, - _In_reads_(ControllerSerialNumberLength) IN PSTR ControllerSerialNumber, - _In_ IN SIZE_T ControllerSerialNumberLength, - _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, - _In_ IN BOOLEAN AcquireLock - ) -/*++ - -Routine Description: - - This routine compares the passed in serial number and SCSI address with the - entries in the list of controller objects. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization. - PortObject - Port FDO exposing the controller. - ScsiAddress - The scsi address to match. - ControllerSerialNumber - The serial number for which to find a match. - ControllerSerialNumberLength - Length of the passed in serial number, in bytes. - CodeSet - Code set used when building the passed in serial number. - AcquireLock - FALSE indicates that the caller has already acquired the spin lock. - -Return Value: - - Controller list entry if a match is found, else NULL - ---*/ -{ - KIRQL oldIrql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error - PLIST_ENTRY entry; - PDSM_CONTROLLER_LIST_ENTRY controllerEntry = NULL; - BOOLEAN found = FALSE; - PDSM_CONTROLLER_LIST_ENTRY candidate = NULL; - - UNREFERENCED_PARAMETER(CodeSet); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFindControllerEntry (SN %s): Entering function.\n", - ControllerSerialNumber)); - - if (AcquireLock) { - - oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - } - - for (entry = DsmContext->ControllerList.Flink; - entry != &DsmContext->ControllerList && !found; - entry = entry->Flink) { - - controllerEntry = CONTAINING_RECORD(entry, DSM_CONTROLLER_LIST_ENTRY, ListEntry); - NT_ASSERT(controllerEntry); - - if (!controllerEntry) { - - continue; - } - - // - // Serial numbers and Portal, Bus, and Target of the SCSI address must match. - // - if (!strncmp((const char*)controllerEntry->Identifier, - ControllerSerialNumber, - ControllerSerialNumberLength) && - (controllerEntry->ScsiAddress->PortNumber == ScsiAddress->PortNumber && - controllerEntry->ScsiAddress->PathId == ScsiAddress->PathId && - controllerEntry->ScsiAddress->TargetId == ScsiAddress->TargetId)) { - - if (controllerEntry->IdLength == ControllerSerialNumberLength) { - - found = TRUE; - - } else { - - if ((!candidate) || - (controllerEntry->IdLength > ControllerSerialNumberLength && ControllerSerialNumberLength == 32)) { - - candidate = controllerEntry; - } - } - } - } - - if (!found) { - - if (candidate) { - - controllerEntry = candidate; - - } else { - - controllerEntry = NULL; - } - } - - // - // If we found a matching controller entry, we need to make sure the Port - // Object (FDO) is updated. We also don't care about the LUN part of the - // SCSI address so we just set it to zero. - // - if (controllerEntry) { - controllerEntry->PortObject = PortObject; - controllerEntry->ScsiAddress->Lun = 0; - } - - if (AcquireLock) { - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFindControllerEntry (SN %s): Exiting function with controllerEntry %p\n", - ControllerSerialNumber, - controllerEntry)); - - return controllerEntry; -} - - -_Ret_maybenull_ -_Must_inspect_result_ -_When_(return != NULL, __drv_allocatesMem(Mem)) -PDSM_CONTROLLER_LIST_ENTRY -DsmpBuildControllerEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_opt_ IN PDEVICE_OBJECT DeviceObject, - _In_ IN PDEVICE_OBJECT PortObject, - _In_ IN PSCSI_ADDRESS ScsiAddress, - _In_ IN PSTR ControllerSerialNumber, - _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, - _In_ IN BOOLEAN AcquireLock - ) -/*++ - -Routine Description: - - This routine builds a new controller list entry with the passed in serial number info. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization. - DeviceObject - Controller's PDO. - PortObject - Port FDO exposing the controller. - ScsiAddress - scsi address of the controller. - ControllerSerialNumber - The serial number to associate with new entry. - CodeSet - Code set of the identifier that was used to build the serial number. - AcquireLock - TRUE indicates that the function must grab the spinlock. FALSE indicates - that caller has the spin lock held. - -Return Value: - - New controller list entry if we successfully built one, else NULL - ---*/ -{ - KIRQL oldIrql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error - PDSM_CONTROLLER_LIST_ENTRY controllerEntry = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildControllerEntry (SN %s): Entering function - Controller %p seen through PortFDO %p.\n", - ControllerSerialNumber, - DeviceObject, - PortObject)); - - if (AcquireLock) { - - oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - } - - controllerEntry = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_CONTROLLER_LIST_ENTRY), - DSM_TAG_CONTROLLER_LIST_ENTRY); - - if (controllerEntry) { - - // - // Note: - // ControllerSerialNumber's length fits in a 32-bit value. - // See implementation in DsmpParseDeviceID() - // - ULONG length = (ULONG)strlen(ControllerSerialNumber); - - controllerEntry->Identifier = DsmpAllocatePool(NonPagedPoolNx, - length + 1, - DSM_TAG_SERIAL_NUM); - - if (controllerEntry->Identifier) { - - controllerEntry->ScsiAddress = DsmpAllocatePool(NonPagedPoolNx, - sizeof(SCSI_ADDRESS), - DSM_TAG_SCSI_ADDRESS); - if (controllerEntry->ScsiAddress) { - - RtlCopyMemory(controllerEntry->ScsiAddress, ScsiAddress, sizeof(SCSI_ADDRESS)); - - controllerEntry->DeviceObject = DeviceObject; - controllerEntry->PortObject = PortObject; - controllerEntry->ControllerSig = DSM_CONTROLLER_SIG; - controllerEntry->IdLength = length; - controllerEntry->IdCodeSet = CodeSet; - - RtlCopyMemory(controllerEntry->Identifier, - ControllerSerialNumber, - length); - - controllerEntry->RefCount = 0; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildControllerEntry (SN %s): Failed to allocate resources for scsiaddress (controllerEntry %p).\n", - ControllerSerialNumber, - controllerEntry)); - - DsmpFreePool(controllerEntry->Identifier); - controllerEntry->Identifier = NULL; - DsmpFreePool(controllerEntry); - controllerEntry = NULL; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildControllerEntry (SN %s): Failed to allocate resources for identifier (controllerEntry %p).\n", - ControllerSerialNumber, - controllerEntry)); - - DsmpFreePool(controllerEntry); - controllerEntry = NULL; - } - - } else { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildControllerEntry (SN %s): Failed to allocate memory for ControllerEntry.\n", - ControllerSerialNumber)); - } - - if (AcquireLock) { - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildControllerEntry (SN %s): Exiting function with controllerEntry %p\n", - ControllerSerialNumber, - controllerEntry)); - - return controllerEntry; -} - - -VOID -DsmpFreeControllerEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ __drv_freesMem(Mem) IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry - ) -/*++ - -Routine Description: - - This routine frees the allocations of the passed in controller list entry. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization. - ControllerEntry - Controller list entry. - -Return Value: - - Nothing - ---*/ -{ - PVOID tempAddress = (PVOID)ControllerEntry; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFreeControllerEntry (Entry %p): Entering function.\n", - ControllerEntry)); - - if (ControllerEntry->Identifier) { - DsmpFreePool(ControllerEntry->Identifier); - } - - if (ControllerEntry->ScsiAddress) { - DsmpFreePool(ControllerEntry->ScsiAddress); - } - - DsmpFreePool(ControllerEntry); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFreeControllerEntry (Entry %p): Exiting function.\n", - tempAddress)); - - return; -} - - -BOOLEAN -DsmpIsDeviceBelongsToController( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry - ) -/*++ - -Routine Description: - - This routine determines if the device passed in was exposed via the passed - in controller. - The match is to be based on VID and SCSI Address (using the Port, Bus - and Target comparison). - -Arguments: - - DsmContext - DSM context given to MPIO during initialization. - DeviceInfo - The device instance to match. - ControllerEntry - The controller object which we need to determine whether - DeviceInfo is exposed from. - -Return Value: - - TRUE - if the controller's VID and scsi address match - FALSE - not matched - ---*/ -{ - BOOLEAN saMatch = FALSE; - BOOLEAN vMatch = FALSE; - BOOLEAN match = FALSE; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpIsDeviceBelongsToController (DevInfo %p): Entering function - ControllerEntry is %p.\n", - DeviceInfo, - ControllerEntry)); - - if (DeviceInfo->ScsiAddress && ControllerEntry->ScsiAddress) { - - saMatch = (DeviceInfo->ScsiAddress->PathId == ControllerEntry->ScsiAddress->PathId && - DeviceInfo->ScsiAddress->PortNumber == ControllerEntry->ScsiAddress->PortNumber && - DeviceInfo->ScsiAddress->TargetId == ControllerEntry->ScsiAddress->TargetId); - } - - if (saMatch) { - - INQUIRYDATA inquiryData = {0}; - UCHAR controllerVID[9] = {0}; - UCHAR deviceVID[9] = {0}; - - if (NT_SUCCESS(DsmpGetStandardInquiryData(ControllerEntry->DeviceObject, &inquiryData))) { - - RtlStringCchCopyA((PSTR)controllerVID, - ARRAYSIZE(controllerVID), - (PCSTR)(&inquiryData.VendorId)); - - RtlStringCchCopyA((PSTR)deviceVID, - ARRAYSIZE(deviceVID), - (PCSTR)(&DeviceInfo->Descriptor) + DeviceInfo->Descriptor.VendorIdOffset); - - - if (!strcmp((const char*)controllerVID, (const char*)deviceVID)) { - - vMatch = TRUE; - } - } - } - - match = saMatch & vMatch; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpIsDeviceBelongsToController (DevInfo %p): ControllerEntry %p. Exiting function with match = %x.\n", - DeviceInfo, - ControllerEntry, - match)); - - return match; -} - - -PDSM_DEVICE_INFO -DsmpFindDevInfoFromGroupAndFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_FAILOVER_GROUP FOGroup - ) -/*++ - -Routine Description: - - This routine will find the deviceInfo that is part of both the passed in Group - as well as passed in Fail-Over group. - - N.B: This routine MUST be called with DsmContextLock held in either Shared or - Exclusive mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - Group - The group that represents the device. - FOGroup - The FOG that the device is part of. - -Return Value: - - The deviceInfo that is part of both. - NULL - if not found. - ---*/ -{ - ULONG i; - PDSM_DEVICE_INFO deviceInfo = NULL; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpFindDevInfoFromGroupAndFOGroup (Group %p FOG %p): Entering function.\n", - Group, - FOGroup)); - - if (Group && FOGroup) { - - // - // Run through the list of devInfos in passed in Group - // - for (i = 0; i < DSM_MAX_PATHS; i++) { - - deviceInfo = Group->DeviceList[i]; - - if (deviceInfo) { - - if (deviceInfo->FailGroup == FOGroup) { - - break; - - } else { - - deviceInfo = NULL; - } - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpFindFOGroup (Group %p FOG %p): Exiting function with deviceInfo %p.\n", - Group, - FOGroup, - deviceInfo)); - - return deviceInfo; -} - - -PDSM_FAILOVER_GROUP -DsmpFindFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PVOID PathId - ) -/*++ - -Routine Description: - - This routine will find the Fail-Over group that corresponds to PathId. - - N.B: This routine MUST be called with DsmContextLock held in either Shared or - Exclusive mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - PathId - The Path Identifier that corresponds to - an adapter/adapter-controller - -Return Value: - - The fail-over group. - NULL - if not found. - ---*/ -{ - PDSM_FAILOVER_GROUP failOverGroup = NULL; - PDSM_FAILOVER_GROUP retFOGroup = NULL; - PLIST_ENTRY entry; - ULONG i; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindFOGroup (PathId %p): Entering function.\n", - PathId)); - - // - // Run through the list of Fail-Over Groups - // - entry = DsmContext->FailGroupList.Flink; - for (i = 0; i < DsmContext->NumberFOGroups; i++, entry = entry->Flink) { - - // - // Extract the fail-over group structure. - // - failOverGroup = CONTAINING_RECORD(entry, DSM_FAILOVER_GROUP, ListEntry); - NT_ASSERT(failOverGroup); - - if (!failOverGroup) { - continue; - } - - // - // Check for a match of the PathId. - // - if (failOverGroup->PathId == PathId) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpFindFOGroup (PathId %p): Found a FO group %p.\n", - PathId, - failOverGroup)); - - retFOGroup = failOverGroup; - - break; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindFOGroup (PathId %p): Exiting function with retFOGroup %p.\n", - PathId, - retFOGroup)); - - return retFOGroup; -} - - -PDSM_FAILOVER_GROUP -DsmpBuildFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PVOID *PathId - ) -/*++ - -Routine Description: - - This routine will build and partially initialise a fail-over group entry. - The FOG corresponds to the device list which will fail as a group. - - N.B: This routine MUST be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DeviceInfo - The first device to add to the group. - PathId - An identifier that is returned to mpio that id's the path. - -Return Value: - - The fail-over group entry. - NULL - on failed allocation. - ---*/ -{ - PDSM_FAILOVER_GROUP failOverGroup; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildFOGroup (PathId %p): Entering function.\n", PathId)); - - // - // Allocate a new Fail Over Group - // - failOverGroup = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_FAILOVER_GROUP), - DSM_TAG_FO_GROUP); - if (failOverGroup) { - - InitializeListHead(&failOverGroup->FOG_DeviceList); - InitializeListHead(&failOverGroup->ZombieGroupList); - - // - // Get the current number of groups, and add the one that's being created. - // - InterlockedIncrement((LONG volatile*)&DsmContext->NumberFOGroups); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpBuildFOGroup (PathId %p): Path that will be used for %p is %p.\n", - PathId, - DeviceInfo, - *PathId)); - - failOverGroup->PathId = *PathId; - - // - // Set the initial state to NORMAL. - // - failOverGroup->State = DSM_FG_NORMAL; - - failOverGroup->FailOverSig = DSM_FOG_SIG; - - // - // Add it to the global list. - // - InsertTailList(&DsmContext->FailGroupList, - &failOverGroup->ListEntry); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpBuildFOGroup (PathId %p): Added new FOGroup %p with path %p. Count of FO Group %d.\n", - PathId, - failOverGroup, - *PathId, - DsmContext->NumberFOGroups)); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildFOGroup (PathId %p): Failed to allocate memory for FailOverGroup.\n", - PathId)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildFOGroup (PathId %p): Exiting function with failOverGroup %p.\n", - PathId, - failOverGroup)); - - return failOverGroup; -} - - -NTSTATUS -DsmpUpdateFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_FAILOVER_GROUP FailGroup, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - This routine will add DeviceInfo to an existing FOG. - - N.B: This routine MUST be called with DsmContextLock held in Exclusive mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - FailGroup - The fail-over group entry. - DeviceInfo - The new device. - -Return Value: - - STATUS_SUCCESS or appropriate error code. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpUpdateFOGroup (FOG %p): Entering function. DeviceInfo %p.\n", - FailGroup, - DeviceInfo)); - - if (DeviceInfo && FailGroup) { - - fogDeviceListEntry = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_FOG_DEVICELIST_ENTRY), - DSM_TAG_FOG_DEV_ENTRY); - - if (fogDeviceListEntry) { - - // - // Add the device to the list of devices that are on this path. - // - fogDeviceListEntry->DeviceInfo = DeviceInfo; - InterlockedIncrement((LONG volatile*)&FailGroup->Count); - InsertTailList(&FailGroup->FOG_DeviceList, &fogDeviceListEntry->ListEntry); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpUpdateFOGroup (FOG %p): DevInfo %p added (current count: %d)\n", - FailGroup, - DeviceInfo, - FailGroup->Count)); - - // - // Set the device's F.O. Group. - // - DeviceInfo->FailGroup = FailGroup; - - } else { - - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpUpdateFOGroup (FOG %p): Failed to allocate memory for FOG devlist entry.\n", - FailGroup)); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpUpdateFOGroup (FOG %p): Exiting function with status %x.\n", - FailGroup, - status)); - - return status; -} - - -VOID -DsmpRemoveDeviceFailGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_FAILOVER_GROUP FailGroup, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN BOOLEAN AcquireDSMLockExclusive - ) -/*++ - -Routine Description: - - This routine will remove DeviceInfo from the FOG. - This routine is called in response to a removal of the device. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - FailGroup - The FOG from which DeviceInfo should be removed. - DeviceInfo - The now missing device. - AcquireDSMLockExclusive - If TRUE this routine should acquire DsmContextLock Exclusively - -Return Value: - - NOTHING - ---*/ -{ - KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 warnings - PLIST_ENTRY entry; - PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry; - PLIST_ENTRY zombieEntry; - PDSM_ZOMBIEGROUP_ENTRY zombieGroup; - PDSM_ZOMBIEGROUP_ENTRY newZombieGroup; - BOOLEAN groupInZombieList = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceFailGroup (FOG %p): Entering function. DeviceInfo %p.\n", - FailGroup, - DeviceInfo)); - - if (FailGroup && DeviceInfo) { - - if (AcquireDSMLockExclusive) { - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - } - - for (entry = FailGroup->FOG_DeviceList.Flink; - entry != &FailGroup->FOG_DeviceList; - entry = entry->Flink) { - - fogDeviceListEntry = CONTAINING_RECORD(entry, - DSM_FOG_DEVICELIST_ENTRY, - ListEntry); - DSM_ASSERT(fogDeviceListEntry); - - if (!fogDeviceListEntry) { - continue; - } - - if (fogDeviceListEntry->DeviceInfo == DeviceInfo) { - - DeviceInfo->FailGroup = NULL; - RemoveEntryList(entry); - DsmpFreePool(fogDeviceListEntry); - - InterlockedDecrement((LONG volatile*)&FailGroup->Count); - - // - // If a DeviceInfo is removed, we need to keep its group in a - // "zombie" list so that we can still access a fail-over group's - // associated groups even when all its devices are gone. - // - for (zombieEntry = FailGroup->ZombieGroupList.Flink; - zombieEntry != &(FailGroup->ZombieGroupList); - zombieEntry = zombieEntry->Flink) { - - zombieGroup = CONTAINING_RECORD(zombieEntry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); - if (zombieGroup != NULL && - zombieGroup->Group != NULL && - zombieGroup->Group == DeviceInfo->Group) { - - groupInZombieList = TRUE; - break; - } - } - - // - // Create a new entry if the group does not exist in the zombie group list. - // - if (groupInZombieList == FALSE) { - newZombieGroup = (PDSM_ZOMBIEGROUP_ENTRY)DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_ZOMBIEGROUP_ENTRY), - DSM_TAG_ZOMBIEGROUP_ENTRY); - if (newZombieGroup != NULL) { - newZombieGroup->Group = DeviceInfo->Group; - InsertTailList(&FailGroup->ZombieGroupList, &newZombieGroup->ListEntry); - } else { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceFailGroup (DevInfo %p): Failed to allocate memory for the zombie group.\n", - DeviceInfo)); - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceFailGroup (FOG %p): DevInfo %p removed from FOG (current count: %d)\n", - FailGroup, - DeviceInfo, - FailGroup->Count)); - - break; - } - } - - if (AcquireDSMLockExclusive) { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceFailGroup (FOG %p): Exiting function.\n", - FailGroup)); - - return; -} - - -ULONG -DsmpRemoveDeviceEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - This routine will remove DeviceInfo from Group. If it is the last DeviceInfo - in the Group, it has the added side-effect of cleaning up the Group entry - also. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - Group - The multi-path group from which DeviceInfo should be removed. - DeviceInfo - The device to remove. - -Return Value: - - Number of devices left in group. - ---*/ -{ - KIRQL irql; - ULONG i; - ULONG j; - ULONG numberDevices; - BOOLEAN freeGroup = FALSE; - PVOID tempAddress = (PVOID)Group; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceEntry (Group %p): Entering function. DeviceInfo %p.\n", - Group, - DeviceInfo)); - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Find it's offset in the array of devices. - // - for (i = 0; i < Group->NumberDevices; i++) { - - if (Group->DeviceList[i] == DeviceInfo) { - - // - // Zero out it's entry. - // - Group->DeviceList[i] = NULL; - - // - // Reduce the number in the group. - // - InterlockedDecrement((LONG volatile*)&Group->NumberDevices); - - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceEntry (Group %p): Removing Device %p (desiredState %u) from Group\n", - Group, - DeviceInfo, - DeviceInfo->DesiredState)); - - // - // Collapse the array. - // Holding the spinlock, so that the state is consistent in other - // routines. - // - for (j = i; j < Group->NumberDevices; j++) { - - // - // Shuffle all entries down to fill the hole. - // - Group->DeviceList[j] = Group->DeviceList[j + 1]; - } - - // - // Zero out the last one. - // - Group->DeviceList[j] = NULL; - break; - } - } - - // - // Remove this devInfo from the TargetPort deviceList - // - DsmpRemoveDeviceFromTargetPortList(DeviceInfo); - - numberDevices = Group->NumberDevices; - - // - // See if anything is left in the Group. - // - if (Group->NumberDevices == 0) { - - Group->State = DSM_GP_FAILED; - - // - // Yank it from the Group list. - // - DsmpRemoveGroupEntry(DsmContext, Group, FALSE); - - freeGroup = TRUE; - } - - // - // Yank the device out of the Global list. - // - RemoveEntryList(&DeviceInfo->ListEntry); - InterlockedDecrement((LONG volatile*)&DsmContext->NumberDevices); - - // - // If the serial number buffer was allocated, need to free it. - // - if (DeviceInfo->SerialNumberAllocated) { - DsmpFreePool(DeviceInfo->SerialNumber); - } - - if (DeviceInfo->ScsiAddress) { - DsmpFreePool(DeviceInfo->ScsiAddress); - } - - // - // Fix up the Reservation List, if needed. - // - if (!freeGroup && Group->ReservationList) { - ULONG oldList; - - // - // Capture the list for debugging. - // - oldList = Group->ReservationList; - Group->ReservationList = 0; - - // - // Go through all devices in this group and find the one(s) registered. - // - for (i = 0; i < Group->NumberDevices; i++) { - - if (Group->DeviceList[i]->RegisterServiced) { - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmRemoveDeviceEntry (Group %p): Device %p at %d registered.\n", - Group, - Group->DeviceList[i], - i)); - - // - // Indicate its place. - // - Group->ReservationList |= (1 << i); - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmRemoveDeviceEntry (Group %p): Reservations Old (%x) New (%x).\n", - Group, - oldList, - Group->ReservationList)); - } - - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - // - // Free the allocation. - // - DsmpFreePool(DeviceInfo); - - if (freeGroup) { - - // - // Free the allocations. - // - if (Group->RegistryKeyName) { - DsmpFreePool(Group->RegistryKeyName); - } - - if (Group->HardwareId) { - DsmpFreePool(Group->HardwareId); - } - - DsmpFreePool(Group); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceEntry (Group %p): Exiting function - numberDevices = %x.\n", - tempAddress, - numberDevices)); - - return numberDevices; -} - - -VOID -DsmpRemoveDeviceFromTargetPortList( - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - This will remove a DeviceInfo from its target port device list. - - The caller should ensure that the DsmContext->SpinLock is held before - calling this function. - -Arguments: - - DeviceInfo - The DeviceInfo to be removed. - -Return Value: - - None - ---*/ -{ - if (DeviceInfo->TargetPort) { - - PLIST_ENTRY entry; - PDSM_TARGET_PORT_DEVICELIST_ENTRY listEntry; - - for (entry = DeviceInfo->TargetPort->TP_DeviceList.Flink; - entry != NULL && entry != &DeviceInfo->TargetPort->TP_DeviceList; - entry = entry->Flink) { - - listEntry = CONTAINING_RECORD(entry, DSM_TARGET_PORT_DEVICELIST_ENTRY, ListEntry); - - if (listEntry) { - - if (listEntry->DeviceInfo == DeviceInfo) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRemoveDeviceFromTargetPortList: Removing device %p from target port entry %p.\n", - DeviceInfo, - listEntry)); - - RemoveEntryList(entry); - InterlockedDecrement((LONG volatile*)&DeviceInfo->TargetPort->Count); - DsmpFreePool(listEntry); - - DeviceInfo->TargetPort = NULL; - DeviceInfo->TargetPortGroup = NULL; - - break; - } - } - } - } -} - - -VOID -DsmpRemoveZombieGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY ZombieGroup - ) -/* ++ - -Routine Description: - - This will scan through all the Failover Groups and remove the given Group - from each Failover Group's zombie group list. - - The DSM lock should be aquired by the caller. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - ZombieGroup - Group entry that should be removed from FOGs' ZombieGroupList - -Return Value: - - None - --- */ -{ - // - // Run through the list of Fail-Over Groups - // - ULONG i; - PDSM_FAILOVER_GROUP failOverGroup = NULL; - PLIST_ENTRY fogEntry; - PLIST_ENTRY groupEntry; - PDSM_ZOMBIEGROUP_ENTRY zombieGroupEntry; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveZombieGroupEntry (Group %p): Entering function.\n", - ZombieGroup)); - - fogEntry = DsmContext->FailGroupList.Flink; - for (i = 0; fogEntry != NULL && i < DsmContext->NumberFOGroups; i++, fogEntry = fogEntry->Flink) { - - failOverGroup = CONTAINING_RECORD(fogEntry, DSM_FAILOVER_GROUP, ListEntry); - if (failOverGroup != NULL) { - - for (groupEntry = failOverGroup->ZombieGroupList.Flink; - groupEntry != &(failOverGroup->ZombieGroupList); - groupEntry = groupEntry->Flink) { - - zombieGroupEntry = CONTAINING_RECORD(groupEntry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); - if (zombieGroupEntry != NULL && - zombieGroupEntry->Group != NULL && - zombieGroupEntry->Group == ZombieGroup) { - - RemoveEntryList(groupEntry); - DsmpFreePool(zombieGroupEntry); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveZombieGroupEntry (Group %p): Found and removed a zombie group in (FOG %p)\n", - ZombieGroup, - failOverGroup)); - - // - // We removed the zombie group entry from this fail-over - // group, so we can move on to the next fail-over group. - // - break; - } - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveZombieGroupEntry (Group %p): Exiting function.\n", - ZombieGroup)); -} - - -VOID -DsmpRemoveGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY GroupEntry, - _In_ IN BOOLEAN AcquireDSMLockExclusive - ) -/*++ - -Routine Description: - - This will remove a group entry from the DSM's list. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - GroupEntry - Group entry that should be removed from DSM's list - AcquireDSMLockExclusive - If TRUE this routine should acquire DsmContextLock Exclusively - -Return Value: - - None - ---*/ -{ - KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 warnings - ULONG index; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup; - PLIST_ENTRY entry; - PDSM_TARGET_PORT_LIST_ENTRY targetPort; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveGroupEntry (Group %p): Entering function.\n", - GroupEntry)); - - if (AcquireDSMLockExclusive) { - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - } - - NT_ASSERT(GroupEntry && GroupEntry->ListEntry.Flink && GroupEntry->ListEntry.Blink); - - // - // Since this group is being removed, we need to make sure it is also - // removed from all fail-over groups' zombie group lists. - // - DsmpRemoveZombieGroupEntry(DsmContext, GroupEntry); - - // - // Add it to the list of multi-path groups. - // - RemoveEntryList(&GroupEntry->ListEntry); - - GroupEntry->ListEntry.Flink = GroupEntry->ListEntry.Blink = NULL; - - InterlockedDecrement((LONG volatile*)&DsmContext->NumberGroups); - - for (index = 0; index < DSM_MAX_PATHS; index++) { - - // - // Clean up all its Target Port Groups - // - targetPortGroup = GroupEntry->TargetPortGroupList[index]; - - if (targetPortGroup) { - - GroupEntry->TargetPortGroupList[index] = NULL; - - // - // For each target port group, clean up all its target ports - // - while (!IsListEmpty(&targetPortGroup->TargetPortList)) { - - entry = RemoveHeadList(&targetPortGroup->TargetPortList); - - if (entry) { - - targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); - - if (targetPort) { - - PLIST_ENTRY deviceEntry; - PDSM_TARGET_PORT_DEVICELIST_ENTRY listEntry; - - while (!IsListEmpty(&targetPort->TP_DeviceList)) { - - deviceEntry = RemoveHeadList(&targetPort->TP_DeviceList); - - if (deviceEntry) { - - listEntry = CONTAINING_RECORD(deviceEntry, - DSM_TARGET_PORT_DEVICELIST_ENTRY, - ListEntry); - - if (listEntry) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRemoveGroupEntry (Group %p): Deleting device %p from TP %p list (TPG %p).\n", - GroupEntry, - listEntry->DeviceInfo, - targetPort, - targetPortGroup)); - - DsmpFreePool(listEntry); - - InterlockedDecrement((LONG volatile*)&targetPort->Count); - } - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRemoveGroupEntry (Group %p): Deleting target port %p from TPG %p list.\n", - GroupEntry, - targetPort, - targetPortGroup)); - - DsmpFreePool(targetPort); - - InterlockedDecrement((LONG volatile*)&targetPortGroup->NumberTargetPorts); - } - } - } - - NT_ASSERT(targetPortGroup->NumberTargetPorts == 0); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRemoveGroupEntry (Group %p): Deleting target port group %p.\n", - GroupEntry, - targetPortGroup)); - - DsmpFreePool(targetPortGroup); - - InterlockedDecrement((LONG volatile*)&GroupEntry->NumberTargetPortGroups); - } - } - - NT_ASSERT(GroupEntry->NumberTargetPortGroups == 0); - - if (AcquireDSMLockExclusive) { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRemoveGroupEntry (Group %p): Exiting function.\n", - GroupEntry)); - - return; -} - - -PDSM_FAILOVER_GROUP -DsmpSetNewPath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDevice - ) -/*++ - -Routine Description: - - This routine will assign a new path to the multi-path group in - which FailingDevice resides. - - Caller must NOT hold spin lock. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - - FailingDevice - The device-path that is being moved - (due to failure, or admin. request) - -Return Value: - - The FOG containing the new path. - ---*/ -{ - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpSetNewPath (DevInfo %p): Entering function.\n", - FailingDevice)); - - if (DsmpIsSymmetricAccess(FailingDevice)) { - - DsmpSetLBForPathRemoval(DsmContext, FailingDevice, NULL, SpecialHandlingFlag); - - } else { - - DsmpSetLBForPathRemovalALUA(DsmContext, FailingDevice, NULL, SpecialHandlingFlag); - } - - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpSetNewPath (DevInfo %p): Exiting function with path (failGroup) %p.\n", - FailingDevice, - FailingDevice->Group->PathToBeUsed)); - - return FailingDevice->Group->PathToBeUsed; -} - - -PDSM_FAILOVER_GROUP -DsmpSetNewPathUsingGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group - ) -/*++ - -Routine Description: - - This routine will try to assign a new path using the given multi-path group. - This function should only be called during failover in the event that there - is no DeviceInfo with which to call DsmpSetNewPath(). - - Typically this will be called with one of a fail-over group's zombie groups. - - Caller must NOT hold spin lock. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization. - - Group - The multi-path group which to assign a new path. - -Return Value: - - The FOG containing the new path or NULL if no path was found. - ---*/ - -{ - ULONG i; - PDSM_DEVICE_INFO pDevInfo = NULL; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetNewPathUsingGroup (Group %p): Entering function.\n", - Group)); - - // - // Get the first available DeviceInfo. - // - for (i = 0; i < DSM_MAX_PATHS; i ++) { - if (Group->DeviceList[i] != NULL) { - pDevInfo = Group->DeviceList[i]; - break; - } - } - - if (pDevInfo == NULL) { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetNewPathForZombieGroup (ZombieGroup %p): No failover group can be found.\n", - Group)); - return NULL; - } - - - if (DsmpIsSymmetricAccess(pDevInfo)) { - - DsmpSetLBForPathRemoval(DsmContext, pDevInfo, Group, SpecialHandlingFlag); - - } else { - - DsmpSetLBForPathRemovalALUA(DsmContext, pDevInfo, Group, SpecialHandlingFlag); - } - - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetNewPathForZombieGroup (ZombieGroup %p): Exiting function with path (failGroup) %p.\n", - Group, - Group->PathToBeUsed)); - - return Group->PathToBeUsed; - -} - - -NTSTATUS -DsmpUpdateTargetPortGroupDevicesStates( - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN DSM_DEVICE_STATE NewState - ) -/*++ - -Routine Description: - - This routine will update the target port group and all its appropriate - devInfos (ones not in remove pending, removed, or invalidated) with the - new state. The ALUAState will only be updated, NOT the real State. - Caller needs to update the real State based on the current LB policy. - - Note: This should be called with DsmContext Lock held and should only be - called after a SetTargetPortGroups request was sent down. - -Arguments: - - TargetPortGroup - TargetPortGroup whose state and deviceInfos need to be - updated - - NewState - The new state - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PLIST_ENTRY entry = NULL; - PDSM_TARGET_PORT_LIST_ENTRY targetPort = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Entering function.\n", - TargetPortGroup)); - - if (!TargetPortGroup) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Invalid TPG passed in.\n", - TargetPortGroup)); - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpUpdateTargetPortGroupDevicesStates; - } - - // - // First update TPG's asymmetric access state. - // - TargetPortGroup->AsymmetricAccessState = NewState; - - // - // Now update state of each of the devices belonging to this TPG. - // - for (entry = TargetPortGroup->TargetPortList.Flink; - entry != &TargetPortGroup->TargetPortList; - entry = entry->Flink) { - - targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); - NT_ASSERT(targetPort); - - if (targetPort) { - - PLIST_ENTRY deviceEntry; - PDSM_TARGET_PORT_DEVICELIST_ENTRY tp_device; - - for (deviceEntry = targetPort->TP_DeviceList.Flink; - deviceEntry != &targetPort->TP_DeviceList; - deviceEntry = deviceEntry->Flink) { - - tp_device = CONTAINING_RECORD(deviceEntry, - DSM_TARGET_PORT_DEVICELIST_ENTRY, - ListEntry); - - if (tp_device) { - - tp_device->DeviceInfo->ALUAState = NewState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Updated device %p alua state to %x.\n", - TargetPortGroup, - tp_device->DeviceInfo, - tp_device->DeviceInfo->ALUAState)); - } - } - } - } - -__Exit_DsmpUpdateTargetPortGroupDevicesStates: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Exiting function with status %x.\n", - TargetPortGroup, - status)); - - return status; -} - - -VOID -DsmpIncrementCounters( - _In_ PDSM_FAILOVER_GROUP FailGroup, - _In_ PSCSI_REQUEST_BLOCK Srb - ) -{ - ULONG bytes = 0; - PCDB cdb = NULL; - ULONG cdbLength = 0; - BOOLEAN isReadWrite = FALSE; - ULONGLONG lastLba = 0; - ULONG numBlocks = 0; - ULONGLONG startLba = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpIncrementCounters (FOG %p): Entering function.\n", - FailGroup)); - - if (Srb) { - - cdb = SrbGetCdb(Srb); - - if (cdb && DsmIsReadWrite(cdb->AsByte[0])) { - - isReadWrite = TRUE; - } - } - - InterlockedIncrement(&FailGroup->NumberOfRequestsInFlight); - - // - // Update counters that apply to read/write requests - // - if (isReadWrite) { - - bytes = SrbGetDataTransferLength(Srb); - - InterlockedExchangeAdd64((LONGLONG volatile*)&FailGroup->OutstandingBytesOfIO, bytes); - - cdbLength = SrbGetCdbLength(Srb); - - if (cdbLength == 16) { - - REVERSE_BYTES_QUAD(&startLba, &cdb->CDB16.LogicalBlock); - REVERSE_BYTES(&numBlocks, &cdb->CDB16.TransferLength); - - } else { - - REVERSE_BYTES(&startLba, &cdb->CDB10.LogicalBlockByte0); - REVERSE_BYTES_SHORT(&numBlocks, &cdb->CDB10.TransferBlocksMsb); - } - - lastLba = startLba + numBlocks - 1; - - InterlockedExchange64((LONGLONG volatile*)&FailGroup->LastLba, lastLba); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpIncrementCounters (FOG %p): Exiting function.\n", - FailGroup)); - - return; -} - - -BOOLEAN -DsmpDecrementCounters( - _In_ PDSM_FAILOVER_GROUP FailGroup, - _In_ PSCSI_REQUEST_BLOCK Srb - ) -{ - ULONG bytes = 0; - PCDB cdb = NULL; - BOOLEAN isReadWrite = FALSE; - BOOLEAN isDeletionEligible = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpDecrementCounters (FOG %p): Entering function.\n", - FailGroup)); - - if (Srb) { - - cdb = SrbGetCdb(Srb); - - if (cdb && DsmIsReadWrite(cdb->AsByte[0])) { - - isReadWrite = TRUE; - } - } - - // - // Update counters that apply to read/write requests - // - if (isReadWrite) { - - bytes = SrbGetDataTransferLength(Srb); - - InterlockedExchangeAdd64((LONGLONG volatile*)&FailGroup->OutstandingBytesOfIO, -(LONGLONG)bytes); - } - - NT_ASSERT(FailGroup->NumberOfRequestsInFlight > 0); - if (InterlockedCompareExchange(&FailGroup->NumberOfRequestsInFlight, 0, 0) > 0) { - - if(InterlockedDecrement(&FailGroup->NumberOfRequestsInFlight) == 0){ - - // - // If the inflight requests on the path is zero, if needed path can be removed. - // - isDeletionEligible = TRUE; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpDecrementCounters (FOG %p): Exiting function.\n", - FailGroup)); - - return isDeletionEligible; -} - - -PDSM_FAILOVER_GROUP -DsmpGetPath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmList, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine will pick a path, for processing a request, based - on the current LoadBalance policy that is set. - - N.B: This routine must be called with DSM Context Lock held in Shared mode. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DsmList - List of DSM Ids sent by MPIO - Srb - The read/write/verify request - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - FailOver Group that should be used for processing the request ---*/ -{ - // - // Algorithm: - // ========== - // Failover-only: - // -------------- - // If symmetric LUA (ie. ALUA not supported, or symmetric LUA using ALUA semantics (viz. storage reports - // implicit-only transitions and all TPGs in A/O): - // One path AO, <- this will be the only path used for I/O - // M paths in SB, <- one of these will be made active on failure of the above active path - // Rest of the paths Failed (Invalidated/PendingRemove/Removed) - // - // If ALUA: - // One path AO, <- this will be the only path used for I/O - // M paths in AU, SB or UA <- one of these made active on failover. Pref: AU > SB > UA. Also, controller affinity. - // Rest of the paths Failed - // - // Automatic failback will happen only if Preferred path has been set. - // This is the only policy that will support failback. - // - // Round-Robin: - // ------------ - // If symmetric LUA: - // N paths AO, <- round robin among these - // Rest of the paths Failed - // - // If ALUA: - // Round Robin policy not supported since all paths can't be in A/O state. - // - // Round-Robin With Subset: - // ------------------------ - // If symmetric LUA: - // N paths AO, <- round robin among these - // M paths SB, <- if no active paths left, make one of these active - // Rest of the paths Failed - // - // If ALUA: - // N paths AO, <- round robin among these (NOTE: paths in AU not considered) - // M paths AU, SB or UA <- if no active paths, make subset of these active (based on TPG states after transition) - // Rest of the paths Failed - // - // Least-Queue Depth: - // ------------------ - // If symmetric LUA: - // N paths AO, <- one with least outstanding I/O is chosen - // Rest of the paths Failed - // - // If ALUA: - // N paths AO, <- one with least outstanding I/O is chosen - // M paths AU, SB or UA <- if no AO paths available, subset of these become active (based on TPG - // states after transition) - one with least outstanding I/O is chosen. - // Rest of the paths Failed - // - // Least-Weighted: - // --------------- - // If symmetric LUA: - // N paths AO, <- every path has an associated weight, path with least weight is used. - // Rest of the paths Failed - // - // If ALUA: - // N paths AO, - // M paths AU, SB or UA <- if no AO paths available, subset of these become active (based on TPG - // states after transition) - path with least weight used. - // Rest of the paths Failed - // - // Least-Blocks: - // ------------- - // If symmetric LUA: - // N paths AO, <- one with least cumulative outstanding IO is chosen - // Rest of the paths Failed - // - // If ALUA: - // N paths AO, <- one with least cumulative outstanding IO is chosen - // M paths AU, SB or UA <- if no AO paths available, subset of these become active (based on TPG - // states after transition) - one with least cumulative outstanding is chosen. - // - // Actual implementation of algorithm happens in the following routines: DsmpGetAnyActivePath, - // DsmpGetActivePathToBeUsed, flavors of DsmpSetLBForPathXXX. - // - - PDSM_FAILOVER_GROUP failGroup = NULL; - PDSM_DEVICE_INFO deviceInfo = DsmList->IdList[0]; - PDSM_GROUP_ENTRY groupEntry; - ULONG inx = 0; - - UNREFERENCED_PARAMETER(DsmContext); - UNREFERENCED_PARAMETER(SpecialHandlingFlag); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Entering function.\n", - DsmList)); - - if (!(DsmList->Count && deviceInfo)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Called with no available paths.\n", - DsmList)); - - goto __Exit_DsmpGetPath; - } - - groupEntry = deviceInfo->Group; - DSM_ASSERT(groupEntry->GroupSig == DSM_GROUP_SIG); - - switch (groupEntry->LoadBalanceType) { - - case DSM_LB_FAILOVER: - case DSM_LB_WEIGHTED_PATHS: { - - // - // For FailOverOnly there is only one active path so we can - // just grab it from the cached location and go with it. - // For LeastWeightPath we always choose the lowest weighted - // one so we grab that and go - // - failGroup = groupEntry->PathToBeUsed; - - break; - } - - case DSM_LB_ROUND_ROBIN: - case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { - - PDSM_DEVICE_INFO candidateDevice = NULL; - PDSM_GROUP_ENTRY newGroup = NULL; - ULONG newPath; - BOOLEAN foundPath = FALSE; - ULONG jnx = 0; - ULONG counter = 0; - BOOLEAN reset = FALSE; - - for (inx = 0; inx < DsmList->Count; inx++) { - - deviceInfo = DsmList->IdList[inx]; - - if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { - - continue; - } - - - if (deviceInfo->FailGroup == groupEntry->PathToBeUsed) { - - // - // We've reached the devInfo that corresponds to the path - // that we should be using. If this devInfo is not in the - // right state to be used, we need to find the first candidate - // starting from this one to satisfy the request. - // To play it safe, we may have already considered a previous - // devInfo to be a candidate, that now needs to be reset to - // the one that we now find. - // - reset = TRUE; - } - -#if DBG - if (deviceInfo->TargetPortGroup && !DsmpIsDeviceFailedState(deviceInfo->State)) { - - if (deviceInfo->State != deviceInfo->ALUAState) { - - DSM_ASSERT(groupEntry->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET && - deviceInfo->State == DSM_DEV_ACTIVE_UNOPTIMIZED && - deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED); - } - } -#endif - - if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { - - if (!candidateDevice || reset) { - - candidateDevice = deviceInfo; - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Candidate device %p.\n", - DsmList, - candidateDevice)); - - jnx = inx; - } - - if (!groupEntry->PathToBeUsed || deviceInfo->FailGroup == groupEntry->PathToBeUsed) { - - // - // The devInfo that corresponds to the path that we were - // supposed to use, is in a state that makes it usable. - // So we've found our devInfo. - // - InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)deviceInfo->FailGroup); - foundPath = TRUE; - candidateDevice = NULL; - - break; - } - } - } - - if (!foundPath) { - - if (candidateDevice) { - - InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)candidateDevice->FailGroup); - inx = jnx; - candidateDevice = NULL; - - } else { - - inx = 0; - } - } - - failGroup = groupEntry->PathToBeUsed; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Path to be used is %p.\n", - DsmList, - groupEntry->PathToBeUsed)); - - // - // The current chosen path is given by failGroup. Find the next path - // that should be chosen in the RoundRobin policy. Start with the - // device at index inx + 1, and look for the one with Active state. - // - for (counter = 0, jnx = inx + 1; - counter < DsmList->Count && !newGroup; - counter++, jnx++) { - - newPath = jnx % DsmList->Count; - - deviceInfo = DsmList->IdList[newPath]; - - if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { - - continue; - } - - - if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { - - newGroup = deviceInfo->Group; - DSM_ASSERT(newGroup == groupEntry); - - InterlockedExchangePointer(&(newGroup->PathToBeUsed), (PVOID)deviceInfo->FailGroup); - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): New Path is %p.\n", - DsmList, - newGroup->PathToBeUsed)); - - break; - } - } - - break; - } - - case DSM_LB_DYN_LEAST_QUEUE_DEPTH: { - - LONG leastQueueDepth = 0x7FFFFFFF; - - for (inx = 0; inx < DsmList->Count; inx++) { - - deviceInfo = DsmList->IdList[inx]; - - if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { - - continue; - } - - - if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED && - deviceInfo->FailGroup->NumberOfRequestsInFlight < leastQueueDepth) { - - leastQueueDepth = deviceInfo->FailGroup->NumberOfRequestsInFlight; - failGroup = deviceInfo->FailGroup; - } - } - - if (failGroup) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Path to be used for LQD is %p.\n", - DsmList, - failGroup)); - - } else { - - // - // For ALUA storage there are two cases where we are left with no - // TPG in the A/O state: - // 1) On storage that supports implicit transitions, a transition - // was initiated that left no TPG in the A/O state. - // 2) On storage that has explicit only transitions enabled, we tried - // making at least one path as A/O and failed. This can happen, - // for example, when STPG fails because this initiator is not - // registered or does not hold exclusive reservation over the - // target. - // - // For such storages, we should return some path instead of just - // failing the I/O. The path will likely be an A/U path until the - // storage does a transition to make a TPG A/O. - // - if (!DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmList->IdList[0])) { - - // - // Use the same path as the one used for the previous request. - // - failGroup = groupEntry->PathToBeUsed; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpGetPath (DsmIds %p): Using same path (FOG %p) as previous request for LQD.\n", - DsmList, - failGroup)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Failed to find a path for LQD.\n", - DsmList)); - } - } - - break; - } - - case DSM_LB_LEAST_BLOCKS: { - - ULONG bytes = 0; - PCDB cdb = NULL; - ULONG cdbLength = 0; - BOOLEAN isRead = FALSE; - BOOLEAN isWrite = FALSE; - PDSM_FAILOVER_GROUP lastPathUsed = groupEntry->PathToBeUsed; - ULONGLONG leastOutstandingIO = MAXULONGLONG; - ULONGLONG startLba = 0; - - // - // Use the last path under the following conditions: - // - // 1. This is not a read/write request or - // 2. This is a read/write request and - // a. The request is sequential and - // b. The cache is not exhausted - // - - if (Srb) { - - cdb = SrbGetCdb(Srb); - - if (cdb && DsmIsReadRequest(cdb->AsByte[0])) { - - isRead = TRUE; - } - - if (cdb && DsmIsWriteRequest(cdb->AsByte[0])) { - - isWrite = TRUE; - } - } - - if (isRead || isWrite) { - - if (groupEntry->UseCacheForLeastBlocks) { - - bytes = SrbGetDataTransferLength(Srb); - - cdbLength = SrbGetCdbLength(Srb); - - if (cdbLength == 16) { - - REVERSE_BYTES_QUAD(&startLba, &cdb->CDB16.LogicalBlock); - - } else { - - REVERSE_BYTES(&startLba, &cdb->CDB10.LogicalBlockByte0); - } - - // - // Check if: - // 1. The IO is sequential, AND - // 2. It is either: - // a. read request, OR - // b. write request and outstanding bytes will be within the cache limit - // - if ((lastPathUsed != NULL) && - (startLba >= lastPathUsed->LastLba) && - ((isRead) || - (isWrite && lastPathUsed->OutstandingBytesOfIO + bytes <= groupEntry->CacheSizeForLeastBlocks))) { - - failGroup = groupEntry->PathToBeUsed; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Sequential IO, so using same path %p for LeastBlocks.\n", - DsmList, - failGroup)); - } - } - - } else { - // - // The request is neither a read nor a write so use the same path. - // - failGroup = groupEntry->PathToBeUsed; - } - - if (!failGroup) { - - // - // Choose whichever Active/Optimized path has the least outstanding bytes. - // - for (inx = 0; inx < DsmList->Count; inx++) { - - deviceInfo = DsmList->IdList[inx]; - - if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { - - continue; - } - - - if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED && - deviceInfo->FailGroup->OutstandingBytesOfIO < leastOutstandingIO) { - - leastOutstandingIO = deviceInfo->FailGroup->OutstandingBytesOfIO; - failGroup = deviceInfo->FailGroup; - } - } - } - - if (failGroup) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Path to be used for LeastBlocks is %p.\n", - DsmList, - failGroup)); - - } else { - - // - // For ALUA storage there are two cases where we are left with no - // TPG in the A/O state: - // 1) On storage that supports implicit transitions, a transition - // was initiated that left no TPG in the A/O state. - // 2) On storage that has explicit only transitions enabled, we tried - // making at least one path as A/O and failed. This can happen, - // for example, when STPG fails because this initiator is not - // registered or does not hold exclusive reservation over the - // target. - // - // For such storages, we should return some path instead of just - // failing the I/O. The path will likely be an A/U path until the - // storage does a transition to make a TPG A/O. - // - if (!DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmList->IdList[0])) { - - // - // Use the same path as the one used for the previous request. - // - failGroup = groupEntry->PathToBeUsed; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpGetPath (DsmIds %p): Using same path (FOG %p) as previous request for LeastBlocks.\n", - DsmList, - failGroup)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Failed to find a path for LeastBlocks.\n", - DsmList)); - } - } - - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Invalid LB Type %d set for group %p.\n", - DsmList, - groupEntry->LoadBalanceType, - groupEntry)); - - DSM_ASSERT(FALSE); - - break; - } - } - -__Exit_DsmpGetPath: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpGetPath (DsmIds %p): Exiting function with failGroup %p.\n", - DsmList, - failGroup)); - - return failGroup; -} - - -PVOID -DsmpGetPathIdFromPassThroughPath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmList, - _In_ PIRP Irp, - _Inout_ IN OUT NTSTATUS *Status - ) -/*++ - -Routine Description: - - This routine will pick the path that corresponds to the PathId - in the mpio pass through structure. - - NOTE: Caller must ensure that the IRP is either MPTP or MPTPD. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DsmList - List of DSM Ids sent by MPIO - Irp - The MPTP or MPTPD request - Status - Returned status - -Return Value: - - The PathId to which the request should be sent ---*/ -{ - PDSM_FAILOVER_GROUP failGroup = NULL; - PDSM_GROUP_ENTRY groupEntry; - PDSM_DEVICE_INFO deviceInfo; - ULONG inx = 0; - NTSTATUS status = STATUS_INVALID_PARAMETER; - KIRQL irql; - PVOID newPath = NULL; - BOOLEAN found = FALSE; - BOOLEAN useScsiAddress = FALSE; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - ULONG controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; - UCHAR pathId = 0; - UCHAR targetId = 0; - UCHAR portNumber = 0; - ULONGLONG mpioPathId = 0; - -#if DBG - BOOLEAN useMpioPathId = FALSE; -#endif - - // - // Extract the parameters from the passthrough based on the bitness of the - // process (32 or 64) and the type of passthrough (legacy or extended). - // -#if defined (_WIN64) - if (IoIs32bitProcess(Irp)) { - - if (DsmpIsMPIOPassThroughEx(controlCode)) { - PMPIO_PASS_THROUGH_PATH32_EX mpioPassThroughPath32 = (PMPIO_PASS_THROUGH_PATH32_EX)(Irp->AssociatedIrp.SystemBuffer); - PSCSI_PASS_THROUGH32_EX passThrough32 = (PSCSI_PASS_THROUGH32_EX)((PUCHAR)mpioPassThroughPath32 + mpioPassThroughPath32->PassThroughOffset); - - useScsiAddress = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; - #if DBG - useMpioPathId = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_PATHID; - #endif - - if (useScsiAddress) { - PSTOR_ADDRESS address; - if (passThrough32->StorAddressOffset < sizeof(SCSI_PASS_THROUGH_EX) || - passThrough32->StorAddressLength < sizeof(STOR_ADDRESS)) { - *Status = STATUS_INVALID_PARAMETER; - return NULL; - } - address = (PSTOR_ADDRESS)((PUCHAR)passThrough32 + passThrough32->StorAddressOffset); - if (address->Type != STOR_ADDRESS_TYPE_BTL8 || - address->AddressLength < STOR_ADDR_BTL8_ADDRESS_LENGTH) { - *Status = STATUS_INVALID_PARAMETER; - return NULL; - } - pathId = ((PSTOR_ADDR_BTL8)address)->Path; - targetId = ((PSTOR_ADDR_BTL8)address)->Target; - portNumber = mpioPassThroughPath32->PortNumber; - } else { - mpioPathId = mpioPassThroughPath32->MpioPathId; - } - - } else { - PMPIO_PASS_THROUGH_PATH32 mpioPassThroughPath32 = (PMPIO_PASS_THROUGH_PATH32)(Irp->AssociatedIrp.SystemBuffer); - - useScsiAddress = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; - #if DBG - useMpioPathId = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_PATHID; - #endif - - if (useScsiAddress) { - pathId = mpioPassThroughPath32->PassThrough.PathId; - targetId = mpioPassThroughPath32->PassThrough.TargetId; - portNumber = mpioPassThroughPath32->PortNumber; - } else { - mpioPathId = mpioPassThroughPath32->MpioPathId; - } - } - } else -#endif - if (DsmpIsMPIOPassThroughEx(controlCode)) { - PMPIO_PASS_THROUGH_PATH_EX mpioPassThroughPath = (PMPIO_PASS_THROUGH_PATH_EX)(Irp->AssociatedIrp.SystemBuffer); - PSCSI_PASS_THROUGH_EX passThrough = (PSCSI_PASS_THROUGH_EX)((PUCHAR)mpioPassThroughPath + mpioPassThroughPath->PassThroughOffset); - - useScsiAddress = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; - #if DBG - useMpioPathId = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_PATHID; - #endif - - if (useScsiAddress) { - PSTOR_ADDRESS address; - if (passThrough->StorAddressOffset < sizeof(SCSI_PASS_THROUGH_EX) || - passThrough->StorAddressLength < sizeof(STOR_ADDRESS)) { - *Status = STATUS_INVALID_PARAMETER; - return NULL; - } - address = (PSTOR_ADDRESS)((PUCHAR)passThrough + passThrough->StorAddressOffset); - if (address->Type != STOR_ADDRESS_TYPE_BTL8 || - address->AddressLength < STOR_ADDR_BTL8_ADDRESS_LENGTH) { - *Status = STATUS_INVALID_PARAMETER; - return NULL; - } - pathId = ((PSTOR_ADDR_BTL8)address)->Path; - targetId = ((PSTOR_ADDR_BTL8)address)->Target; - portNumber = mpioPassThroughPath->PortNumber; - } else { - mpioPathId = mpioPassThroughPath->MpioPathId; - } - } else { - PMPIO_PASS_THROUGH_PATH mpioPassThroughPath = (PMPIO_PASS_THROUGH_PATH)(Irp->AssociatedIrp.SystemBuffer); - - useScsiAddress = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; - #if DBG - useMpioPathId = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_PATHID; - #endif - - if (useScsiAddress) { - pathId = mpioPassThroughPath->PassThrough.PathId; - targetId = mpioPassThroughPath->PassThrough.TargetId; - portNumber = mpioPassThroughPath->PortNumber; - } else { - mpioPathId = mpioPassThroughPath->MpioPathId; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpGetPathIdFromPassThroughPath (DsmIds %p): Entering function.\n", - DsmList)); - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - deviceInfo = DsmList->IdList[0]; - groupEntry = deviceInfo->Group; - DSM_ASSERT(groupEntry->GroupSig == DSM_GROUP_SIG); - // - // useMpioPathId is BOOLEAN (0 or 1) since MPIO_IOCTL_FLAG_USE_PATHID = 1 - // But since MPIO_IOCTL_FLAG_USE_SCSIADDRESS = 0x2, - // useScsiAddress could have a value of 2 if set. Use logical NOT to make boolean before comparing below - // - DSM_ASSERT(useMpioPathId == !useScsiAddress); - - for (inx = 0; inx < DSM_MAX_PATHS; inx++) { - - deviceInfo = groupEntry->DeviceList[inx]; - - if (deviceInfo) { - - failGroup = deviceInfo->FailGroup; - - if (failGroup) { - - if (useScsiAddress) { - - if (portNumber == deviceInfo->ScsiAddress->PortNumber && - pathId == deviceInfo->ScsiAddress->PathId && - targetId == deviceInfo->ScsiAddress->TargetId) { - - found = TRUE; - break; - } - } else { - - NT_ASSERT(useMpioPathId); - - if ((ULONGLONG)((ULONG_PTR)(failGroup->PathId)) == mpioPathId) { - - found = TRUE; - break; - } - } - } - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - if (found) { - - newPath = failGroup->PathId; - status = STATUS_SUCCESS; - - // - // This should not affect the next path chosen based on the - // current LB policy, so do NOT update groupEntry->PathToBeUsed - // - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpGetPathIdFromPassThroughPath (DsmIds %p): Failed to get corresponding path.\n", - DsmList)); - } - - if (Status) { - - *Status = status; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpGetPathIdFromPassThroughPath (DsmIds %p): Exiting function with path %p and status %x.\n", - DsmList, - newPath, - status)); - - return newPath; -} - - -BOOLEAN -DsmpShouldRetryTPGRequest( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ) -/*++ - -Routine Description: - - This routine determines if a Report/Set TargetPortGroup request (sent either - as a passThrough or as an IRP_MJ_SCSI) needs to be retried. - -Arguments: - - SenseData - Pointer to Sense Data information buffer. - SenseDataSize - Size of the passed in sense data buffer. - -Return Value: - - TRUE if sense information indicates a retry-able error, else FALSE. - ---*/ -{ - BOOLEAN retry = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryTPGRequest (SenseData %p): Entering function.\n", - SenseData)); - - // - // Two types of conditions need to be retried: - // 1. Asymmetric Access State Changed - // 2. Asymmetric Access State Transition - // - - // - // Check if asymmetric access state changed - // - retry = DsmpShouldRetryPassThroughRequest(SenseData, SenseDataSize); - if (!retry) { - - BOOLEAN validSense = FALSE; - UCHAR senseKey = 0; - UCHAR addSenseCode = 0; - UCHAR addSenseCodeQualifier = 0; - - validSense = ScsiGetSenseKeyAndCodes(SenseData, - SenseDataSize, - SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, - &senseKey, - &addSenseCode, - &addSenseCodeQualifier); - if (validSense) { - - if (senseKey == SCSI_SENSE_NOT_READY) { - - switch (addSenseCode) { - case SCSI_ADSENSE_LUN_NOT_READY: { - - // - // Check if asymmetric access state transitioning - // - if (addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION) { - - retry = TRUE; - } - break; - } - - case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: { - - if (addSenseCodeQualifier == SCSI_SENSEQ_REPORTED_LUNS_DATA_CHANGED) { - - retry = TRUE; - } - break; - } - - default: { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryTPGRequest (SenseData %p): AddSenseCode %x. Not retrying.\n", - SenseData, - addSenseCode)); - - retry = FALSE; - break; - } - } - } - } else { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryTPGRequest (SenseData %p): Sense data size %d not big enough.\n", - SenseData, - SenseDataSize)); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryTPGRequest (SenseData %p): Exiting function with retry %x.\n", - SenseData, - retry)); - - return retry; -} - - -BOOLEAN -DsmpIsDeviceRemoved( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ) -/*++ - -Routine Description: - - This routine evaluate Sense Data and determine if LUN is available or not. - -Arguments: - - SenseData - Pointer to Sense Data information buffer. - SenseDataSize - Size of the passed in sense data buffer. - -Return Value: - - TRUE if device is no longer available, else FALSE. - ---*/ -{ - BOOLEAN validSense = FALSE; - UCHAR senseKey = 0; - UCHAR addSenseCode = 0; - UCHAR addSenseCodeQualifier = 0; - BOOLEAN bRemoved = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpIsDeviceRemoved (SenseData %p): Entering function.\n", - SenseData)); - - validSense = ScsiGetSenseKeyAndCodes(SenseData, - SenseDataSize, - SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, - &senseKey, - &addSenseCode, - &addSenseCodeQualifier); - - if (validSense) { - // - // SPC 3 6.25 suggests response should follow Test Unit Ready responses - // For now, we accept Ileegal Request as an indication of device not in available - // state. - // - if (senseKey == SCSI_SENSE_ILLEGAL_REQUEST) { - - ASSERT(addSenseCodeQualifier == 0); //LOGICAL UNIT NOT SUPPORTED - - bRemoved = TRUE; - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpIsDeviceRemoved (SenseData %p): SenseKey %x AddSenseCode %x. Remove %x\n", - SenseData, - senseKey, - addSenseCode, - bRemoved)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpIsDeviceRemoved (SenseData %p): Exiting function. Removed %x.\n", - SenseData, - bRemoved)); - - return bRemoved; -} - - -BOOLEAN -DsmpReservationCommand( - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb - ) -/*++ - -Routine Description: - - This routine examines the DeviceIoControlCode and Srb OpCode to determine - if this is PR request. - -Arguments: - - Irp - The Irp containing Srb. - Srb - The current non-read/write Srb. - -Return Value: - - TRUE - If it's a special-case command (some reservation-handling request). - ---*/ -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - UCHAR opCode = 0; - BOOLEAN isReservationCommand = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpReservationCommand (Irp %p): Entering function.\n", - Irp)); - - // - // Ensure it's a scsi request before checking the opcode. - // - if (irpStack->MajorFunction == IRP_MJ_SCSI) { - - PCDB cdb = SrbGetCdb(Srb); - if (cdb != NULL) { - opCode = cdb->AsByte[0]; - - if (opCode == SCSIOP_PERSISTENT_RESERVE_IN || opCode == SCSIOP_PERSISTENT_RESERVE_OUT) { - - // - // Set or release a reservation. - // - isReservationCommand = TRUE; - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpReservationCommand (Irp %p): Exiting function - IsReservationCmd %x.\n", - Irp, - isReservationCommand)); - - return isReservationCommand; -} - - -BOOLEAN -DsmpMpioPassThroughPathCommand( - _In_ IN PIRP Irp - ) -/*++ - -Routine Description: - - This routine examines the DeviceIoControlCode to determine whether this is - either a mpio pass through or a mpio pass through direct. If so, it needs - to be handled via a specific path indicated by the caller. - -Arguments: - - Irp - The Irp. - -Return Value: - - TRUE - If it is either MPTP or MPTPD. - FALSE - Otherwise. - ---*/ -{ - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - ULONG ioctlCode; - BOOLEAN isMPTPCommand = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpMpioPassThroughPathCommand (Irp %p): Entering function.\n", - Irp)); - - if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { - - // - // Check whether this is a MPTP, MPTPD, or an extended flavor. - // - ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; - - if (ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH || - ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH_DIRECT || - ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH_EX || - ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH_DIRECT_EX) { - - isMPTPCommand = TRUE; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpMpioPassThroughPathCommand (Irp %p): Exiting function - IsMpioPassThruPathCmd %!bool!.\n", - Irp, - isMPTPCommand)); - - return isMPTPCommand; -} - - -VOID -DsmpRequestComplete( - _In_ IN PVOID DsmId, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PVOID DsmContext - ) -/*++ - -Routine Description: - - This routine is called from mpio's completion routine when the Irp - has been completed by the port driver. Currently, it updates some counters - and free's the context back to the look-aside list. - -Arguments: - - DsmIds - The collection of DSM IDs that pertain to the MPDISK. - Irp - Irp containing SRB. - Srb - Scsi request block - DsmContext - DSM context given to MPIO during initialization - -Return Value: - - NONE - ---*/ - -{ - PDSM_DEVICE_INFO deviceInfo = DsmId; - PDSM_CONTEXT dsmContext = (PDSM_CONTEXT)DsmContext; - UCHAR opCode = 0xFF; - ULONG dataTransferLength = 0; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PDSM_FAILOVER_GROUP failGroup = irpStack->Parameters.Others.Argument3; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpRequestComplete (DevInfo %p): Entering function.\n", - DsmId)); - - DSM_ASSERT(DsmContext); - - if (Srb) { - PCDB cdb = SrbGetCdb(Srb); - if (cdb) { - opCode = cdb->AsByte[0]; - } - dataTransferLength = SrbGetDataTransferLength(Srb); - } - - // - // Extract the interesting bits from the context struct. - // - - if (failGroup) { - - if (DsmpDecrementCounters(failGroup, Srb)) { - - // - // If there are no requests on a path that is supposed to be removed, remove it now. - // - if (failGroup->State == DSM_FG_PENDING_REMOVE) { - - KIRQL oldIrql; - - NT_ASSERT(failGroup->Count == 0); - - oldIrql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - RemoveEntryList(&failGroup->ListEntry); - InterlockedDecrement((LONG volatile*)&dsmContext->NumberStaleFOGroups); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpRequestComplete (DevInfo %p): Removing FOGroup %p with path %p.\n", - DsmId, - failGroup, - failGroup->PathId)); - - DsmpFreePool(failGroup); - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), oldIrql); - } - } - } - - // - // Note: We use the deviceInfo passed in since the one saved off in the - // context may be stale in the case of a retried I/O - // - if (deviceInfo) { - - // - // If statistics gathering is enabled update the inflight request count - // for this device-path pairing. - // - if (!dsmContext->DisableStatsGathering) { - - // - // Indicate one less request on this device. - // Update the path that on which the increment was done. - // - if (InterlockedCompareExchange((LONG volatile*)&deviceInfo->NumberOfRequestsInProgress, 0, 0) > 0) { - InterlockedDecrement(&(deviceInfo->NumberOfRequestsInProgress)); - } - } - - // - // If statistics gathering is enabled, we are interested in read/write requests - // - if (!dsmContext->DisableStatsGathering) { - - // - // If it's a read or a write, update the stats. - // Use the path that was cached during dispatch. - // - if (DsmIsReadRequest(opCode)) { - - if (deviceInfo->DeviceStats.NumberReads <= MAXULONG) { - - InterlockedIncrement((LONG volatile*)&deviceInfo->DeviceStats.NumberReads); - } - - if ((MAXULONGLONG - dataTransferLength) > deviceInfo->DeviceStats.BytesRead) { - - deviceInfo->DeviceStats.BytesRead += dataTransferLength; - - } else { - - deviceInfo->DeviceStats.BytesRead = MAXULONGLONG; - } - - } else if (DsmIsWriteRequest(opCode)) { - - if (deviceInfo->DeviceStats.NumberWrites <= MAXULONG) { - - InterlockedIncrement((LONG volatile*)&deviceInfo->DeviceStats.NumberWrites); - } - - if ((MAXULONGLONG - dataTransferLength) > deviceInfo->DeviceStats.BytesWritten) { - - deviceInfo->DeviceStats.BytesWritten += dataTransferLength; - - } else { - - deviceInfo->DeviceStats.BytesWritten = MAXULONGLONG; - } - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpRequestComplete (DevInfo %p): Exiting function.\n", - DsmId)); - - return; -} - - -NTSTATUS -DsmpRegisterPersistentReservationKeys( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN BOOLEAN Register - ) -/*++ - -Routine Description: - - This routine is used to build and send down the request to register - or unregister the persistent reservation keys to the device down - the path given by DeviceInfo. - -Arguments: - - DeviceInfo - Device-path pair to use for sending down the request - Register - Flag to indicate whether to register or unregister the keys. - -Return Value: - - STATUS_SUCCESS on success, else appropriate failure code. - ---*/ -{ - PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; - PCDB cdb; - PPRO_PARAMETER_LIST parameters; - IO_STATUS_BLOCK ioStatus; - NTSTATUS status = STATUS_SUCCESS; - ULONG length; - PDSM_DEVICE_INFO deviceInfo = DeviceInfo; - PDSM_GROUP_ENTRY group; - ULONGLONG saKey; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Entering function - Register = %x.\n", - deviceInfo, - Register)); - - group = DeviceInfo->Group; - - NT_ASSERT(group && group->PRKeyValid); - - if (DeviceInfo->State >= DSM_DEV_FAILED) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Unusable - state %d.\n", - deviceInfo, - deviceInfo->State)); - - status = STATUS_UNSUCCESSFUL; - goto __Exit_DsmpRegisterPersistentReservationKeys; - } - - // - // Build a pass through command to process Persistent Reserve Out - // for registering the device. - // - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - passThrough = DsmpAllocatePool(NonPagedPoolNx, - length, - DSM_TAG_PASS_THRU); - if (!passThrough) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Failed to allocate memory for persistent reserve.\n", - deviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegisterPersistentReservationKeys; - } - - REVERSE_BYTES_QUAD(&saKey, &group->PersistentReservationRegisteredKey); - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Attempting PR-Out SA %u, Type %u, Scope %u, PR-Key %I64x.\n", - deviceInfo, - group->PRServiceAction, - group->PRType, - group->PRScope, - saKey)); - -__RetryRequest: - - // - // Build the cdb to reserve the device (Logical Unit). The type of reservation - // scope and service action is whatever cluster service provided at the time of - // sending down registration to this device before this particular path was available. - // - cdb = (PCDB) passThrough->ScsiPassThrough.Cdb; - cdb->PERSISTENT_RESERVE_OUT.OperationCode = SCSIOP_PERSISTENT_RESERVE_OUT; - cdb->PERSISTENT_RESERVE_OUT.ServiceAction = group->PRServiceAction; - cdb->PERSISTENT_RESERVE_OUT.Scope = group->PRScope; - cdb->PERSISTENT_RESERVE_OUT.Type = group->PRType; - cdb->PERSISTENT_RESERVE_OUT.ParameterListLength[1] = sizeof(PRO_PARAMETER_LIST); - - passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); - passThrough->ScsiPassThrough.CdbLength = 10; - passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; - passThrough->ScsiPassThrough.DataIn = 0; - passThrough->ScsiPassThrough.DataTransferLength = sizeof(PRO_PARAMETER_LIST); - passThrough->ScsiPassThrough.TimeOutValue = 20; - passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); - passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); - - parameters = (PPRO_PARAMETER_LIST)(passThrough->DataBuffer); - - // - // Copy the persistent reservation key given by cluster service to - // Service Action Reservation Key. This key will be registered - // with the device. - // - // Set ServiceActionReservationKey to the well-known key if we are registering. - // Note that to unregister ServiceActionReservationKey needs to be set to 0. - // - if (Register) { - - RtlCopyMemory(parameters->ServiceActionReservationKey, group->PersistentReservationRegisteredKey, 8); - - } else { - - RtlCopyMemory(parameters->ReservationKey, group->PersistentReservationRegisteredKey, 8); - RtlZeroMemory(parameters->ServiceActionReservationKey, 8); - } - - DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, - DeviceInfo->TargetObject, - passThrough, - passThrough, - length, - length, - FALSE, - &ioStatus); - - status = ioStatus.Status; - - if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(ioStatus.Status))) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Persistent Reserve (Register Key) succeeded using %p.\n", - deviceInfo, - DeviceInfo)); - - } else { - - PUCHAR senseData; - UCHAR senseInfoLength; - - senseData = (PUCHAR)(passThrough->SenseInfoBuffer); - senseInfoLength = passThrough->ScsiPassThrough.SenseInfoLength; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): DevInfo %p, Register keys (%d): NTStatus %x, ScsiStatus %x.\n", - deviceInfo, - DeviceInfo, - Register, - ioStatus.Status, - passThrough->ScsiPassThrough.ScsiStatus)); - - if (DsmpShouldRetryPassThroughRequest((PVOID)senseData, senseInfoLength)) { - - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - RtlZeroMemory(passThrough, length); - - goto __RetryRequest; - - } else if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Will change success to error status for register\n", - deviceInfo)); - - status = STATUS_INVALID_DEVICE_REQUEST; - } - } - - // - // Free the passthrough + data buffer. - // - DsmpFreePool(passThrough); - -__Exit_DsmpRegisterPersistentReservationKeys: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpRegisterPersistentReservationKeys (DevInfo %p): Exiting function with status %x.\n", - DeviceInfo, - status)); - - return status; -} - - - -BOOLEAN -DsmpShouldRetryPassThroughRequest( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ) -/*++ - -Routine Description: - - This routine determines if a passthrough request needs to be retried based on the - information in the passed in sense data. - -Arguments: - - SenseData - Pointer to Sense Data information buffer. - SenseDataSize - Size of the passed in sense data buffer. - -Return Value: - - TRUE if sense information indicates a retry-able error, else FALSE. - ---*/ -{ - BOOLEAN validSense = FALSE; - UCHAR senseKey = 0; - UCHAR addSenseCode = 0; - BOOLEAN retry = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPassThroughRequest (SenseData %p): Entering function.\n", - SenseData)); - -#if DBG - if (SenseDataSize > 0) { - - ULONG inx; - PUCHAR senseInfo; - - - senseInfo = (PUCHAR) SenseData; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPassThroughRequest (SenseData %p): Sense info length %d. Sense Info : ", - SenseData, - SenseDataSize)); - - for (inx = 0; inx < SenseDataSize; inx++) { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "%x ", - senseInfo[inx])); - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "\n")); - } -#endif - - validSense = ScsiGetSenseKeyAndCodes(SenseData, - SenseDataSize, - SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, - &senseKey, - &addSenseCode, - NULL); - if (validSense) { - if (senseKey == SCSI_SENSE_UNIT_ATTENTION) { - - switch (addSenseCode) { - case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: - case SCSI_ADSENSE_BUS_RESET: - case SCSI_ADSENSE_PARAMETERS_CHANGED: { - retry = TRUE; - break; - } - - default: { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPassThroughRequest (SenseData %p): AddSenseCode %x. Not retrying.\n", - SenseData, - addSenseCode)); - - retry = FALSE; - break; - } - } - } - } else { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPassThroughRequest (SenseData %p): Sense data size %d not big enough.\n", - SenseData, - SenseDataSize)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPassThroughRequest (SenseData %p): Exiting function with retry %x.\n", - SenseData, - retry)); - - return retry; -} - - -BOOLEAN -DsmpShouldRetryPersistentReserveCommand( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ) -/*++ - -Routine Description: - - This routine determines if a a PR request needs to be retried based on the - information in the passed in sense data. - -Arguments: - - SenseData - Pointer to Sense Data information buffer. - SenseDataSize - Size of the passed in sense data buffer. - -Return Value: - - TRUE if sense information indicates a retry-able error, else FALSE. - ---*/ -{ - BOOLEAN retry = FALSE; - BOOLEAN validSense = FALSE; - UCHAR senseKey = 0; - UCHAR addSenseCode = 0; - UCHAR addSenseCodeQualifier = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPersistentReserveCommand (SenseData %p): Entering function.\n", - SenseData)); - - retry = DsmpShouldRetryPassThroughRequest(SenseData, SenseDataSize); - - if (!retry) { - validSense = ScsiGetSenseKeyAndCodes(SenseData, - SenseDataSize, - SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, - &senseKey, - &addSenseCode, - &addSenseCodeQualifier); - if (validSense) { - - // - // If the TPG is in transitioning state, retry the request - // - if ((senseKey == SCSI_SENSE_UNIT_ATTENTION || senseKey == SCSI_SENSE_NOT_READY) && - (addSenseCode == SCSI_ADSENSE_LUN_NOT_READY && - addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION)) { - - retry = TRUE; - } - } else { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPersistentReserveCommand (SenseData %p): Sense data size %d not big enough.\n", - SenseData, - SenseDataSize)); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpShouldRetryPersistentReserveCommand (SenseData %p): Exiting function with retry %x.\n", - SenseData, - retry)); - - return retry; -} - - -VOID -DsmpAllowStandbyPathsToRest( - _In_ PDSM_GROUP_ENTRY Group - ) -/*++ - -Routine Description: - - This routine is called when a new path is available for a device - and has a desired state of ACTIVE_O. Since this will be an ACTIVE_O - path we see if there are any paths with a desired state of Standby - but that are currently active. These paths can be safely moved by - to standby. - - This routine assumes that the lock is held - -Arguements: - - Group is the multipath group - -Return Value: - - None ---*/ -{ - PDSM_DEVICE_INFO existingDeviceInfo; - ULONG inx; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpAllowStandbyPathsToRest (Group %p): Entering function.\n", - Group)); - - for (inx = 0; inx < Group->NumberDevices; inx++) { - - existingDeviceInfo = Group->DeviceList[inx]; - - if ((existingDeviceInfo->DesiredState == DSM_DEV_STANDBY) && - (existingDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED)) { - - existingDeviceInfo->State = DSM_DEV_STANDBY; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpAllowStandbyPathsToRest (Group %p): DevInfo %p changed to state %d at %d\n", - Group, - existingDeviceInfo, - existingDeviceInfo->State, - __LINE__)); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpAllowStandbyPathsToRest (Group %p): Exiting function.\n", - Group)); - return; -} - - -PDSM_DEVICE_INFO -DsmpGetAnyActivePath( - _In_ PDSM_GROUP_ENTRY Group, - _In_ BOOLEAN Exception, - _In_opt_ PDSM_DEVICE_INFO DeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine will return an active path from the list - - This routine assumes that the DSM lock is held - -Arguements: - - Group is the multipath group - Exception - if TRUE, indicates that the returned devInfo must not be the same - as the one passed in. - DeviceInfo - the must-not-match devInfo. Valid parameter only if Exception is - TRUE. - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - active path or NULL - ---*/ -{ - PDSM_DEVICE_INFO existingDeviceInfo; - PDSM_DEVICE_INFO candidateDevInfo = NULL; - ULONG inx; - - UNREFERENCED_PARAMETER(SpecialHandlingFlag); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetAnyActivePath (Group %p): Entering function.\n", - Group)); - - for (inx = 0; inx < DSM_MAX_PATHS; inx++) { - - existingDeviceInfo = Group->DeviceList[inx]; - - if (existingDeviceInfo && - existingDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED && - DsmpIsDeviceInitialized(existingDeviceInfo) && - DsmpIsDeviceUsable(existingDeviceInfo) && - DsmpIsDeviceUsablePR(existingDeviceInfo)) { - - - if (Exception && existingDeviceInfo == DeviceInfo) { - continue; - } - - candidateDevInfo = existingDeviceInfo; - break; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetAnyActivePath (Group %p): Exiting function with DevInfo %p\n", - Group, - candidateDevInfo)); - - return candidateDevInfo; -} - - -PDSM_DEVICE_INFO -DsmpGetActivePathToBeUsed( - _In_ PDSM_GROUP_ENTRY Group, - _In_ BOOLEAN Symmetric, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine will return an active path from the list that should - be the next one used by the DSM - - This routine assumes that the DSM lock is held - -Arguements: - - Group is the multipath group - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - active path or NULL - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetActivePathToBeUsed (Group %p): Entering function.\n", - Group)); - - deviceInfo = NULL; - - switch (Group->LoadBalanceType) { - - case DSM_LB_LEAST_BLOCKS: - case DSM_LB_DYN_LEAST_QUEUE_DEPTH: { - - // - // Since we choose the path with the smallest queue or cumulative size in - // DsmpGetPath, we just pick any path now - // - - // fall through - } - - case DSM_LB_ROUND_ROBIN_WITH_SUBSET: - case DSM_LB_ROUND_ROBIN: { - - // - // For RR and RRS we just pick any active path to start with - // and the DsmpGetPath will do the round robining - // - } - - case DSM_LB_FAILOVER: { - - deviceInfo = DsmpGetAnyActivePath(Group, FALSE, NULL, SpecialHandlingFlag); - - break; - } - - case DSM_LB_WEIGHTED_PATHS: { - - PDSM_DEVICE_INFO workDeviceInfo; - ULONG weight = (ULONG) -1; - ULONG inx; - - for (inx = 0; inx < Group->NumberDevices; inx++) { - - workDeviceInfo = Group->DeviceList[inx]; - - if ((workDeviceInfo) && - (DsmpIsDeviceInitialized(workDeviceInfo)) && - (DsmpIsDeviceUsable(workDeviceInfo)) && - (DsmpIsDeviceUsablePR(workDeviceInfo)) && - (workDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) && - (workDeviceInfo->PathWeight < weight)) { - - // - // We found a path that is active and is at - // the lowest weight. Remember it. - // - weight = workDeviceInfo->PathWeight; - - deviceInfo = workDeviceInfo; - } - } - - break; - } - - default: { - - break; - } - } - - if (!deviceInfo && !Symmetric) { - - // - // In the case of implicit transitions, it is possible that a TPG hasn't yet - // been made A/O. So instead of not setting any path, fall back to using some - // other path. IO sent down this path may fail, but will be retried in - // InterpretError(). Hopefully by then, at least one TPG will have transitioned - // to A/O state. - // - // The same argument holds true if the storage supports both implicit and - // explicit transitions, since it is possible that after we explicitly changed - // the TPG states, an implicit transition left us with no path in A/O state. - // - // In the case of explicit only transitions, we tried making at least one path - // as A/O and failed. This can happen, for example, when STPG fails because - // this initiator is not registered or does not hold exclusive reservation over - // the target. Instead of not using any path, we can consider a path in A/U state, - // A/U being just a functional path state. - // - BOOLEAN sendTPG = FALSE; - - deviceInfo = DsmpFindStandbyPathToActivateALUA(Group, &sendTPG, SpecialHandlingFlag); - - if ((deviceInfo != NULL) && - ((deviceInfo->ALUASupport != DSM_DEVINFO_ALUA_EXPLICIT) || - ((deviceInfo->ALUASupport == DSM_DEVINFO_ALUA_EXPLICIT) && - (deviceInfo->State <= DSM_DEV_ACTIVE_UNOPTIMIZED)))) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpGetActivePathToBeUsed (Group %p): Using best alternative candidate device %p\n", - Group, - deviceInfo)); - } else { - - deviceInfo = NULL; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpGetActivePathToBeUsed (Group %p): No active/alternative path available for group\n", - Group)); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetActivePathToBeUsed (Group %p): Exiting function with devInfo %p.\n", - Group, - deviceInfo)); - - return deviceInfo; -} - - -PDSM_DEVICE_INFO -DsmpFindStandbyPathToActivate( - _In_ PDSM_GROUP_ENTRY Group, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine will find another path in the group that is active - - This routine assumes that the DSM lock is held - - This is used by devices that support symmetric LUA. - -Arguements: - - Group is the multipath group - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Standby path or NULL if no standby path is available - ---*/ -{ - PDSM_DEVICE_INFO existingDeviceInfo; - ULONG inx; - PDSM_DEVICE_INFO candidateDevInfo = NULL; - - UNREFERENCED_PARAMETER(SpecialHandlingFlag); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindStandbyPathToActivate(Group %p): Entering function.\n", - Group)); - - for (inx = 0; inx < Group->NumberDevices; inx++) { - - existingDeviceInfo = Group->DeviceList[inx]; - - if (existingDeviceInfo && - existingDeviceInfo->State == DSM_DEV_STANDBY && - DsmpIsDeviceInitialized(existingDeviceInfo) && - DsmpIsDeviceUsable(existingDeviceInfo) && - DsmpIsDeviceUsablePR(existingDeviceInfo)) { - - // - // If we don't as yet have a candidate, pick the first available one. - // However, our preference is one that is through the preferred TPG. - // - if (!candidateDevInfo || - existingDeviceInfo->TargetPortGroup && existingDeviceInfo->TargetPortGroup->Preferred) { - - candidateDevInfo = existingDeviceInfo; - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindStandbyPathToActivate (Group %p): Exiting function with devInfo %p.\n", - Group, - candidateDevInfo)); - - return candidateDevInfo; -} - - -PDSM_DEVICE_INFO -DsmpFindStandbyPathToActivateALUA( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PBOOLEAN SendTPG, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine will find another path in the group that is active - - This is used by devices that don't support symmetric LUA. - - N.B: This routine MUST be called with DsmContextLock held in either Shared or - Exclusive mode. - -Arguements: - - Group is the multipath group - SendTPG - output parameter that indicates if TPG command need to be sent down. - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Standby path or NULL if no standby path is available - ---*/ -{ - PDSM_DEVICE_INFO existingDeviceInfo; - ULONG inx; - PDSM_DEVICE_INFO candidateDevInfo = NULL; - - UNREFERENCED_PARAMETER(SpecialHandlingFlag); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindStandbyPathToActivateALUA (Group %p): Entering function.\n", - Group)); - - for (inx = 0; inx < Group->NumberDevices; inx++) { - - existingDeviceInfo = Group->DeviceList[inx]; - - // - // The candidate for making A/O obviously mustn't be in a failed state - // and should have a path assigned. - // - if (existingDeviceInfo && - !DsmpIsDeviceFailedState(existingDeviceInfo->State) && - DsmpIsDeviceInitialized(existingDeviceInfo) && - DsmpIsDeviceUsable(existingDeviceInfo) && - DsmpIsDeviceUsablePR(existingDeviceInfo)) { - - // - // If we don't have any candidate currently, choose the very first - // one that is in a non-failure state, regardless of what state it - // may be in. - // - if (!candidateDevInfo) { - - candidateDevInfo = existingDeviceInfo; - *SendTPG = TRUE; - } - - // - // Might as well use one that the Admin desires for to be in A/O - // - if (existingDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) { - - // - // However, such a devInfo is not a better candidate if our candidate - // devInfo is also one that the Admin desires be in A/O, and it is - // through a preferred TPG. - // - if (!(existingDeviceInfo->DesiredState == candidateDevInfo->DesiredState && - candidateDevInfo->TargetPortGroup->Preferred)) { - - candidateDevInfo = existingDeviceInfo; - *SendTPG = TRUE; - } - } - - // - // Check if the current one is at least better than the candidate. - // - if (DsmpIsBetterDeviceState(candidateDevInfo->State, existingDeviceInfo->State)) { - - candidateDevInfo = existingDeviceInfo; - *SendTPG = TRUE; - } - - // - // We found one that we may have just masked as non-A/O. This is the - // best option as we don't have to send down an STPG. - // - if (existingDeviceInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { - - candidateDevInfo = existingDeviceInfo; - *SendTPG = FALSE; - break; - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindStandbyPathToActivateALUA (Group %p): Exiting function with devInfo %p.\n", - Group, - candidateDevInfo)); - - return candidateDevInfo; -} - - -PDSM_DEVICE_INFO -DsmpFindStandbyPathInAlternateTpgALUA( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine will find another path in the group that is not in the same - TPG as the passed in DeviceInfo. - - This routine assumes that the DSM lock is held - - This is used by devices that support ALUA. - -Arguements: - - Group is the multipath group - DeviceInfo is the devInfo whose TPG must not be matched - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Standby path not in same TPG as passed in DeviceInfo - or NULL if no standby path is available - ---*/ -{ - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = DeviceInfo->TargetPortGroup; - PDSM_DEVICE_INFO existingDeviceInfo; - ULONG inx; - PDSM_DEVICE_INFO candidateDevInfo = NULL; - - UNREFERENCED_PARAMETER(SpecialHandlingFlag); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindStandbyPathInAlternateTpgALUA (DevInfo %p): Entering function.\n", - DeviceInfo)); - - for (inx = 0; inx < Group->NumberDevices; inx++) { - - existingDeviceInfo = Group->DeviceList[inx]; - - // - // We only care about deviceInfo if TPG is different - // - if (existingDeviceInfo && existingDeviceInfo->TargetPortGroup != targetPortGroup) { - - // - // The candidate for making A/O obviously mustn't be in a failed state - // and must be initialized - // - if (!DsmpIsDeviceFailedState(existingDeviceInfo->State) && - DsmpIsDeviceInitialized(existingDeviceInfo) && - DsmpIsDeviceUsable(existingDeviceInfo) && - DsmpIsDeviceUsablePR(existingDeviceInfo)) { - - // - // If we don't have any candidate currently, choose the very first - // one that is in a non-failure state, regardless of what state it - // may be in. - // - if (!candidateDevInfo) { - - candidateDevInfo = existingDeviceInfo; - continue; - } - - // - // Check if the current one is at least better than the candidate. - // - if (DsmpIsBetterDeviceState(candidateDevInfo->State, existingDeviceInfo->State)) { - - candidateDevInfo = existingDeviceInfo; - } - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFindStandbyPathInAlternateTpgALUA (DevInfo %p): Exiting function with devInfo %p.\n", - DeviceInfo, - candidateDevInfo)); - - return candidateDevInfo; -} - - -NTSTATUS -DsmpSetLBForDsmPolicyAdjustment( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ) - -/*++ - -Routine Description: - - This routine is called when a change is made to the DSM-wide default - load balance policy. It goes through each LUN representation (ie. Group - entry) and updates the appropriate ones (ie. ones for which the policy - was not chosen based on VID/PID or because of an explicit settings on - the LUN). It also then updates the path states in accordance with the - new LB policy. - -Arguements: - - DsmContext is the DSM context - LoadBalanceType is the new load balance policy to be applied - PreferredPath is the preferred failback path to be used (applicable only - if LB policy is Failover) - -Return Value: - - Success - ---*/ - -{ - NTSTATUS status = STATUS_SUCCESS; - KIRQL oldIrql; - PLIST_ENTRY entry; - ULONG groupIndex = 0; - ULONG devInfoIndex; - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO devInfo; - DSM_LOAD_BALANCE_TYPE newLoadBalancePolicy; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetLBForDsmPolicyAdjustment (DsmContext %p): Entering function.\n", - DsmContext)); - - oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - for (entry = DsmContext->GroupList.Flink; entry != &(DsmContext->GroupList); entry = entry->Flink, groupIndex++) { - - group = CONTAINING_RECORD(entry, DSM_GROUP_ENTRY, ListEntry); - - newLoadBalancePolicy = LoadBalanceType; - - // - // Only LUNs that don't have their policy explicitly set - // and ones that don't have it set based on VID/PID are - // of interest to us here. - // - if (group->LBPolicySelection == DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY || - group->LBPolicySelection == DSM_DEFAULT_LB_POLICY_DSM_WIDE) { - - // - // Also, if the caller is trying to clear the DSM-wide - // default policy, then we don't even care about those - // LUNs whose policies were not set using this value. - // - if (newLoadBalancePolicy < DSM_LB_FAILOVER && - group->LBPolicySelection != DSM_DEFAULT_LB_POLICY_DSM_WIDE) { - - continue; - } - - // - // If the DSM-wide setting is being cleared, we need to fall back - // to using the default based on the array's ALUA capabilities. - // - if (newLoadBalancePolicy < DSM_LB_FAILOVER) { - - newLoadBalancePolicy = DSM_LB_ROUND_ROBIN; - group->PreferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; - - - } else { - - // - // Since a new policy has been selected for the DSM-wide - // one, it needs to be applied to this LUN. - // - group->PreferredPath = (ULONGLONG)((ULONG_PTR)PreferredPath); - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; - } - - // - // If Round Robin is set and ALUA is enabled, we need to change the - // policy to Round Robin with Subset. - // - if (!DsmpIsSymmetricAccess(group->DeviceList[0]) && newLoadBalancePolicy == DSM_LB_ROUND_ROBIN) { - - newLoadBalancePolicy = DSM_LB_ROUND_ROBIN_WITH_SUBSET; - } - - // - // Finally set the new load balance policy. - // - group->LoadBalanceType = newLoadBalancePolicy; - - // - // Path states need to be updated in accordance with the new policy. - // - for (devInfoIndex = 0; devInfoIndex < DSM_MAX_PATHS; devInfoIndex++) { - - devInfo = group->DeviceList[devInfoIndex]; - DsmpSetNewDefaultLBPolicy(DsmContext, devInfo, group->LoadBalanceType, SpecialHandlingFlag); - } - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetLBForDsmPolicyAdjustment (DsmContext %p): Exiting function with status %x\n", - DsmContext, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForVidPidPolicyAdjustment( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PWSTR TargetHardwareId, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ) - -/*++ - -Routine Description: - - This routine is called when a change is made to the default load balance - policy for a VID/PID. It goes through each LUN representation (ie. Group - entry) and updates the appropriate ones (ie. ones for which the policy - was not because of an explicit settings on the LUN). It also then updates - the path states in accordance with the new LB policy. - -Arguements: - - DsmContext is the DSM context - TargetHardwareId is the VID/PID whose matching LUNs policy need to be updated - LoadBalanceType is the new load balance policy to be applied - PreferredPath is the preferred failback path to be used (applicable only - if LB policy is Failover) - -Return Value: - - Success - ---*/ - -{ - NTSTATUS status = STATUS_SUCCESS; - KIRQL oldIrql; - PLIST_ENTRY entry; - ULONG groupIndex = 0; - ULONG devInfoIndex; - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO devInfo; - DSM_LOAD_BALANCE_TYPE dsmLoadBalanceType; - ULONGLONG dsmPreferredPath; - BOOLEAN useDsmLBSettings = FALSE; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetLBForVidPidPolicyAdjustment (%ws): Entering function.\n", - TargetHardwareId)); - - status = DsmpQueryDsmLBPolicyFromRegistry(&dsmLoadBalanceType, &dsmPreferredPath); - - if (NT_SUCCESS(status)) { - - useDsmLBSettings = TRUE; - - } else { - - if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - - status = STATUS_SUCCESS; - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_WMI, - "DsmpSetLBForVidPidPolicyAdjustment (%ws): MSDSM-wide default LB policy not set.\n", - TargetHardwareId)); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLBForVidPidPolicyAdjustment (%ws): Failed to query MSDMS-wide default LB setting. Status %x.\n", - TargetHardwareId, - status)); - } - } - - oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - for (entry = DsmContext->GroupList.Flink; entry != &(DsmContext->GroupList); entry = entry->Flink, groupIndex++) { - - group = CONTAINING_RECORD(entry, DSM_GROUP_ENTRY, ListEntry); - - // - // Only LUNs that don't have their policy explicitly set - // are of interest to us here. - // - if (group->LBPolicySelection < DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT) { - - // - // Figure out if this LUN matches the VID/PID of interest - // Device not of interest if it doesn't match the passed in target ID - // - if (wcscmp(group->HardwareId, TargetHardwareId) != 0) { - - continue; - } - - // - // Also, if the caller is trying to clear the VID/PID - // default policy, then we don't even care about those - // LUNs whose policies were not set using this value. - // - if (LoadBalanceType < DSM_LB_FAILOVER && - group->LBPolicySelection != DSM_DEFAULT_LB_POLICY_VID_PID) { - - continue; - } - - // - // If the VID/PID setting is being cleared, we need to fall back - // to using the DSM-wide default policy if it has been set, else - // we need to use the default based on the array's ALUA capabilities. - // - if (LoadBalanceType < DSM_LB_FAILOVER) { - - if (useDsmLBSettings) { - - // - // Even if the MSDSM-wide policy is specified as RR, if the storage - // is ALUA, we can't have the policy as RR, so we'll change it to - // RRWS instead. - // - if (!DsmpIsSymmetricAccess(group->DeviceList[0]) && dsmLoadBalanceType == DSM_LB_ROUND_ROBIN) { - - group->LoadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; - - } else { - - group->LoadBalanceType = dsmLoadBalanceType; - } - - group->PreferredPath = (ULONGLONG)((ULONG_PTR)dsmPreferredPath); - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; - - } else { - - // - // Default LB type: - // is Round Robin if ALUA is not supported, or if ALUA support is implicit but access is symmetric, - // else Round Robin With Subset (since in ALUA, all paths aren't in A/O). - // - if (DsmpIsSymmetricAccess(group->DeviceList[0])) { - - group->LoadBalanceType = DSM_LB_ROUND_ROBIN; - - } else { - - group->LoadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; - } - - - group->PreferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; - } - - } else { - - // - // Since a new policy has been selected for the DSM-wide - // one, it needs to be applied to this LUN. - // - // However, if the VID/PID policy is specified as RR but the storage - // is ALUA, we can't have the policy as RR, so we'll change it to - // RRWS instead. - // - if (!DsmpIsSymmetricAccess(group->DeviceList[0]) && LoadBalanceType == DSM_LB_ROUND_ROBIN) { - - group->LoadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; - - } else { - - group->LoadBalanceType = LoadBalanceType; - } - - group->PreferredPath = (ULONGLONG)((ULONG_PTR)PreferredPath); - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_VID_PID; - } - - // - // Path states need to be updated in accordance with the new policy. - // - for (devInfoIndex = 0; devInfoIndex < DSM_MAX_PATHS; devInfoIndex++) { - - devInfo = group->DeviceList[devInfoIndex]; - DsmpSetNewDefaultLBPolicy(DsmContext, devInfo, group->LoadBalanceType, SpecialHandlingFlag); - } - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetLBForVidPidPolicyAdjustment (%ws): Exiting function with status %x\n", - TargetHardwareId, - status)); - - return status; -} - - -NTSTATUS -DsmpSetNewDefaultLBPolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_opt_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called to adjust the path state of an instance of a - LUN for which a new default load balance policy was applied - following an admin request for such a change. - - This routine must be called with spinlock held. - -Arguements: - - DsmContext is the DSM context - DeviceInfo is the device info on which the new path state needs to be set - LoadBalanceType is the load balance policy in accordance with which the path state needs to be adjusted - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - NTSTATUS status = STATUS_SUCCESS; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetNewDefaultLBPolicy (DevInfo %p): Entering function\n", - DeviceInfo)); - - if (!DeviceInfo) { - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpSetNewDefaultLBPolicy; - } - - if (!(DsmpIsDeviceInitialized(DeviceInfo) && DsmpIsDeviceUsable(DeviceInfo) && DsmpIsDeviceUsablePR(DeviceInfo)) || - DsmpIsDeviceFailedState(DeviceInfo->State)) { - - status = STATUS_UNSUCCESSFUL; - goto __Exit_DsmpSetNewDefaultLBPolicy; - } - - - group = DeviceInfo->Group; - - if (!DsmpIsSymmetricAccess(DeviceInfo)) { - - DsmpAdjustDeviceStatesALUA(group, NULL, SpecialHandlingFlag); - - } else { - - switch (LoadBalanceType) { - - // - // For failover, it is important the right path is - // chosen, ie. preferred path needs to be taken into - // consideration. - // - case DSM_LB_FAILOVER: { - - DsmpSetLBForPathArrival(DsmContext, DeviceInfo, SpecialHandlingFlag); - - break; - } - - // - // For all other policies, the state must be A/O. - // - default: { - - DeviceInfo->PreviousState = DeviceInfo->State; - DeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - break; - } - } - } - -__Exit_DsmpSetNewDefaultLBPolicy: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetNewDefaultLBPolicy (DevInfo %p): Exiting function with status %x\n", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForPathArrival( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called when a new path arrives for a multipath - group that doesn't support ALUA. The routine will set the path - to the appropriate state and fix up the other paths state if - they need to change. - - This is used by devices NOT supporting ALUA. - - This routine must be called with spinlock held. - -Arguements: - - DsmContext is the DSM context - NewDeviceInfo is the device info for the newly arrived path - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO deviceInfo; - NTSTATUS status = STATUS_SUCCESS; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): Entering function.\n", - NewDeviceInfo)); - - group = NewDeviceInfo->Group; - - if (!(DsmpIsDeviceInitialized(NewDeviceInfo) && DsmpIsDeviceUsable(NewDeviceInfo) && DsmpIsDeviceUsablePR(NewDeviceInfo))) { - - // - // Bad device instance. Nothing can be done about it. - // - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_UNDETERMINED; - - NT_ASSERT(NewDeviceInfo->FailGroup == NULL); - - goto __Exit_DsmpSetLBForPathArrival; - } - - - if (group->NumberDevices == 1) { - - // - // if this is the only device for the group then we will always - // be active as every group must have at least one active path - // - if (NewDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { - - // - // All's good - // - goto __Exit_DsmpSetLBForPathArrival; - - } else { - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): State changed to %d at %d\n", - NewDeviceInfo, - NewDeviceInfo->State, - __LINE__)); - - goto __Exit_DsmpSetLBForPathArrival; - } - - switch(group->LoadBalanceType) { - case DSM_LB_FAILOVER: { - - // - // Get the current active path. - // - deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); - - // - // If the newly arriving path is the preferred path, this now should - // become our active path. - // - if (group->PreferredPath == ((ULONGLONG)((ULONG_PTR)(NewDeviceInfo->FailGroup->PathId)))) { - - // - // If current active path is not the preferred path, change its - // path state to standby. - // - if (deviceInfo && deviceInfo != NewDeviceInfo) { - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_STANDBY; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (Group %p): Preferred path back online. DevInfo %p changed to state %d\n", - group, - deviceInfo, - deviceInfo->State)); - } - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - } else { - - // - // In the case of failover, we must have only a single - // active path. If this newly added path is configured as - // the one that is desired to be active then we make this - // active and set the standby path that was active back to - // standby unless the preferred path is the currently active - // path. If the newly added path is supposed to be - // standby then we leave it as standby. - // - if (NewDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) { - - if (deviceInfo) { - - // - // If the preferred path is currently active, don't change - // it regardless of this path wanting to be in active state. - // - if (group->PreferredPath == ((ULONGLONG)((ULONG_PTR)(deviceInfo->FailGroup->PathId)))) { - - if (NewDeviceInfo != deviceInfo) { - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_STANDBY; - } - - } else { - - // - // Since the preferred path is not active, make this - // path active since it wants to be so. This means - // changing the current active path to standby. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_STANDBY; - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - } - } else { - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - } - - } else { - - if (deviceInfo) { - - if (deviceInfo != NewDeviceInfo) { - - // - // This newly arrived device doesn't want to be in - // A/O, and we already have an active path, so make - // it standby. - // - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_STANDBY; - } - } else { - - // - // Since we currently don't have an active path, this one - // needs to be made active, regardless of its path it wishes - // to be in. - // - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - } - } - } - - break; - } - - case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { - - // - // In RRWS, a set of paths can be active and another set of - // paths can be standby. We set the new path to the desired - // state unless the desired state is standby, but there are - // no active paths. Also if the desired state is Active we - // need to check if there are any existing paths that are - // also active but have a desired state of standby. For - // those we can move them back to standby. - // - if (NewDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) { - - // - // We are the active path coming back. Find out who has - // been the active one and place him back to standby - // - DsmpAllowStandbyPathsToRest(group); - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): Changed to state %d at %d\n", - NewDeviceInfo, - NewDeviceInfo->State, - __LINE__)); - - } else { - - // - // if there are no paths already active then we've got - // to make this one AO, otherwise we can be non-AO - // - deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); - - if (!deviceInfo || deviceInfo == NewDeviceInfo) { - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - } else { - - NewDeviceInfo->State = DSM_DEV_STANDBY; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (%p): Changed to state %d at %d. Status %x\n", - NewDeviceInfo, - NewDeviceInfo->State, - __LINE__, - status)); - } - - status = STATUS_SUCCESS; - - break; - } - - case DSM_LB_LEAST_BLOCKS: - case DSM_LB_ROUND_ROBIN: - case DSM_LB_DYN_LEAST_QUEUE_DEPTH: - case DSM_LB_WEIGHTED_PATHS: { - - // - // In RR, LWP, LB and LQD all paths are active so the new device - // becomes AO or AU. - // - if (NewDeviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED) { - - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): Changed to state %d at %d. Status %x\n", - NewDeviceInfo, - NewDeviceInfo->State, - __LINE__, - status)); - - status = STATUS_SUCCESS; - - break; - } - - default: { - status = STATUS_INVALID_PARAMETER; - break; - } - } - -__Exit_DsmpSetLBForPathArrival: - - // - // Update the next path to be used for the group - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess(NewDeviceInfo), - SpecialHandlingFlag); - if (deviceInfo != NULL) { - - InterlockedExchangePointer(&(group->PathToBeUsed), (PVOID)deviceInfo->FailGroup); - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): Updating PathToBeUsed in %p to %p\n", - NewDeviceInfo, - group, - group->PathToBeUsed)); - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): No FOG available for group %p\n", - NewDeviceInfo, - group)); - - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrival (DevInfo %p): Exiting function with status %x\n", - NewDeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForPathArrivalALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called when a new path arrives for a multipath - group. The routine will set the path to the appropriate state and - fix up the other paths state if they need to change. - - Spin lock must NOT be held by caller - -Arguements: - - DsmContext is the DSM context - NewDeviceInfo is the device info for the newly arrived path - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO deviceInfo = NULL; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 warnings; - BOOLEAN lockHeld = FALSE; - PDSM_DEVICE_INFO preferredActiveDeviceInfo = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): Entering function.\n", - NewDeviceInfo)); - - group = NewDeviceInfo->Group; - - if (!(DsmpIsDeviceInitialized(NewDeviceInfo) && DsmpIsDeviceUsable(NewDeviceInfo) && DsmpIsDeviceUsablePR(NewDeviceInfo))) { - - // - // Bad device instance. Nothing can be done about it. - // - NewDeviceInfo->PreviousState = NewDeviceInfo->State; - NewDeviceInfo->State = DSM_DEV_UNDETERMINED; - - NT_ASSERT(NewDeviceInfo->FailGroup == NULL); - - goto __Exit_DsmpSetLBForPathArrivalALUA; - } - - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - lockHeld = TRUE; - - if (group->NumberDevices == 1) { - - // - // If this is the only device for the group then it should be the - // active instance as every group must have at least one active path. - // - if (NewDeviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED) { - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - lockHeld = FALSE; - - if (NewDeviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { - - // - // If the device supports explicit transitions, set its state to A/O - // - status = DsmpSetDeviceALUAState(DsmContext, NewDeviceInfo, DSM_DEV_ACTIVE_OPTIMIZED); - - } else { - - // - // Since the device supports only implicit transitions, send down - // RTPG and hope that the controller has made this one the A/O path. - // - status = DsmpGetDeviceALUAState(DsmContext, NewDeviceInfo, NULL); - - if (NT_SUCCESS(status)) { - - // - // Remember that at this point it is possible that this path - // is still non-A/O. We'll need to handle this in DsmGetPath - // as a special case where we don't find an A/O path but the - // storage supports implicit-only transitions. At that time, - // we mustn't blindly return a NULL path back. - // - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): RTPG returned state = %x, ALUA state = %x.\n", - NewDeviceInfo, - NewDeviceInfo->State, - NewDeviceInfo->ALUAState)); - } - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): State changed to %d at %d\n", - NewDeviceInfo, - NewDeviceInfo->State, - __LINE__)); - - } else { - - deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); - - // - // Irrespecitve of the policy, we must have at least one A/O path. - // - // For RRWS and FOO, this path is of interest if it is desired to be in A/O. - // - // Also, for failover-only, this new path is of interest if it is - // the preferred path. - // - // This path is also of interest if it is not A/O and desired state has not - // explicitly been set to non-A/O and it has been exposed through the - // preferred TPG. - // - if ((!deviceInfo) || - ((NewDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) && - (group->LoadBalanceType == DSM_LB_FAILOVER || - group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET)) || - (group->PreferredPath == (ULONGLONG)((ULONG_PTR)(NewDeviceInfo->FailGroup->PathId)) && - group->LoadBalanceType == DSM_LB_FAILOVER) || - (NewDeviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED && - NewDeviceInfo->DesiredState == DSM_DEV_UNDETERMINED && - NewDeviceInfo->TargetPortGroup->Preferred)) { - - // - // Since this path is supposed to be active, we make it - // active and then allow any paths that are supposed to - // be standby go back to being standby - // - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - lockHeld = FALSE; - - // - // If explicit ALUA is supported, we need to send down STPG to make the change. - // - if (NewDeviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { - - status = DsmpSetDeviceALUAState(DsmContext, NewDeviceInfo, DSM_DEV_ACTIVE_OPTIMIZED); - - } else { - - // - // If implicit ALUA, the controller may have made some - // changes to the TPG states. We just need to query it. - // We'll try and honor the Admin's request but can't - // guarantee it. - // - status = DsmpGetDeviceALUAState(DsmContext, NewDeviceInfo, NULL); - } - - // - // We prefer this newly arrived devInfo to be A/O - // - preferredActiveDeviceInfo = NewDeviceInfo; - } - } - - if (!lockHeld) { - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - lockHeld = TRUE; - } - - if (NT_SUCCESS(status)) { - - DsmpAdjustDeviceStatesALUA(group, preferredActiveDeviceInfo, SpecialHandlingFlag); - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): Trying to query ALUA state failed with %x\n", - NewDeviceInfo, - status)); - } - - status = STATUS_SUCCESS; - -__Exit_DsmpSetLBForPathArrivalALUA: - - // - // Update the next path to be used for the group - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess(NewDeviceInfo), - SpecialHandlingFlag); - if (deviceInfo != NULL) { - - InterlockedExchangePointer(&(group->PathToBeUsed), (PVOID)deviceInfo->FailGroup); - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): Updating PathToBeUsed in %p to %p\n", - NewDeviceInfo, - group, - group->PathToBeUsed)); - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): No active/alternative path available for group %p\n", - NewDeviceInfo, - group)); - - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - } - - if (lockHeld) { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathArrivalALUA (DevInfo %p): Exiting function with status %x\n", - NewDeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForPathRemoval( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, - _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called when a path is removed from a multipath - group. The routine will set the path to the appropriate state and - fix up the other paths state if they need to change. - - Note: This is used by devices NOT supporting ALUA. - -Arguements: - - DsmContext is the DSM context - - RemovedDeviceInfo is the device info for failing/going-away path - - Group is an optional group override. That is, if Group is not NULL, this - function will run the load balance policy on the given Group and not - the Group from the RemovedDeviceInfo. This should only be used when - it's impossible to get a pointer to the RemovedDeviceInfo. - - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO deviceInfo; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p, Group %p): Entering function.\n", - RemovedDeviceInfo, - Group)); - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - if (Group == NULL) { - - if (!(DsmpIsDeviceFailedState(RemovedDeviceInfo->State))) { - - RemovedDeviceInfo->LastKnownGoodState = RemovedDeviceInfo->State; - } - - RemovedDeviceInfo->PreviousState = RemovedDeviceInfo->State; - RemovedDeviceInfo->State = DSM_DEV_FAILED; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): changed to state %d at %d\n", - RemovedDeviceInfo, - RemovedDeviceInfo->State, - __LINE__)); - - group = RemovedDeviceInfo->Group; - - } else { - // - // The caller has chosen to override the RemovedDeviceInfo->Group. - // - group = Group; - } - - switch(group->LoadBalanceType) { - case DSM_LB_FAILOVER: - case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { - - // - // In the case of failover, we must have only a single - // active path. If the removed path was the active path we - // need to find another path to become active - // - // In RRWS, a set of paths can be active and another set of - // paths can be standby. If the removed path is an active - // path then we need to make sure there is another active - // path. If there is already another active path then there - // is nothing to do. If not then a path needs to be made - // active. - // - if (!DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag)) { - - deviceInfo = DsmpFindStandbyPathToActivate(group, SpecialHandlingFlag); - if (deviceInfo) { - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): DevInfo %p changed to state %d at %d\n", - RemovedDeviceInfo, - deviceInfo, - deviceInfo->State, - __LINE__)); - } - } else { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): LB Policy FO/RRWS and other paths active, no path made active at %d\n", - RemovedDeviceInfo, - __LINE__)); - } - - break; - } - - case DSM_LB_LEAST_BLOCKS: - case DSM_LB_ROUND_ROBIN: - case DSM_LB_WEIGHTED_PATHS: - case DSM_LB_DYN_LEAST_QUEUE_DEPTH: { - - // - // In RR, LQD, LB and LWP, all paths are active so we don't - // need to worry about activating a new path - // - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): LB Policy RR, LWP or LQD, no path made active at %d\n", - RemovedDeviceInfo, - __LINE__)); - break; - } - - default: { - status = STATUS_INVALID_PARAMETER; - break; - } - } - - // - // Update the next path to be used for the group - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess(RemovedDeviceInfo), - SpecialHandlingFlag); - if (deviceInfo != NULL) { - - InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): Removal: Updating PathToBeUsed in %p to %p\n", - RemovedDeviceInfo, - group, - group->PathToBeUsed)); - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): After remove No FOG available for group %p\n", - RemovedDeviceInfo, - group)); - - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemoval (DevInfo %p): Exiting function with status %x\n", - RemovedDeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForPathRemovalALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, - _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called when a path is removed from a multipath - group. The routine will set the path to the appropriate state and - fix up the other paths state if they need to change. - - Note: This should NOT be called with DsmContext Lock held - This is used for devices supporting ALUA. - -Arguements: - - DsmContext is the DSM context - - RemovedDeviceInfo is the device info for the failing/going-away path - - Group is an optional group override. That is, if Group is not NULL, this - function will run the load balance policy on the given Group and not - the Group from the RemovedDeviceInfo. This should only be used when - it's impossible to get a pointer to the RemovedDeviceInfo. - - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO deviceInfo = NULL; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql; - BOOLEAN lockHeld = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p, Group %p): Entering function.\n", - RemovedDeviceInfo, - Group)); - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - lockHeld = TRUE; - - if (Group == NULL) { - - if (!(DsmpIsDeviceFailedState(RemovedDeviceInfo->State))) { - - RemovedDeviceInfo->LastKnownGoodState = RemovedDeviceInfo->State; - } - - RemovedDeviceInfo->PreviousState = RemovedDeviceInfo->State; - RemovedDeviceInfo->State = DSM_DEV_FAILED; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): changed to state %d at %d\n", - RemovedDeviceInfo, - RemovedDeviceInfo->State, - __LINE__)); - - group = RemovedDeviceInfo->Group; - - } else { - // - // The caller has chosen to override the RemovedDeviceInfo->Group. - // - group = Group; - } - - if (group->LoadBalanceType < DSM_LB_FAILOVER || - group->LoadBalanceType > DSM_LB_LEAST_BLOCKS) { - - status = STATUS_INVALID_PARAMETER; - - } else { - - // - // In the case of failover, we must have only a single - // active path. If the removed path was the active path we - // need to find another path to become active - // - // In rest of policies, set of paths can be active and another set of - // paths can be standby. If the removed path is an active - // path then we need to make sure there is another active - // path. If there is already another active path then there - // is nothing to do. If not then a path needs to be made - // active. - // - if (!DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag)) { - - BOOLEAN sendTPG = TRUE; - - deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); - - if (deviceInfo) { - - if (sendTPG) { - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - lockHeld = FALSE; - - // - // If explicit transition supported, we need to send down STPG to make the change. - // - if (deviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { - - status = DsmpSetDeviceALUAState(DsmContext, deviceInfo, DSM_DEV_ACTIVE_OPTIMIZED); - - } else { - - // - // If implicit ALUA, the controller may have made necessary - // changes to the TPG states. We just need to query it. - // - status = DsmpGetDeviceALUAState(DsmContext, deviceInfo, NULL); - } - - if (!lockHeld) { - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - lockHeld = TRUE; - } - - if (NT_SUCCESS(status)) { - - DsmpAdjustDeviceStatesALUA(group, deviceInfo, SpecialHandlingFlag); - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): Trying to query for ALUA state failed with status %x\n", - RemovedDeviceInfo, - status)); - } - } else { - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - } - - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): Device %p changed to state %d at %d\n", - RemovedDeviceInfo, - deviceInfo, - deviceInfo->State, - __LINE__)); - } - } - } else { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): Other paths active, no path made active at %d\n", - RemovedDeviceInfo, - __LINE__)); - } - - status = STATUS_SUCCESS; - } - - // - // Update the next path to be used for the group - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess(RemovedDeviceInfo), - SpecialHandlingFlag); - if (deviceInfo != NULL) { - - InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): Removal: Updating PathToBeUsed in %p to %p\n", - RemovedDeviceInfo, - group, - group->PathToBeUsed)); - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): No active/alternative path available for group %p\n", - RemovedDeviceInfo, - group)); - - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - } - - if (lockHeld) { - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): Exiting function with status %x.\n", - RemovedDeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForPathFailing( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, - _In_ IN BOOLEAN MarkDevInfoFailed, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called when an IO that was sent using this path fails with - a fatal error. The routine will set the path to the appropriate state and - fix up the other paths state if they need to change. - - Note: This is used by devices NOT supporting ALUA. - -Arguements: - - DsmContext is the DSM context - - FailingDeviceInfo is the device info for the path on which IO failed - - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - NTSTATUS status; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailing (DevInfo %p): Entering function.\n", - FailingDeviceInfo)); - - // - // We need to do exactly what DsmpSetLBForPathRemoval() does, except - // that the devInfo may not really go away (may come back before a - // Pnp remove comes down for the real LUN) - // - if (MarkDevInfoFailed) { - status = DsmpSetLBForPathRemoval(DsmContext, FailingDeviceInfo, NULL, SpecialHandlingFlag); - } else { - status = DsmpSetLBForPathRemoval(DsmContext, FailingDeviceInfo, FailingDeviceInfo->Group, SpecialHandlingFlag); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailing (DevInfo %p): Exiting function with status %x\n", - FailingDeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLBForPathFailingALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, - _In_ IN BOOLEAN MarkDevInfoFailed, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - This routine is called when an IO that was sent using this path fails with - a fatal error. The routine will set the path to the appropriate state and - send down a Set Target Port Groups command asynchronously to fix up the - other paths state if they need to change (actual work done in the completion - routine). - - Note: This should NOT be called with DsmContext Lock held - This is used for devices supporting ALUA. - -Arguements: - - DsmContext is the DSM context - - FailingDeviceInfo is the device info for the failing/going-away path - - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; - PDSM_DEVICE_INFO deviceInfo = NULL; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql; - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength; - PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR tpgDescriptor = NULL; - PDSM_COMPLETION_CONTEXT completionContext = NULL; - PVOID senseInfo = NULL; - PSCSI_REQUEST_BLOCK srb = NULL; - PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Entering function.\n", - FailingDeviceInfo)); - - if (MarkDevInfoFailed) { - if (!(DsmpIsDeviceFailedState(FailingDeviceInfo->State))) { - - FailingDeviceInfo->LastKnownGoodState = FailingDeviceInfo->State; - } - - FailingDeviceInfo->PreviousState = FailingDeviceInfo->State; - FailingDeviceInfo->State = DSM_DEV_FAILED; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): changed to state %d at %d\n", - FailingDeviceInfo, - FailingDeviceInfo->State, - __LINE__)); - } - - group = FailingDeviceInfo->Group; - - if (group->LoadBalanceType < DSM_LB_FAILOVER || - group->LoadBalanceType > DSM_LB_LEAST_BLOCKS) { - - status = STATUS_INVALID_PARAMETER; - - } else { - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Check if there are any active paths that can be used. - // - deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); - if (!deviceInfo) { - - // - // Check if an Set/Report TPG has already been sent for this failing devInfo - // - failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(DsmContext, group, FailingDeviceInfo); - - if (!failDevInfoListEntry) { - - BOOLEAN sendTPG = TRUE; - - deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); - - if (deviceInfo) { - - if (sendTPG) { - - tpgCompletionContext = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_TPG_COMPLETION_CONTEXT), - DSM_TAG_TPG_COMPLETION_CONTEXT); - - if (tpgCompletionContext) { - UCHAR senseInfoLength = SENSE_BUFFER_SIZE_EX; - - senseInfo = DsmpAllocatePool(NonPagedPoolNx, - senseInfoLength, - DSM_TAG_SCSI_SENSE_INFO); - - if (senseInfo) { - - srb = DsmpAllocatePool(NonPagedPoolNx, - sizeof(SCSI_REQUEST_BLOCK), - DSM_TAG_SCSI_REQUEST_BLOCK); - - if (srb) { - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - - completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); - if (completionContext) { - - // - // Update the target port group that needs to be made - // active/optimized. We will send down an STPG for - // storages that support both implicit and explicit. - // If the storage does NOT like our choice of A/O TPG, - // it will make an implicit transition. This is still - // a better option than solely relying on the storage's - // implicit transitions at this stage and ending up with - // no path in A/O state. - // - if (deviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { - - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); - - } else { - - // - // Find an active/optimized target port group that should - // have been set by the controller - // - // Take care of worst case scenario, which is: - // 1. 4-byte header (for allocation length) - // 2. 32 8-byte descriptors (for TPGs) - // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) - // - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - DSM_MAX_PATHS * sizeof(ULONG))); - } - - targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, - targetPortGroupsInfoLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo) { - - failDevInfoListEntry = DsmpBuildFailPathDevInfoEntry(DsmContext, - group, - FailingDeviceInfo, - deviceInfo); - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - if (failDevInfoListEntry) { - - tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)(targetPortGroupsInfo + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE); - tpgDescriptor->AsymmetricAccessState = DSM_DEV_ACTIVE_OPTIMIZED; - REVERSE_BYTES_SHORT(&tpgDescriptor->TPG_Identifier, &deviceInfo->TargetPortGroup->Identifier); - - // - // Prevent the device info from being removed when a TPG is in-flight. - // - InterlockedIncrement(&FailingDeviceInfo->BlockRemove); - - completionContext->DeviceInfo = FailingDeviceInfo; - completionContext->DsmContext = DsmContext; - completionContext->RequestUnique1 = deviceInfo; - completionContext->RequestUnique2 = FALSE; - - tpgCompletionContext->CompletionContext = completionContext; - tpgCompletionContext->Srb = srb; - tpgCompletionContext->SenseInfoBuffer = senseInfo; - tpgCompletionContext->SenseInfoBufferLength = senseInfoLength; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Sending down TPG asynchronously for %p using devInfo %p (path %p).\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId, - deviceInfo, - deviceInfo->FailGroup->PathId)); - - if (deviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { - - status = DsmpSetTargetPortGroupsAsync(deviceInfo, - DsmpPhase1ProcessPathFailingALUA, - tpgCompletionContext, - targetPortGroupsInfoLength, - targetPortGroupsInfo); - } else { - - status = DsmpReportTargetPortGroupsAsync(deviceInfo, - DsmpPhase2ProcessPathFailingALUA, - tpgCompletionContext, - targetPortGroupsInfoLength, - targetPortGroupsInfo); - } - - if (status != STATUS_PENDING) { - - // - // Request not sent down successfully. Free the allocations. - // - DsmpFreePool(targetPortGroupsInfo); - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - DsmpFreePool(srb); - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - - // - // Allow the failing device to be removed. - // - InterlockedDecrement(&FailingDeviceInfo->BlockRemove); - } - } else { - - // - // Fail to build DevInfo entry. Free the allocations. - // - DsmpFreePool(targetPortGroupsInfo); - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - DsmpFreePool(srb); - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - DsmpFreePool(srb); - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - NT_ASSERT(completionContext != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate completion context. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - DsmpFreePool(srb); - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - NT_ASSERT(srb != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate SRB. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - NT_ASSERT(senseInfo != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate senseInfo. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - DsmpFreePool(tpgCompletionContext); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - NT_ASSERT(tpgCompletionContext != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate TPG completion context. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Found alternative devInfo %p for failing path %p without need for TPG\n", - FailingDeviceInfo, - deviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Couldn't find a standby path to activate for failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - deviceInfo = failDevInfoListEntry->TempDeviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): There is an RTPG/STPG already in progress for this path %p. Returning alternative %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId, - deviceInfo)); - } - } else { - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Other paths active, no path made active at %d\n", - FailingDeviceInfo, - __LINE__)); - } - - status = STATUS_SUCCESS; - } - - if (deviceInfo) { - - // - // Update temporarily the next path to be used for the group as this devInfo - // - InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Updating PathToBeUsed in %p to %p\n", - FailingDeviceInfo, - group, - group->PathToBeUsed)); - - } else { - - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpSetLBForPathRemovalALUA (DevInfo %p): No FOG available for group %p\n", - FailingDeviceInfo, - group)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetLBForPathFailingALUA (DevInfo %p): Exiting function with status %x.\n", - FailingDeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpSetPathForIoRetryALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, - _In_ IN BOOLEAN TPGException, - _In_ IN BOOLEAN DeviceInfoException - ) -/*++ - -Routine Description: - - This routine is called when an IO that was sent using this path fails with - a retry-able "ALUA" error. What this basically means is that most likely an - implicit transition has taken place and we need an RTPG to get the updated - path states. The routine will send down a Report Target Port Groups command - asynchronously to get the paths states (actual work done in the completion - routine). - - Note: This should NOT be called with DsmContext Lock held - This is used for devices supporting ALUA. - -Arguements: - - DsmContext is the DSM context - - FailingDeviceInfo is the device info for the failing/going-away path - - TPGException is a flag used to indicate if the selected path must be from a - TPG that is different from FailingDeviceInfo's. This is - special handling for UA with sense "TPG in SB/UA state" - - DeviceInfoException is a flag used to indicate that the current FailindDeviceInfo - itself needs to be used again. This is special handling for - UA with sense "Asymmetric Access State Changed" - - (NOTE: TPGException and DeviceInfoException are mutually exclusive, although - it is okay for both to be FALSE) - -Return Value: - - Status - ---*/ -{ - PDSM_GROUP_ENTRY group; - PDSM_DEVICE_INFO deviceInfo = NULL; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql; - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength; - PDSM_COMPLETION_CONTEXT completionContext = NULL; - PVOID senseInfo = NULL; - PSCSI_REQUEST_BLOCK srb = NULL; - PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = NULL; - NTSTATUS throttleStatus = STATUS_UNSUCCESSFUL; - ULONG inflightRTPG; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Entering function.\n", - FailingDeviceInfo)); - - group = FailingDeviceInfo->Group; - - - if (group->LoadBalanceType < DSM_LB_FAILOVER || - group->LoadBalanceType > DSM_LB_LEAST_BLOCKS) { - - status = STATUS_INVALID_PARAMETER; - - } else { - - // - // First check to see if we need to find a candidate from a different TPG. - // - if (TPGException) { - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Find a candidate in a TPG that is different from this one - // - deviceInfo = DsmpFindStandbyPathInAlternateTpgALUA(group, FailingDeviceInfo, SpecialHandlingFlag); - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Need to try a different TPG deviceInfo %p.\n", - FailingDeviceInfo, - deviceInfo)); - - } else if (DeviceInfoException) { - - // - // Retry on the same path - // - deviceInfo = FailingDeviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Will retry using same deviceInfo %p.\n", - FailingDeviceInfo, - deviceInfo)); - } - - // - // Check if an Report TPG has already been sent for this group - // - inflightRTPG = InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 0, 0); - - // - // If there is no RTPG currently in flight, use the best candidate found - // above to send down the RTPG. If there is already an RTPG inflight, - // we're done. The result of the RTPG should fix the path states. - // - if (!inflightRTPG) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): No RTPG in flight. Try sending one down.\n", - FailingDeviceInfo)); - - // - // If we need a candidate device, first get the currently active one. - // If we can't find one that way, resort to finding the best alternative. - // Basic idea is find SOME path instead of failing IOs back to the application. - // - if (!deviceInfo) { - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Find the best candidate - ie. either a currently A/O path or - // the best alternative path to be made A/O. - // - deviceInfo = DsmpGetAnyActivePath(group, TRUE, deviceInfo, SpecialHandlingFlag); - if (!deviceInfo) { - - BOOLEAN sendTPG = TRUE; - - deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): No active path. Best alternative %p.\n", - FailingDeviceInfo, - deviceInfo)); - } - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - - if (deviceInfo) { - - tpgCompletionContext = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_TPG_COMPLETION_CONTEXT), - DSM_TAG_TPG_COMPLETION_CONTEXT); - - if (tpgCompletionContext) { - UCHAR senseInfoLength = SENSE_BUFFER_SIZE_EX; - - senseInfo = DsmpAllocatePool(NonPagedPoolNx, - senseInfoLength, - DSM_TAG_SCSI_SENSE_INFO); - - if (senseInfo) { - - srb = DsmpAllocatePool(NonPagedPoolNx, - sizeof(SCSI_REQUEST_BLOCK), - DSM_TAG_SCSI_REQUEST_BLOCK); - - if (srb) { - - srb->Length = SCSI_REQUEST_BLOCK_SIZE; - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - - completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); - - if (completionContext) { - - // - // Find an active/optimized target port group that should - // have been set by the controller - // - // Take care of worst case scenario, which is: - // 1. 4-byte header (for allocation length) - // 2. 32 8-byte descriptors (for TPGs) - // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) - // - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - DSM_MAX_PATHS * sizeof(ULONG))); - - targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, - targetPortGroupsInfoLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo) { - - completionContext->DeviceInfo = FailingDeviceInfo; - completionContext->DsmContext = DsmContext; - completionContext->RequestUnique1 = deviceInfo; - completionContext->RequestUnique2 = TRUE; - - tpgCompletionContext->CompletionContext = completionContext; - tpgCompletionContext->Srb = srb; - tpgCompletionContext->SenseInfoBuffer = senseInfo; - tpgCompletionContext->SenseInfoBufferLength = senseInfoLength; - - // - // Now we are all set to send the RTPG request. - // check and set InFlightRTPG to make sure this thread is the only one with - // the RTPG active for this group, since it is possible to have more than one - // threads reaching up to this point in parallel - // - inflightRTPG = InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 1, 0); - if (inflightRTPG) { - - DsmpFreePool(targetPortGroupsInfo); - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - DsmpFreePool(srb); - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - } else { - - // - // Prevent the device info from being removed when a TPG is in-flight. - // - InterlockedIncrement(&FailingDeviceInfo->BlockRemove); - - // - // First try and throttle the IO. The completion routine will - // take care of resuming the IO. - // - if (!InterlockedCompareExchange((LONG volatile*)&group->Throttled, 1, 0)) { - - DsmNotification(((PDSM_CONTEXT)DsmContext)->MPIOContext, - ThrottleIO_V2, - deviceInfo, - FALSE, - &throttleStatus, - 0); - - if (NT_SUCCESS(throttleStatus)) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Successfully throttled IO. About to send RTPG. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - } else { - - // - // Throttle can fail when the MPDisk is - // 1. Being removed. (or) - // 2. In any other state other than Normal or Degraded. - // - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Throttle before RTPG failed. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - InterlockedDecrement((LONG volatile*)&FailingDeviceInfo->Group->Throttled); - } - } else { - - // - // Currently we don't expect this to happen - // - NT_ASSERT(FALSE); - } - - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Sending RTPG asynchronously. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - if (STATUS_PENDING != DsmpReportTargetPortGroupsAsync(deviceInfo, - DsmpPhase2ProcessPathFailingALUA, - tpgCompletionContext, - targetPortGroupsInfoLength, - targetPortGroupsInfo)) { - - - - // - // Request not sent down successfully. Free the allocations. - // - DsmpFreePool(targetPortGroupsInfo); - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - DsmpFreePool(srb); - DsmpFreePool(senseInfo); - DsmpFreePool(tpgCompletionContext); - - // - // Allow the failing device to be removed. - // - InterlockedDecrement(&FailingDeviceInfo->BlockRemove); - - // - // Resume IO if we throttled requests before calling DsmpReportTargetPortGroupsAsync - // - if (InterlockedCompareExchange((LONG volatile*)&group->Throttled, 0, 1)) { - - NTSTATUS resumeStatus = STATUS_UNSUCCESSFUL; - - DsmNotification(((PDSM_CONTEXT)deviceInfo->DsmContext)->MPIOContext, - ResumeIO_V2, - deviceInfo, - TRUE, - &resumeStatus, - 0); - - if (!NT_SUCCESS(resumeStatus)) { - - // - // Resume can fail when - // 1. The MPDisk is being removed (or) - // 2. The MPDisk is any other state other than throttled (or) - // 3. There is a problem dispatching throttled requests. - // - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Resume IO failed.\n", - deviceInfo)); - } - - } - - InterlockedDecrement((LONG volatile*)&group->InFlightRTPG); - } - } - } else { - - NT_ASSERT(targetPortGroupsInfo != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate TPG info buffer. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - ExFreePool(srb); - ExFreePool(senseInfo); - ExFreePool(tpgCompletionContext); - } - } else { - - NT_ASSERT(completionContext != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate completion context. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - ExFreePool(srb); - ExFreePool(senseInfo); - ExFreePool(tpgCompletionContext); - } - } else { - - NT_ASSERT(srb != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate SRB. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - ExFreePool(senseInfo); - ExFreePool(tpgCompletionContext); - } - } else { - - NT_ASSERT(senseInfo != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate senseInfo. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - - ExFreePool(tpgCompletionContext); - } - } else { - - NT_ASSERT(tpgCompletionContext != NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate TPG completion context. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - } - } else { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't find a path for RTPG. Failing path %p.\n", - FailingDeviceInfo, - FailingDeviceInfo->FailGroup->PathId)); - } - } else { - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Other paths active, no path made active at %d\n", - FailingDeviceInfo, - __LINE__)); - } - - if(!deviceInfo) { - - // - // It is possible that there are only two TPGs with one of them in U/A - // state and the other in transitioning state. In such a case, we would - // not find an alternative TPG deviceInfo. In addition, if there is an - // RTPG in flight, we won't go down the path of forcibly picking any - // deviceInfo. This is to cover that scenario, else we're left with no - // deviceInfo to do the retry and we'll end up setting the group's PTBU - // to NULL thus failing the retried request (if for eg. the LB is RRWS). - // Need to ensure that we handle this exception case. - // - if (inflightRTPG) { - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Find the best candidate - ie. either a currently A/O path or - // the best alternative path to be made A/O. - // - deviceInfo = DsmpGetAnyActivePath(group, TRUE, deviceInfo, SpecialHandlingFlag); - if (!deviceInfo) { - - BOOLEAN sendTPG = TRUE; - - deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - } - - if(deviceInfo) { - - // - // Update temporarily the next path to be used for the group as this devInfo - // - InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Updating PathToBeUsed in %p to %p\n", - FailingDeviceInfo, - group, - group->PathToBeUsed)); - - } else { - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): No FOG available for group %p\n", - FailingDeviceInfo, - group)); - } - - status = STATUS_SUCCESS; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetPathForIoRetryALUA (DevInfo %p): Exiting function with status %x.\n", - FailingDeviceInfo, - status)); - - return status; -} - - -PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY -DsmpFindFailPathDevInfoEntry( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO FailingDevInfo - ) -/*++ - -Routine Description: - - This routine finds the entry that contains the alternate devInfo to use for - a failing one for the passed in devInfo. - - N.B: This routine MUST be called with DsmContextLock held in either Shared or - Exclusive mode. - -Arguments: - - Context is the DSM's context info. - - Group is the group entry representing the device. - - FailingDevInfo is the device info whose entry needs to be found. - -Return Value: - - Pointer to the entry. NULL if it doesn't exist. - ---*/ -{ - PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; - PLIST_ENTRY entry = NULL; - - UNREFERENCED_PARAMETER(Context); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpFindFailPathDevInfoEntry (DevInfo %p): Entering function.\n", - FailingDevInfo)); - - for (entry = Group->FailingDevInfoList.Flink; - entry != &Group->FailingDevInfoList; - entry = entry->Flink) { - - failDevInfoListEntry = CONTAINING_RECORD(entry, DSM_FAIL_PATH_PROCESSING_LIST_ENTRY, ListEntry); - NT_ASSERT(failDevInfoListEntry); - - if (failDevInfoListEntry) { - - if (failDevInfoListEntry->FailingDeviceInfo == FailingDevInfo) { - - break; - - } else { - - failDevInfoListEntry = NULL; - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpFindFailPathDevInfoEntry (DevInfo %p): Exiting function returning entry %p.\n", - FailingDevInfo, - failDevInfoListEntry)); - - return failDevInfoListEntry; -} - - -PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY -DsmpBuildFailPathDevInfoEntry( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO FailingDevInfo, - _In_ IN PDSM_DEVICE_INFO AlternateDevInfo - ) -/*++ - -Routine Description: - - When InterpretError() is called with an IRP that has failed with a fatal error, - if the device is ALUA it is possible that STPG needs to be sent to update a new - devInfo as being Active/Optimized. However, for in-flight IOs that weren't - queued by MPIO, we still need to return a path that can be used. - - This routine is builds an entry that contains the alternate devInfo to use for - a failing one. - - NOTE: Calling function should be holding the spin lock. - -Arguments: - - Context is the DSM's context info. - - Group is the group entry representing the device. - - FailingDevInfo is the device info that was used when the IRP failed. - - AlternateDevInfo is the new one to temporarily use until its state can be properly set. - -Return Value: - - Pointer to the newly built entry. - NULL if there were any errors building it. - ---*/ -{ - PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; - - UNREFERENCED_PARAMETER(Context); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpBuildFailPathDevInfoEntry (DevInfo %p): Entering function.\n", - FailingDevInfo)); - - failDevInfoListEntry = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_FAIL_PATH_PROCESSING_LIST_ENTRY), - DSM_TAG_FAIL_DEVINFO_LIST_ENTRY); - - if (failDevInfoListEntry) { - - failDevInfoListEntry->FailingDeviceInfo = FailingDevInfo; - failDevInfoListEntry->TempDeviceInfo = AlternateDevInfo; - InsertTailList(&Group->FailingDevInfoList, &failDevInfoListEntry->ListEntry); - InterlockedIncrement((LONG volatile*)&Group->NumberFailingDevInfos); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpBuildFailPathDevInfoEntry (DevInfo %p): Failed to allocate memory for entry.\n", - FailingDevInfo)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpBuildFailPathDevInfoEntry (DevInfo %p): Exiting function returning entry %p.\n", - FailingDevInfo, - failDevInfoListEntry)); - - return failDevInfoListEntry; -} - - -NTSTATUS -DsmpPhase1ProcessPathFailingALUA( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -/*++ - -Routine Description: - - This is the completion routine that is called when the STPG is sent down by - DsmpSetLBForPathFailingALUA. - - The caller SHOULD NOT acquire the DSM Context lock before calling this routine. - -Arguements: - - DeviceObject is the target device object to which Irp was sent - - Irp is the scsi pass through request for STPG - - Context is the completion context. - -Return Value: - - Status - ---*/ -{ - PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); - PDSM_TPG_COMPLETION_CONTEXT context = (PDSM_TPG_COMPLETION_CONTEXT)Context; - PSCSI_REQUEST_BLOCK srb = context->Srb; - PVOID senseData = context->SenseInfoBuffer; - UCHAR senseDataLength = context->SenseInfoBufferLength; - NTSTATUS status = Irp->IoStatus.Status; - ULONG targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); - PUCHAR targetPortGroupsInfo; - PDSM_DEVICE_INFO deviceInfo = (PDSM_DEVICE_INFO)(context->CompletionContext->RequestUnique1); - PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; - BOOLEAN releaseCompletionContextResources = TRUE; - KIRQL irql; - UCHAR scsiStatus = SrbGetScsiStatus(srb); - - UNREFERENCED_PARAMETER(DeviceObject); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): Entering function.\n", - deviceInfo)); - -#if DBG - KeQuerySystemTime(&context->CompletionContext->TickCount); -#endif - - if ((scsiStatus == SCSISTAT_GOOD) && - (NT_SUCCESS(status))) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): STPG succeeded.\n", - deviceInfo)); - - } else if (NT_SUCCESS(status) && - scsiStatus == SCSISTAT_CHECK_CONDITION && - DsmpShouldRetryTPGRequest(senseData, senseDataLength)) { - - if ((context->NumberRetries)--) { - - // - // Retry the request - // - - NT_ASSERT(SrbGetDataBuffer(srb) == MmGetMdlVirtualAddress(Irp->MdlAddress)); - - // - // Reset byte count of transfer in SRB Extension. - // - SrbSetDataTransferLength(srb, Irp->MdlAddress->ByteCount); - - // - // Zero SRB statuses. - // - srb->SrbStatus = 0; - SrbSetScsiStatus(srb, 0); - - nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - nextIrpStack->MinorFunction = IRP_MN_SCSI_CLASS; - - // - // Save SRB address in next stack for port driver. - // - nextIrpStack->Parameters.Scsi.Srb = srb; - IoSetCompletionRoutine(Irp, DsmpPhase1ProcessPathFailingALUA, Context, TRUE, TRUE, TRUE); - - IoMarkIrpPending(Irp); - - // - // Send the IRP asynchronously - // - DsmSendRequestEx(context->CompletionContext->DsmContext->MPIOContext, - deviceInfo->TargetObject, - Irp, - deviceInfo, - DSM_CALL_COMPLETION_ON_MPIO_ERROR); - - // - // We know that the completion routine will always be called. - // - status = STATUS_PENDING; - goto __Exit_DsmpPhase1ProcessPathFailingALUA; - } - } else { - - irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); - - failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - context->CompletionContext->DeviceInfo); - - if (failDevInfoListEntry) { - - DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - failDevInfoListEntry); - } - - ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): NTStatus 0%x, ScsiStatus 0x%x.\n", - deviceInfo, - status, - scsiStatus)); - } - - if (NT_SUCCESS(status)) { - - // - // An explicit transition may cause changes to some other TPGs. - // So we need to query for the states of all the TPGs and update - // our internal list and its elements. - // - - // - // Take care of worst case scenario, which is: - // 1. 4-byte header (for allocation length) - // 2. 32 8-byte descriptors (for TPGs) - // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) - // - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - DSM_MAX_PATHS * sizeof(ULONG))); - - targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, - targetPortGroupsInfoLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo) { - - if (STATUS_PENDING == DsmpReportTargetPortGroupsAsync(deviceInfo, - DsmpPhase2ProcessPathFailingALUA, - Context, - targetPortGroupsInfoLength, - targetPortGroupsInfo)) { - - releaseCompletionContextResources = FALSE; - - } else { - - DsmpFreePool(targetPortGroupsInfo); - } - } else { - - irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); - - failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - context->CompletionContext->DeviceInfo); - - if (failDevInfoListEntry) { - - DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - failDevInfoListEntry); - } - - ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); - } - } - - // - // Free the allocations. - // - IoFreeMdl(Irp->MdlAddress); - Irp->MdlAddress = NULL; - - DsmpFreePool(Irp->UserBuffer); - - IoFreeIrp(Irp); - Irp = (PIRP) NULL; - - if (releaseCompletionContextResources) { - - // - // Release our hold on the device info so that it can be removed. - // - InterlockedDecrement(&context->CompletionContext->DeviceInfo->BlockRemove); - - ExFreeToNPagedLookasideList(&(context->CompletionContext->DsmContext)->CompletionContextList, context->CompletionContext); - DsmpFreePool(context->Srb); - DsmpFreePool(context->SenseInfoBuffer); -#pragma warning(suppress:6001) // DevDiv 818965 - DsmpFreePool(context); - } - -__Exit_DsmpPhase1ProcessPathFailingALUA: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): Exiting function.\n", - deviceInfo)); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - - -NTSTATUS -DsmpRemoveFailPathDevInfoEntry( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY FailPathDevInfoEntry - ) -/*++ - -Routine Description: - - This routine removes the entry pointed to from the passed in Group's list. - - NOTE: Calling function should be holding the spin lock. - -Arguments: - - Context is the DSM's context info. - - Group is the group entry representing the device. - - FailingPathDevInfoEntry is the entry that needs to be removed. - -Return Value: - - STATUS_SUCCESS if successful, else appropriate NT error code. - ---*/ -{ - PLIST_ENTRY entry = &FailPathDevInfoEntry->ListEntry; - PDSM_DEVICE_INFO deviceInfo = FailPathDevInfoEntry->FailingDeviceInfo; - NTSTATUS status = STATUS_SUCCESS; - - UNREFERENCED_PARAMETER(Context); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpRemoveFailPathDevInfoEntry (DevInfo %p): Entering function.\n", - deviceInfo)); - - RemoveEntryList(entry); - DsmpFreePool(FailPathDevInfoEntry); - InterlockedDecrement((LONG volatile*)&Group->NumberFailingDevInfos); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpRemoveFailPathDevInfoEntry (DevInfo %p): Exiting function with status %x.\n", - deviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpPhase2ProcessPathFailingALUA( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -/*++ - -Routine Description: - - This is the completion routine that is called when the RTPG is sent down by - DsmpPhase1ProcessPathFailingALUA. - - The caller SHOULD NOT acquire the DSM Context lock before calling this routine. - -Arguements: - - DeviceObject is the target device object to which Irp was sent - - Irp is the scsi pass through request for RTPG - - Context is the completion context. - -Return Value: - - Status - ---*/ -{ - PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); - PDSM_TPG_COMPLETION_CONTEXT context = (PDSM_TPG_COMPLETION_CONTEXT)Context; - PSCSI_REQUEST_BLOCK srb = context->Srb; - PVOID senseData = context->SenseInfoBuffer; - UCHAR senseDataLength = context->SenseInfoBufferLength; - NTSTATUS status = Irp->IoStatus.Status; - PUCHAR header; - ULONG returnedDataLength = 0; - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength = 0; - PDSM_DEVICE_INFO deviceInfo = (PDSM_DEVICE_INFO)(context->CompletionContext->RequestUnique1); - BOOLEAN decrementRTPGcount = (BOOLEAN)(context->CompletionContext->RequestUnique2); - KIRQL irql; - ULONG index; - PDSM_DEVICE_INFO devInfo; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = NULL; - PDSM_GROUP_ENTRY group = deviceInfo->Group; - PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; - UCHAR scsiStatus = SrbGetScsiStatus(srb); - - UNREFERENCED_PARAMETER(DeviceObject); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Entering function.\n", - deviceInfo)); - -#if DBG - KeQuerySystemTime(&(context->CompletionContext)->TickCount); -#endif - - if ((status == STATUS_BUFFER_OVERFLOW) || - (NT_SUCCESS(status) && - (scsiStatus == SCSISTAT_GOOD))) { - - header = (PUCHAR)((PUCHAR)SrbGetDataBuffer(srb)); - GetUlongFrom4ByteArray(header, returnedDataLength); - - status = STATUS_SUCCESS; - if (returnedDataLength > SrbGetDataTransferLength(srb)) { - - status = STATUS_BUFFER_OVERFLOW; - } - } - - if ((scsiStatus == SCSISTAT_GOOD) && - (NT_SUCCESS(status))) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): RTPG using path %p succeeded.\n", - deviceInfo, - deviceInfo->FailGroup->PathId)); - - header = (PUCHAR)((PUCHAR)SrbGetDataBuffer(srb)); - GetUlongFrom4ByteArray(header, returnedDataLength); - - // - // Allocate a buffer to hold the TPG info. - // - targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, - SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + returnedDataLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo) { - - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + returnedDataLength; - - // - // Copy it over. - // - RtlCopyMemory(targetPortGroupsInfo, - header, - targetPortGroupsInfoLength); - - } else { - - irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); - - failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - context->CompletionContext->DeviceInfo); - - if (failDevInfoListEntry) { - - DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - failDevInfoListEntry); - } - - ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Failed to allocate mem for TPG.\n", - deviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - - } else if (NT_SUCCESS(status) && - scsiStatus == SCSISTAT_CHECK_CONDITION && - DsmpShouldRetryTPGRequest(senseData, senseDataLength)) { - - if ((context->NumberRetries)--) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Retrying check condition using path %p. Retries remaining %u.\n", - deviceInfo, - deviceInfo->FailGroup->PathId, - context->NumberRetries)); - - // - // Retry the request - // - - NT_ASSERT(SrbGetDataBuffer(srb) == MmGetMdlVirtualAddress(Irp->MdlAddress)); - - // - // Reset byte count of transfer in SRB Extension to true length. - // - SrbSetDataTransferLength(srb, targetPortGroupsInfoLength); - - // - // Zero SRB statuses. - // - srb->SrbStatus = 0; - SrbSetScsiStatus(srb, 0); - - nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - nextIrpStack->MinorFunction = IRP_MN_SCSI_CLASS; - - // - // Save SRB address in next stack for port driver. - // - nextIrpStack->Parameters.Scsi.Srb = srb; - IoSetCompletionRoutine(Irp, DsmpPhase2ProcessPathFailingALUA, Context, TRUE, TRUE, TRUE); - - IoMarkIrpPending(Irp); - - // - // Send the IRP asynchronously - // - DsmSendRequestEx(context->CompletionContext->DsmContext->MPIOContext, - deviceInfo->TargetObject, - Irp, - deviceInfo, - DSM_CALL_COMPLETION_ON_MPIO_ERROR); - - // - // We know that the completion routine will always be called. - // - status = STATUS_PENDING; - goto __Exit_DsmpPhase2ProcessPathFailingALUA; - } - } else { - - irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); - - failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - context->CompletionContext->DeviceInfo); - - if (failDevInfoListEntry) { - - DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - failDevInfoListEntry); - } - - ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): NTStatus 0%x, ScsiStatus 0x%x.\n", - deviceInfo, - status, - SrbGetScsiStatus(srb))); - - // Failed to get TPG Info. - // Here it is possible status is success, but scsiStatus is not. - // If so, set status to unsuccessful. - - if (NT_SUCCESS(status)) { - status = STATUS_UNSUCCESSFUL; - } - } - - if (NT_SUCCESS(status)) { - - irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); - - // - // Parse the TPG information and update the device path states - // - status = DsmpParseTargetPortGroupsInformation(context->CompletionContext->DsmContext, - deviceInfo->Group, - targetPortGroupsInfo, - targetPortGroupsInfoLength); - - for (index = 0; index < DSM_MAX_PATHS; index++) { - - targetPortGroup = deviceInfo->Group->TargetPortGroupList[index]; - - if (targetPortGroup) { - - DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); - } - } - - if (NT_SUCCESS(status)) { - - PDSM_DEVICE_INFO tempDevice = NULL; - - // - // Update all the devInfo states. If the device is AO but - // not this device, make it fake AU. - // If device not in AO, make sure that it matches the TPG - // state. - // Ensure that: - // 1. All devices match their ALUA state. - // 2. For RRWS, if a device's desired state is non-A/O, but ALUA state is A/O, mask it. - // 3. For FOO there must be only one A/O device. Preferably the preferred path. - // - for (index = 0; index < DSM_MAX_PATHS; index++) { - - devInfo = group->DeviceList[index]; - - if (devInfo) { - - if (devInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { - - // - // In implicit transitions, there is no guarantee that - // the TPG of chosen "deviceInfo" is in A/O state. So - // to play it safe, we hang on to the very first devInfo - // whose TPG is in A/O state. - // - if (!tempDevice && - !DsmpIsDeviceFailedState(devInfo->State)) { - - devInfo->PreviousState = devInfo->State; - devInfo->State = devInfo->ALUAState; - - tempDevice = devInfo; - } - - if (devInfo != deviceInfo) { - - if (!DsmpIsDeviceFailedState(devInfo->State)) { - - // - // For FOO, only one path can be in A/O. - // For RRWS, mask an A/O path if that isn't the desired state. - // - if ((group->LoadBalanceType == DSM_LB_FAILOVER) || - (group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET && - devInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - devInfo->DesiredState != DSM_DEV_UNDETERMINED)) { - - // - // For implicit transitions, we may have saved off an A/O path. - // Don't undo that. - // - if (tempDevice != devInfo) { - - devInfo->PreviousState = devInfo->State; - devInfo->State = DSM_DEV_ACTIVE_UNOPTIMIZED; - } - - } else { - - devInfo->PreviousState = devInfo->State; - devInfo->State = devInfo->ALUAState; - } - } - } else { - - devInfo->PreviousState = devInfo->State; - - // - // For FOO, only one path can be in A/O state. - // The TPG of the selected "deviceInfo" is in A/O, so this - // can now very well be made the candidate. However, since - // it is possible that we saved off another candidate, we - // now need to replace that with this. - // - if (!DsmpIsDeviceFailedState(devInfo->State) && - devInfo->Group->LoadBalanceType == DSM_LB_FAILOVER && - tempDevice) { - - tempDevice->State = DSM_DEV_ACTIVE_UNOPTIMIZED; - } - - devInfo->State = devInfo->ALUAState; - - tempDevice = devInfo; - } - } else { - - if (!DsmpIsDeviceFailedState(devInfo->State)) { - - devInfo->PreviousState = devInfo->State; - devInfo->State = devInfo->ALUAState; - } - } - } - } - } - - failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - context->CompletionContext->DeviceInfo); - - if (failDevInfoListEntry) { - - DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, - context->CompletionContext->DeviceInfo->Group, - failDevInfoListEntry); - } - - ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); - } - - - // - // Resume IO if we throttled requests. - // - if (InterlockedCompareExchange((LONG volatile*)&group->Throttled, 0, 1)) { - - NTSTATUS resumeStatus = STATUS_UNSUCCESSFUL; - - DsmNotification(((PDSM_CONTEXT)deviceInfo->DsmContext)->MPIOContext, - ResumeIO_V2, - deviceInfo, - TRUE, - &resumeStatus, - 0); - - if (!NT_SUCCESS(resumeStatus)) { - - // - // Resume can fail when - // 1. The MPDisk is being removed (or) - // 2. The MPDisk is any other state other than throttled (or) - // 3. There is a problem dispatching throttled requests. - // - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevObj %p): Resume IO failed.\n", - DeviceObject)); - } - - } - - if (decrementRTPGcount) { - - // - // Resetting InFlightRTPG after resume so that we don't get into situation where - // new DsmpSetPathForIoRetryALUA caller thread finds that InFlightRTPG is not set but Throttled is set - // - ULONG count = InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 0, 1); - - // - // If decrementRTPGCount flag is set, there must be atleast one RTPG in flight. - // - NT_ASSERT(count); - - UNREFERENCED_PARAMETER(count); - - } - - // - // Free the allocations. - // - if (targetPortGroupsInfo) { - - DsmpFreePool(targetPortGroupsInfo); - } - - // - // Release our hold on the device info so that it can be removed. - // - InterlockedDecrement(&context->CompletionContext->DeviceInfo->BlockRemove); - - IoFreeMdl(Irp->MdlAddress); - Irp->MdlAddress = NULL; - - DsmpFreePool(Irp->UserBuffer); - - IoFreeIrp(Irp); - Irp = (PIRP) NULL; - - ExFreeToNPagedLookasideList(&(context->CompletionContext->DsmContext)->CompletionContextList, context->CompletionContext); - DsmpFreePool(srb); - DsmpFreePool(senseData); -#pragma warning(suppress:6001) // DevDiv 818965 - DsmpFreePool(context); - -__Exit_DsmpPhase2ProcessPathFailingALUA: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Exiting function.\n", - deviceInfo)); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - - -NTSTATUS -DsmpPersistentReserveOut( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ) -/*++ - -Routine Description: - - This routine will handle determine which devices to send the request to based - on the service action of the PR-out command. - On REGISTER/REGISTER_AND_IGNORE_EXISTING, it will send the command down all - paths. If any path succeeds, the PR key will be stored. If failure down any - path, return failure. - On REGISTER/REGISTER_AND_IGNORE_EXISTING with key == 0 (ie. UNREGISTER), - the request is sent down every path. Failure is returned if request fails down - any path (but error is ignored if path happens to be one where prior - REGISTER/REGISTER_AND_IGNORE_EXISTING had failed in the first place). The - stored PR key is cleared irrespective of success/failure being returned. - On RESERVE/RELEASE, the command is sent down one path. If it fails, another - path is tried. Failure is returned only if none succeed. - On CLEAR, command is sent down one path. If it fails, another path is tried. - Failure is returned only if none succeed. The stored PR key is cleared - irrespective of success/failure being returned. - On PREEMPT, command is sent down one path. If it fails, another path is - tried. Failure is returned only if none succeed. - On PREEMPT_AND_ABORT, command is sent down one path. Failed request is not - retried. - - NOTE: If a path shows up later, REGISTER_AND_IGNORE_EXISTING request is - built by the IsPathActive routine using the saved PR key and sent down new path. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DsmIds - The collection of DSM IDs that pertain to the MPDISK. - Irp - Irp containing SRB. - Srb - Scsi request block - Event - The event to - -Return Value: - - NTSTATUS of the operation. - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo; - PDSM_DEVICE_INFO servicingDeviceInfo = NULL; - PDSM_GROUP_ENTRY group; - LONG i; - ULONG count; - NTSTATUS status = STATUS_UNSUCCESSFUL; - PDSM_COMPLETION_CONTEXT completionContext; - PCDB cdb = SrbGetCdb(Srb); - UCHAR serviceAction; - NTSTATUS returnStatus = STATUS_SUCCESS; - BOOLEAN sendDownAll = FALSE; - BOOLEAN savePRKeyIfAnySucceed = FALSE; - BOOLEAN retryOnAnother = FALSE; - BOOLEAN passOnlyIfAllSucceed = FALSE; - BOOLEAN ignoreIfPreviousFailed = FALSE; - BOOLEAN clearPRKey = FALSE; - KEVENT event; - PPRO_PARAMETER_LIST prOutParam = Irp->AssociatedIrp.SystemBuffer; - PUCHAR index = NULL; - UCHAR prKey[8] = {0}; - PSTORAGE_REQUEST_BLOCK_HEADER srbCopy = NULL; - PIO_STACK_LOCATION irpStack; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - BOOLEAN statusUpdated = FALSE; - ULONGLONG currentTickCount; - ULONGLONG finalTickCount; - ULONG tickLength = KeQueryTimeIncrement(); - PVOID senseInfoBuffer = NULL; - UCHAR senseInfoBufferLength = 0; - BOOLEAN srbCopySucceeded = FALSE; - UCHAR prType; - UCHAR prScope; - ULONGLONG saKey; - ULONGLONG resKey; - ULONG SpecialHandlingFlag = 0; - - UNREFERENCED_PARAMETER(Event); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // Cache away a copy of the SRB - // - srbCopy = SrbAllocateCopy(Srb, NonPagedPoolNx, DSM_TAG_SCSI_REQUEST_BLOCK); - if (srbCopy == NULL) { - returnStatus = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpPersistentReserveOut; - } - - deviceInfo = DsmIds->IdList[0]; - group = deviceInfo->Group; - - prType = cdb->PERSISTENT_RESERVE_OUT.Type; - prScope = cdb->PERSISTENT_RESERVE_OUT.Scope; - serviceAction = cdb->PERSISTENT_RESERVE_OUT.ServiceAction; - - NT_ASSERT(serviceAction >= RESERVATION_ACTION_REGISTER && serviceAction <= RESERVATION_ACTION_REGISTER_IGNORE_EXISTING); - - index = prOutParam->ServiceActionReservationKey; - RtlCopyMemory(&prKey, index, 8); - REVERSE_BYTES_QUAD(&saKey, &prOutParam->ServiceActionReservationKey); - - REVERSE_BYTES_QUAD(&resKey, &prOutParam->ReservationKey); - - switch (serviceAction) { - case RESERVATION_ACTION_REGISTER: - case RESERVATION_ACTION_REGISTER_IGNORE_EXISTING: { - - // - // The command must be sent down all paths. - // - sendDownAll = TRUE; - - // - // Return failure if it fails down even one of the paths. - // - passOnlyIfAllSucceed = TRUE; - - if (DsmpIsPersistentReservationKeyZeroKey(ARRAY_SIZE(prKey), prKey)) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): NULL PR key, service action %u\n", - DsmIds, - serviceAction)); - - // - // If unregister fails, don't report it back as error if the - // previous register/register_and_ignore_existing down that - // path had failed too. - // - ignoreIfPreviousFailed = TRUE; - - // - // Clear the group PR key irrespective of the status that is - // going to be returned to clusdisk. - // - clearPRKey = TRUE; - - } else { - - // - // If register/register_and_ignore_existing succeed down any of - // the paths, save off the PR key for the group entry. - // - savePRKeyIfAnySucceed = TRUE; - } - - break; - } - - case RESERVATION_ACTION_RESERVE: - case RESERVATION_ACTION_RELEASE: - case RESERVATION_ACTION_PREEMPT: - case RESERVATION_ACTION_PREEMPT_ABORT: - case RESERVATION_ACTION_CLEAR: { - - if (serviceAction != RESERVATION_ACTION_PREEMPT_ABORT) { - - // - // Apart from preempt_abort, all the others must be retried - // (down another path) if they fail down the chosen path. - // - retryOnAnother = TRUE; - } - - if (serviceAction == RESERVATION_ACTION_CLEAR) { - - // - // Clear the stored PR key for the group entry irrespective of - // the status that is going to be returned back. - // - clearPRKey = TRUE; - } - - break; - } - - default: { - - returnStatus = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): Invalid service action %u.\n", - DsmIds, - serviceAction)); - - goto __Exit_DsmpPersistentReserveOut; - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): Srb %p, Service Action %u, Type %u, Scope %u, \ - \n\t\t\t\tservice action reservation key %I64x, reservation key %I64x.\n", - DsmIds, - Srb, - serviceAction, - prType, - prScope, - saKey, - resKey)); - - // - // Allocate a context for the completion routine. - // - completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); - if (!completionContext) { - - returnStatus = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Failed to allocate completion context.\n", - DsmIds, - serviceAction)); - - goto __Exit_DsmpPersistentReserveOut; - } - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Indicate the target for this request. - // - completionContext->DsmContext = DsmContext; - completionContext->RequestUnique1 = (PVOID)&event; - completionContext->RequestUnique2 = cdb->PERSISTENT_RESERVE_OUT.OperationCode; - - count = group->NumberDevices; - - for (i = count - 1; i >= 0; i--) { - - // - // A PR command may fail with a "retry-able" UA when reservation is - // released or preempted (on every I_T_L nexus except the one on which - // it was released/preempted). In such a case we should retry the PR - // command on the same path. - // - KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); - finalTickCount = currentTickCount + (DSM_SECONDS_TO_TICKS(group->MaxPRRetryTimeDuringStateTransition) / tickLength); - - if (!sendDownAll && !retryOnAnother) { - - // - // If the request doesn't need to be retried (down another path) on - // failure, better choose the path that has maximum chances of - // success. - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmIds->IdList[0]), - SpecialHandlingFlag); - - if (!deviceInfo) { - - returnStatus = STATUS_UNSUCCESSFUL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - No active/alternative path for device %p.\n", - DsmIds, - serviceAction, - group)); - - break; - } - - } else { - - deviceInfo = group->DeviceList[i]; - - // - // Ignore "bad" paths for now. If the path becomes "good" again, - // IsPathActive() will send down the register. - // Also, don't consider newly arrived paths for which the group has - // a reservation but register has not yet been sent down. This rule - // applies only to requests that are not Register. - // - if ((DsmpIsDeviceFailedState(deviceInfo->State) || !DsmpIsDeviceInitialized(deviceInfo)) || - (!DsmpIsDeviceUsablePR(deviceInfo) && !sendDownAll)) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): Ignoring bad instance - state %x, init %x, key reg %x (key valid %x).\n", - DsmIds, - deviceInfo->State, - deviceInfo->Initialized, - deviceInfo->PRKeyRegistered, - deviceInfo->Group->PRKeyValid)); - - deviceInfo = NULL; - } - - } - - if (!deviceInfo) { - - // - // Maybe a remove came through and caused a collapse of the device - // list, thus making this entry empty. - // - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Couldn't find path for device %p.\n", - DsmIds, - serviceAction, - group)); - - continue; - } - -__DsmpPersistentReserveOut_RetryRequest: - - IoMarkIrpPending(Irp); - - completionContext->DeviceInfo = deviceInfo; - - // - // Set-up a completion routine. - // - IoSetCompletionRoutine(Irp, - DsmpPersistentReserveCompletion, - completionContext, - TRUE, - TRUE, - TRUE); - - // - // Always send the original request down a new path - // - irpStack = IoGetNextIrpStackLocation(Irp); - srbCopySucceeded = SrbCopySrb(Srb, SrbGetSrbLength(Srb), srbCopy); - NT_ASSERT(srbCopySucceeded == TRUE); - irpStack->Parameters.Scsi.Srb = Srb; - - // - // Clear the sense buffer if it exists - // - senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); - senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); - if (senseInfoBuffer) { - RtlZeroMemory(senseInfoBuffer, senseInfoBufferLength); - } - - servicingDeviceInfo = deviceInfo; - - // - // Issue the request and wait. - // - status = DsmSendRequest(DsmContext->MPIOContext, - deviceInfo->TargetObject, - Irp, - deviceInfo); - - if (status == STATUS_PENDING) { - - KeWaitForSingleObject(&event, - Executive, - KernelMode, - FALSE, - NULL); - - status = Irp->IoStatus.Status; - } - - if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u sent down successfully on %p.\n", - DsmIds, - serviceAction, - deviceInfo->FailGroup->PathId)); - - if (!passOnlyIfAllSucceed) { - - // - // Success down any one path means success - // - returnStatus = status; - } - - if (savePRKeyIfAnySucceed) { - - RtlCopyMemory(&group->PersistentReservationRegisteredKey, &prKey, 8); - - group->PRServiceAction = serviceAction; - group->PRType = prType; - group->PRScope = prScope; - group->PRKeyValid = TRUE; - deviceInfo->PRKeyRegistered = TRUE; - } - - if (!sendDownAll) { - - // - // Need for retrying on another path only necessary in the case - // of request failing down the chosen path. Since the request - // succeeded down this path, we are done. - // - break; - } - } else { - - BOOLEAN recordFailure; - - // - // Check to see if the request failed because of a "transient error", - // like reservations released for example. If so, this is NOT an actual - // error and the request must be retried. Multiple retries may be required - // if for example the UA indicates that the TPGs are in transitioning state. - // - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && - Srb->SrbStatus & SRB_STATUS_ERROR && - SrbGetScsiStatus(Srb) == SCSISTAT_CHECK_CONDITION) { - - KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); - - senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); - senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); - - if (DsmpShouldRetryPersistentReserveCommand(senseInfoBuffer, senseInfoBufferLength) && - currentTickCount < finalTickCount) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u returned UA with error %x. Retrying same path %p.\n", - DsmIds, - serviceAction, - status, - deviceInfo->FailGroup->PathId)); - - KeResetEvent(&event); - Irp->IoStatus.Status = 0; - - goto __DsmpPersistentReserveOut_RetryRequest; - } - } - - // - // The return status is STATUS_SUCCESS by default. This means that if the - // request failed on the first path and was retried down every other path - // but fails down all of them, the return status is never updated. - // So cache the first failure status to cover the above scenario. - // - if (!statusUpdated) { - - returnStatus = status; - statusUpdated = TRUE; - } - - recordFailure = TRUE; - if (ignoreIfPreviousFailed && !deviceInfo->PRKeyRegistered) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Ignoring status %x for path %p.\n", - DsmIds, - serviceAction, - status, - deviceInfo->FailGroup->PathId)); - - // - // Okay to ignore this failure if the previous failed. - // - recordFailure = FALSE; - } - - if (passOnlyIfAllSucceed && recordFailure) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Saving status %x for return.\n", - DsmIds, - serviceAction, - status)); - - // - // Save the failure status to return back. - // - returnStatus = status; - } - - // - // If the request is not to be sent down all paths, and also - // a retry (along a different path) on failure is not required, - // we're done - just return this failure. - // - if (!(sendDownAll || retryOnAnother)) { - - returnStatus = status; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u sent down %p failed with %x. Breaking out.\n", - DsmIds, - serviceAction, - deviceInfo->FailGroup->PathId, - status)); - - break; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u sent down %p failed with %x. Sending down another path.\n", - DsmIds, - serviceAction, - deviceInfo->FailGroup->PathId, - status)); - } - } - - // - // If we are here, it is either because the request needs to be sent down - // all paths, or because the request failed down the chosen path and needs - // to be retried down a new path. - // - KeResetEvent(&event); - Irp->IoStatus.Status = 0; - } - - if (clearPRKey) { - - for (i = 0; (ULONG)i < group->NumberDevices; i++) { - - deviceInfo = group->DeviceList[i]; - - if (deviceInfo) { - - deviceInfo->RegisterServiced = FALSE; - deviceInfo->PRKeyRegistered = FALSE; - } - } - group->PersistentReservationRegisteredKey[0] = group->PersistentReservationRegisteredKey[1] = - group->PersistentReservationRegisteredKey[2] = group->PersistentReservationRegisteredKey[3] = - group->PersistentReservationRegisteredKey[4] = group->PersistentReservationRegisteredKey[5] = - group->PersistentReservationRegisteredKey[6] = group->PersistentReservationRegisteredKey[7] = 0; - - group->PRKeyValid = FALSE; - group->ReservationList = 0; - } - - if (savePRKeyIfAnySucceed && group->PRKeyValid) { - - ULONG ordinal; - - for (i = 0; (ULONG)i < group->NumberDevices; i++) { - - deviceInfo = group->DeviceList[i]; - - if (deviceInfo) { - - deviceInfo->RegisterServiced = TRUE; - ordinal = (1 << i); - group->ReservationList |= ordinal; - } - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): PR_OUT for %u completed with status %x.\n", - DsmIds, - serviceAction, - returnStatus)); - - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - -__Exit_DsmpPersistentReserveOut: - - if (srbCopy != NULL) { - DsmpFreePool(srbCopy); - } - - currentIrpStack->Parameters.Others.Argument3 = servicingDeviceInfo; - Irp->IoStatus.Status = returnStatus; - if ((!NT_SUCCESS(returnStatus)) && - (SrbGetSrbStatus(Srb) == SRB_STATUS_SUCCESS)) { - SrbSetSrbStatus(Srb, DsmpNtStatusToSrbStatus(returnStatus)); - } - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveOut (DsmIds %p): Exiting function returning IRP status %x.\n", - DsmIds, - returnStatus)); - - return returnStatus; -} - - - -NTSTATUS -DsmpPersistentReserveIn( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ) -/*++ - -Routine Description: - - This routine will handle determine which devices to send the request to based - on the service action of the PR-in command. - On READ KEYS, it will send down one path. In case of failure, other paths will - be tried until one succeeds. Failure is returned only if it fails down all paths. - On READ_RESERVATION/REPORT_CAPABILITIES, command is sent down one path. Failed - request is not retried. - -Arguments: - - DsmContext - DSM context given to MPIO during initialization - DsmIds - The collection of DSM IDs that pertain to the MPDISK. - Irp - Irp containing SRB. - Srb - Scsi request block - Event - The event to - -Return Value: - - NTSTATUS of the operation. - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo; - PDSM_DEVICE_INFO servicingDeviceInfo = NULL; - PDSM_GROUP_ENTRY group; - LONG i; - ULONG count; - NTSTATUS status = STATUS_UNSUCCESSFUL; - PDSM_COMPLETION_CONTEXT completionContext; - PCDB cdb = SrbGetCdb(Srb); - UCHAR serviceAction; - BOOLEAN retryOnAnother = FALSE; - KEVENT event; - PSTORAGE_REQUEST_BLOCK_HEADER srbCopy = NULL; - PIO_STACK_LOCATION irpStack; - PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); - ULONGLONG currentTickCount; - ULONGLONG finalTickCount; - ULONG tickLength = KeQueryTimeIncrement(); - PVOID senseInfoBuffer = NULL; - UCHAR senseInfoBufferLength = 0; - BOOLEAN srbCopySucceeded = FALSE; - ULONG SpecialHandlingFlag = 0; - - UNREFERENCED_PARAMETER(Event); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // Cache away a copy of the SRB - // - srbCopy = SrbAllocateCopy(Srb, NonPagedPoolNx, DSM_TAG_SCSI_REQUEST_BLOCK); - if (srbCopy == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpPersistentReserveIn; - } - - deviceInfo = DsmIds->IdList[0]; - group = deviceInfo->Group; - - serviceAction = cdb->PERSISTENT_RESERVE_IN.ServiceAction; - - switch (serviceAction) { - case RESERVATION_ACTION_READ_RESERVATIONS: - case RESERVATION_ACTION_READ_KEYS: { - - // - // If there is a failure on the chosen path, retry on another path. - // - retryOnAnother = TRUE; - break; - } - - case SPC3_RESERVATION_ACTION_REPORT_CAPABILITIES: { - - break; - } - - default: { - - NT_ASSERT(FALSE); - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpPersistentReserveIn; - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): Srb %p. Service Action %u.\n", - DsmIds, - Srb, - serviceAction)); - - // - // Allocate a context for the completion routine. - // - completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); - if (!completionContext) { - - status = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u - Failed to allocate completion context.\n", - DsmIds, - serviceAction)); - - goto __Exit_DsmpPersistentReserveIn; - } - - KeInitializeEvent(&event, NotificationEvent, FALSE); - - // - // Indicate the target for this request. - // - completionContext->DsmContext = DsmContext; - completionContext->RequestUnique1 = (PVOID)&event; - completionContext->RequestUnique2 = cdb->PERSISTENT_RESERVE_IN.OperationCode; - - count = group->NumberDevices; - - for (i = count - 1; i >= 0; i--) { - - // - // A PR command may fail with a "retry-able" UA when reservation is - // released or preempted (on every I_T_L nexus except the one on which - // it was released/preempted). In such a case we should retry the PR - // command on the same path. - // - KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); - finalTickCount = currentTickCount + (DSM_SECONDS_TO_TICKS(group->MaxPRRetryTimeDuringStateTransition) / tickLength); - - if (!retryOnAnother) { - - // - // If the request doesn't need to be retried (down another path) on - // failure, better choose the path that has maximum chances of - // success. - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmIds->IdList[0]), - SpecialHandlingFlag); - - if (!deviceInfo) { - - status = STATUS_UNSUCCESSFUL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u - No active/alternative path for device %p.\n", - DsmIds, - serviceAction, - group)); - - break; - } - - } else { - - deviceInfo = group->DeviceList[i]; - - if (DsmpIsDeviceFailedState(deviceInfo->State) || !DsmpIsDeviceInitialized(deviceInfo)) { - - // - // Ignore "bad" paths for now. - // - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): Ignoring bad instance - state %x, init %x.\n", - DsmIds, - deviceInfo->State, - deviceInfo->Initialized)); - - deviceInfo = NULL; - } - } - - if (!deviceInfo) { - - // - // Maybe a remove came through and caused a collapse of the device - // list, thus making this entry empty. - // - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u - Couldn't find path for device %p.\n", - DsmIds, - serviceAction, - group)); - - continue; - } - -__DsmpPersistentReserveIn_RetryRequest: - - IoMarkIrpPending(Irp); - - completionContext->DeviceInfo = deviceInfo; - - // - // Set-up a completion routine. - // - IoSetCompletionRoutine(Irp, - DsmpPersistentReserveCompletion, - completionContext, - TRUE, - TRUE, - TRUE); - - // - // Always send the original request down a new path - // - irpStack = IoGetNextIrpStackLocation(Irp); - srbCopySucceeded = SrbCopySrb(Srb, SrbGetSrbLength(Srb), srbCopy); - NT_ASSERT(srbCopySucceeded == TRUE); - irpStack->Parameters.Scsi.Srb = Srb; - - // - // Clear the sense buffer if it exists - // - senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); - senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); - if (senseInfoBuffer) { - RtlZeroMemory(senseInfoBuffer, senseInfoBufferLength); - } - - servicingDeviceInfo = deviceInfo; - - // - // Issue the request and wait. - // - status = DsmSendRequest(DsmContext->MPIOContext, - deviceInfo->TargetObject, - Irp, - deviceInfo); - - if (status == STATUS_PENDING) { - - KeWaitForSingleObject(&event, - Executive, - KernelMode, - FALSE, - NULL); - - status = Irp->IoStatus.Status; - } - - if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u sent down successfully on %p.\n", - DsmIds, - serviceAction, - deviceInfo->FailGroup->PathId)); -#if DBG - if (serviceAction == RESERVATION_ACTION_READ_KEYS) { - - PPRI_REGISTRATION_LIST prInRegistrationList = Irp->AssociatedIrp.SystemBuffer; - ULONG numberOfKeys; - ULONG keyIndex; - ULONGLONG prKey; - - REVERSE_BYTES(&numberOfKeys, &prInRegistrationList->AdditionalLength); - numberOfKeys /= 8; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): %u registrations keys present:\n", - DsmIds, - numberOfKeys)); - - for (keyIndex = 0; keyIndex < numberOfKeys; keyIndex++) { - - REVERSE_BYTES_QUAD(&prKey, &(prInRegistrationList->ReservationKeyList[keyIndex])); - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): Registration Key %u: %I64x\n", - DsmIds, - keyIndex, - prKey)); - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "\n")); - - } else if (serviceAction == RESERVATION_ACTION_READ_RESERVATIONS) { - - PPRI_RESERVATION_LIST prInReservationList = Irp->AssociatedIrp.SystemBuffer; - ULONG numberOfDescriptors; - PPRI_RESERVATION_DESCRIPTOR prInReservationDescriptor = prInReservationList->Reservations; - ULONGLONG prKey = 0; - - REVERSE_BYTES(&numberOfDescriptors, &prInReservationList->AdditionalLength); - numberOfDescriptors /= sizeof(PRI_RESERVATION_DESCRIPTOR); - NT_ASSERT(numberOfDescriptors <= 1); - - if (numberOfDescriptors == 1) { - REVERSE_BYTES_QUAD(&prKey, &prInReservationDescriptor->ReservationKey); - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): %u Reservation Key: %I64x\n", - DsmIds, - numberOfDescriptors, - prKey)); - } -#endif - // - // Done. - // - break; - - } else { - - // - // Check to see if the request failed because of a "transient error", - // like reservations released for example. If so, this is NOT an actual - // error and the request must be retried. Multiple retries may be required - // if for example the UA indicates that the TPGs are in transitioning state. - // - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && - Srb->SrbStatus & SRB_STATUS_ERROR && - SrbGetScsiStatus(Srb) == SCSISTAT_CHECK_CONDITION) { - - KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); - - senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); - senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); - - if (group->PRKeyValid && - DsmpShouldRetryPersistentReserveCommand(senseInfoBuffer, senseInfoBufferLength) && - currentTickCount < finalTickCount) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u returned UA with error %x. Retrying same path %p.\n", - DsmIds, - serviceAction, - status, - deviceInfo->FailGroup->PathId)); - - KeResetEvent(&event); - Irp->IoStatus.Status = 0; - - goto __DsmpPersistentReserveIn_RetryRequest; - } - } - - // - // If a retry (along a different path) on failure is not required, - // we're done - just return this failure. - // - if (!retryOnAnother) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u down %p failed with %x. Breaking out.\n", - DsmIds, - serviceAction, - deviceInfo->FailGroup->PathId, - status)); - - break; - } - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u down %p failed with %x. Sending down another path.\n", - DsmIds, - serviceAction, - deviceInfo->FailGroup->PathId, - status)); - - // - // If we are here, it is because the request failed down the chosen path - // and needs to be retried down a new path. - // - KeResetEvent(&event); - Irp->IoStatus.Status = 0; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u completed with status %x.\n", - DsmIds, - serviceAction, - status)); - - ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); - -__Exit_DsmpPersistentReserveIn: - - if (srbCopy != NULL) { - DsmpFreePool(srbCopy); - } - - currentIrpStack->Parameters.Others.Argument3 = servicingDeviceInfo; - Irp->IoStatus.Status = status; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveIn (DsmIds %p): Exiting function returning IRP status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpPersistentReserveCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -/*++ - -Routine Description: - - General-purpose completion routine for PR in and out commands sent synchronously. - -Arguments: - - DeviceObject - Target of the request. - Irp - Command being sent. - Context - The event on which the caller is waiting. - -Return Value: - - NTSTATUS - ---*/ - -{ - PDSM_COMPLETION_CONTEXT context = Context; - PKEVENT event; - - // It is required to specify a DSM completion context - // when setting DsmpPersistentReserveCompletion as completion routine. - _Analysis_assume_(context != NULL); - - event = (PKEVENT)(context->RequestUnique1); - - UNREFERENCED_PARAMETER(DeviceObject); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpPersistentReserveCompletion: DevInfo %p, IRP %p, Context %p\n", - context->DeviceInfo, - Irp, - Context)); - - if (Irp->PendingReturned) { - - IoMarkIrpPending(Irp); - } - - KeSetEvent(event, 0, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - diff --git a/tests/projects/wdk/wdm/msdsm/dsmtrace.mof b/tests/projects/wdk/wdm/msdsm/dsmtrace.mof deleted file mode 100644 index d9e8cf4cc..000000000 --- a/tests/projects/wdk/wdm/msdsm/dsmtrace.mof +++ /dev/null @@ -1,111 +0,0 @@ -#pragma classflags("forceupdate") -#pragma namespace("\\\\.\\root\\WMI") -// -// Copyright (C) 2004 Microsoft Corporation -// -// WPP Generated File -// - -//ModuleName = wppCtlGuid (Init called in Function DriverEntry) -[Dynamic, - Description("MSDSM Driver Tracing Provider"), - guid("{DEDADFF5-F99F-4600-B8C9-2D4D9B806B5B}"), - locale("MS\\0x409")] -class MSDSMGuid : EventTrace -{ - [Description ("Enable Flags"), - ValueDescriptions{ - "TRACE_FLAG_GENERAL Flag", - "TRACE_FLAG_PNP Flag", - "TRACE_FLAG_POWER Flag", - "TRACE_FLAG_RW Flag", - "TRACE_FLAG_IOCTL Flag", - "TRACE_FLAG_QUEUE Flag", - "TRACE_FLAG_WMI Flag", - "TRACE_FLAG_TIMER Flag", - "TRACE_FLAG_INIT Flag", - "TRACE_FLAG_LOCK Flag", - "TRACE_FLAG_DEBUG1 Flag", - "TRACE_FLAG_DEBUG2 Flag", - "TRACE_FLAG_MCN Flag", - "TRACE_FLAG_ISR Flag", - "TRACE_FLAG_ENUM Flag"}, - DefineValues{ - "TRACE_FLAG_GENERAL", - "TRACE_FLAG_PNP", - "TRACE_FLAG_POWER", - "TRACE_FLAG_RW", - "TRACE_FLAG_IOCTL", - "TRACE_FLAG_QUEUE", - "TRACE_FLAG_WMI", - "TRACE_FLAG_TIMER", - "TRACE_FLAG_INIT", - "TRACE_FLAG_LOCK", - "TRACE_FLAG_DEBUG1", - "TRACE_FLAG_DEBUG2", - "TRACE_FLAG_MCN", - "TRACE_FLAG_ISR", - "TRACE_FLAG_ENUM"}, - Values{ - "TRACE_FLAG_GENERAL", - "TRACE_FLAG_PNP", - "TRACE_FLAG_POWER", - "TRACE_FLAG_RW", - "TRACE_FLAG_IOCTL", - "TRACE_FLAG_QUEUE", - "TRACE_FLAG_WMI", - "TRACE_FLAG_TIMER", - "TRACE_FLAG_INIT", - "TRACE_FLAG_LOCK", - "TRACE_FLAG_DEBUG1", - "TRACE_FLAG_DEBUG2", - "TRACE_FLAG_MCN", - "TRACE_FLAG_ISR", - "TRACE_FLAG_ENUM"}, - ValueMap{ - "0x00000001", - "0x00000002", - "0x00000004", - "0x00000008", - "0x00000010", - "0x00000020", - "0x00000040", - "0x00000080", - "0x00000100", - "0x00000200", - "0x00000400", - "0x00000800", - "0x00001000", - "0x00002000", - "0x00004000"} - ] - uint32 Flags; - [Description ("Levels"), - ValueDescriptions{ - "Abnormal exit or termination", - "Severe errors that need logging", - "Warnings such as allocation failure", - "Includes non-error cases", - "Detailed traces from intermediate steps" }, - DefineValues{ - "TRACE_LEVEL_FATAL", - "TRACE_LEVEL_ERROR", - "TRACE_LEVEL_WARNING" - "TRACE_LEVEL_INFORMATION", - "TRACE_LEVEL_VERBOSE" }, - Values{ - "Fatal", - "Error", - "Warning", - "Information", - "Verbose" }, - ValueMap{ - "0x1", - "0x2", - "0x3", - "0x4", - "0x5" }, - ValueType("index") - ] - uint32 Level; -}; diff --git a/tests/projects/wdk/wdm/msdsm/intrface.c b/tests/projects/wdk/wdm/msdsm/intrface.c deleted file mode 100644 index eeebf7f93..000000000 --- a/tests/projects/wdk/wdm/msdsm/intrface.c +++ /dev/null @@ -1,5198 +0,0 @@ -/*++ - -Copyright (C) 2004-2010 Microsoft Corporation - -Module Name: - - intrface.c - -Abstract: - - This driver is the Microsoft Device Specific Module (DSM) - devices that conform with SPC-3 specs. - It exports behaviors that mpio.sys will use to determine how to - multipath these devices. - - This file contains DriverEntry and all the functions that are - exported to MPIO. - - This DSM is targetted towards Windows 2008 and above. - -Environment: - - kernel mode only - ---*/ - -#include "precomp.h" - -#ifdef DEBUG_USE_WPP -#include "intrface.tmh" -#endif - -#pragma warning (disable:4305) - - -// -// Flag to indicate whether to NT_ASSERT or ignore a particular condition. -// -BOOLEAN DoAssert = TRUE; - -// -// OS Version Info -// MSDSM is targetted towards Windows Server 2008 and above. -// -BOOLEAN gServer2008AndAbove = FALSE; - -// -// Global to cache MPIO's Control Object. -// -PDEVICE_OBJECT gMPIOControlObject = NULL; - -// -// Flag to indicate if the MPIO control object was referenced. -// -BOOLEAN gMPIOControlObjectRefd = FALSE; - -// -// Global to cache the Driver Object. -// -PDRIVER_OBJECT gDsmDriverObject = NULL; - - -#ifdef ALLOC_PRAGMA - #pragma alloc_text(INIT, DriverEntry) -#endif - -// -// The code. -// -NTSTATUS -DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - - This routine is called when the driver is loaded. - -Arguments: - - DriverObject - Supplies the driver object. - RegistryPath - Supplies the registry path. - -Return Value: - - NTSTATUS - ---*/ -{ - PDSM_CONTEXT dsmContext = NULL; - PFILE_OBJECT fileObject; - WCHAR dosDeviceName[64] = DSM_MPIO_CONTROL_OBJECT_SYMLINK; - UNICODE_STRING mpUnicodeName; - NTSTATUS status = STATUS_SUCCESS; - MPIO_VERSION_INFO versionInfo = {0}; - DSM_TYPE dsmMode = DsmType3; - DSM_MPIO_CONTEXT mpctlContext; - IO_STATUS_BLOCK ioStatus; - - - // - // Initialize the tracing subsystem. - // Any failure is handled by ETW itself. - // - WPP_INIT_TRACING(DriverObject, RegistryPath); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Entering function.\n", - DriverObject)); - - gDsmDriverObject = DriverObject; - - // - // Determine the OS version. - // - gServer2008AndAbove = RtlIsNtDdiVersionAvailable(NTDDI_VISTA); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Server2008AndAbove is %!bool!.\n", - DriverObject, - gServer2008AndAbove)); - - // - // MSDSM is supported only on Server 2008 and above. - // - if (!gServer2008AndAbove) { - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DriverEntry; - } - - // - // Build the mpio symbolic link name. - // - RtlInitUnicodeString(&mpUnicodeName, dosDeviceName); - - // - // Get a pointer to mpio's deviceObject. - // - status = IoGetDeviceObjectPointer(&mpUnicodeName, - FILE_READ_ATTRIBUTES, - &fileObject, - &gMPIOControlObject); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_FATAL, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Failed to communicate with MPIO control object. Status %x.\n", - DriverObject, - status)); - - goto __Exit_DriverEntry; - } - - ObReferenceObject(gMPIOControlObject); - gMPIOControlObjectRefd = TRUE; - ObDereferenceObject(fileObject); - - status = DsmGetVersion(&versionInfo, sizeof(MPIO_VERSION_INFO)); - - if (!NT_SUCCESS(status)) { - - // - // If we can't get the version, that means we aren't using a compatible - // version of MPIO drivers and so should not continue. - // - TracePrint((TRACE_LEVEL_FATAL, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): MPIO version unknown - DSM exiting.\n", - DriverObject)); - - status = STATUS_UNSUCCESSFUL; - goto __Exit_DriverEntry; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): MPIO version %d.%d.%d.%d.\n", - DriverObject, - versionInfo.MajorVersion, - versionInfo.MinorVersion, - versionInfo.ProductBuild, - versionInfo.QfeNumber)); - - RtlZeroMemory(&gDsmInitData, sizeof(DSM_INIT_DATA)); - - // - // Must be newer than 1.0.7.0 to support DSM type 2 upwards. - // - if ((versionInfo.MajorVersion > 1) || - (versionInfo.MinorVersion >= 1) || - (versionInfo.ProductBuild > 7) || - (versionInfo.QfeNumber >= 1)) { - - // - // Must be newer than 1.18 to support DSM's versioning - // - if (versionInfo.MajorVersion > 1 || - versionInfo.MinorVersion > 17) { - - dsmMode = DsmType6; - - { - RTL_OSVERSIONINFOW osVersion = {0}; - - osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); - RtlGetVersion(&osVersion); - - gDsmInitData.DsmVersion.MajorVersion = osVersion.dwMajorVersion; - gDsmInitData.DsmVersion.MinorVersion = osVersion.dwMinorVersion; - gDsmInitData.DsmVersion.ProductBuild = osVersion.dwBuildNumber; - gDsmInitData.DsmVersion.QfeNumber = 0; - } - } - } else { - - // - // We cannot use this DSM with older versions of the MPIO drivers. - // - TracePrint((TRACE_LEVEL_FATAL, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): MPIO version not supported - DSM exiting.\n", - DriverObject)); - - status = STATUS_UNSUCCESSFUL; - goto __Exit_DriverEntry; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Setting DSM type to %d.\n", - DriverObject, - dsmMode)); - - // - // Build the init data structure. - // - dsmContext = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_CONTEXT), - DSM_TAG_DSM_CONTEXT); - if (!dsmContext) { - - TracePrint((TRACE_LEVEL_FATAL, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Failed to allocate memory for DSM Context.\n", - DriverObject)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DriverEntry; - } - - // - // Set-up the init data - // - gDsmInitData.DsmContext = (PVOID) dsmContext; - gDsmInitData.InitDataSize = sizeof(DSM_INIT_DATA); - - gDsmInitData.DsmInquireDriver = DsmInquire; - gDsmInitData.DsmCompareDevices = DsmCompareDevices; - gDsmInitData.DsmGetControllerInfo = DsmGetControllerInfo; - gDsmInitData.DsmSetDeviceInfo = DsmSetDeviceInfo; - gDsmInitData.DsmIsPathActive = DsmIsPathActive; - gDsmInitData.DsmPathVerify = DsmPathVerify; - gDsmInitData.DsmInvalidatePath = DsmInvalidatePath; - gDsmInitData.DsmMoveDevice = DsmMoveDevice; - gDsmInitData.DsmRemovePending = DsmRemovePending; - gDsmInitData.DsmRemoveDevice = DsmRemoveDevice; - gDsmInitData.DsmRemovePath = DsmRemovePath; - gDsmInitData.DsmSrbDeviceControl = DsmSrbDeviceControl; - gDsmInitData.DsmLBGetPath = DsmLBGetPath; - gDsmInitData.DsmInterpretErrorEx = DsmInterpretError; - gDsmInitData.DsmUnload = DsmUnload; - gDsmInitData.DsmSetCompletion = DsmSetCompletion; - gDsmInitData.DsmCategorizeRequest = DsmCategorizeRequest; - gDsmInitData.DsmBroadcastSrb = DsmBroadcastRequest; - gDsmInitData.DsmIsAddressTypeSupported = DsmIsAddressTypeSupported; - gDsmInitData.DsmDeviceNotUsed = DsmDeviceNotUsed; - - // - // Since MSDSM is for SPC-3 compliant devices, MPIO should be able to build - // a serial number for the device. - // - gDsmInitData.DsmDeviceSerialNumber = NULL; - - // - // Notifies MPIO of the appropriate Type support - // - gDsmInitData.DsmType = dsmMode; - - gDsmInitData.DriverObject = DriverObject; - - - // - // Set-up the WMI Info. - // - DsmpWmiInitialize(&gDsmInitData.DsmWmiInfo, RegistryPath); - DsmpDsmWmiInitialize(&gDsmInitData.DsmWmiGlobalInfo, RegistryPath); - - RtlInitUnicodeString(&gDsmInitData.DisplayName, DSM_FRIENDLY_NAME); - - // - // Initialize some of the fields in DSM Context structure. - // - KeInitializeSpinLock(&dsmContext->SupportedDevicesListLock); - InitializeListHead(&dsmContext->GroupList); - InitializeListHead(&dsmContext->DeviceList); - InitializeListHead(&dsmContext->FailGroupList); - InitializeListHead(&dsmContext->ControllerList); - InitializeListHead(&dsmContext->StaleFailGroupList); - - // - // Build the list context structures used for completion processing. - // - ExInitializeNPagedLookasideList(&dsmContext->CompletionContextList, - NULL, - NULL, - POOL_NX_ALLOCATION, - sizeof(DSM_COMPLETION_CONTEXT), - DSM_TAG_GENERIC, - 0); - - RtlZeroMemory(&mpctlContext, sizeof(DSM_MPIO_CONTEXT)); - - // - // Send the IOCTL to mpio.sys to register ourselves. - // - DsmSendDeviceIoControlSynchronous(IOCTL_MPDSM_REGISTER, - gMPIOControlObject, - &gDsmInitData, - &mpctlContext, - sizeof(DSM_INIT_DATA), - sizeof(DSM_MPIO_CONTEXT), - TRUE, - &ioStatus); - - status = ioStatus.Status; - - if (NT_SUCCESS(status)) { - - dsmContext->MPIOContext = mpctlContext.MPIOContext; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Registered with MPIO.\n", - DriverObject)); - - DriverObject->DriverUnload = DsmDriverUnload; - - // - // Query the registry for disabling/enabling statistics gathering - // - if (STATUS_OBJECT_NAME_NOT_FOUND == DsmpGetStatsGatheringChoice(dsmContext, (PULONG)&dsmContext->DisableStatsGathering)) { - - // - // If the value does not exist, write the default to registry. - // - DsmpSetStatsGatheringChoice(dsmContext, (ULONG)dsmContext->DisableStatsGathering); - } - } - -__Exit_DriverEntry: - - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Exiting function successfully.\n", - DriverObject)); - } else { - - // - // Since the DSM is going to be unloaded but without DriverUnload being - // called, we need to perform cleanup here. - // - if (dsmContext != NULL) { - DsmpFreeDSMResources(dsmContext); - dsmContext = NULL; - } - - if (gMPIOControlObjectRefd) { - - // - // Drop the reference on MPIO's control object. - // - ObDereferenceObject(gMPIOControlObject); - gMPIOControlObjectRefd = FALSE; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DriverEntry (DrvObj %p): Exiting function with status %x.\n", - DriverObject, - status)); - - // - // Stop the tracing subsystem. - // NOTE: once we unregister ETW, no more TracePrint can be done, so we - // must ensure that ETW unregister is the last thing that happens. - // - WPP_CLEANUP(gDsmDriverObject); - } - - return status; -} - - -VOID -DsmDriverUnload( - _In_ IN PDRIVER_OBJECT DriverObject - ) -/*++ - -Routine Description: - - This routine is called when the driver is unloaded. - -Arguments: - - DriverObject - Supplies the driver object. - -Return Value: - - Nothing - ---*/ -{ - DSM_DEREGISTER_DATA deregisterData; - IO_STATUS_BLOCK ioStatus; - - deregisterData.DeregisterDataSize = sizeof(DSM_DEREGISTER_DATA); - deregisterData.DriverObject = DriverObject; - deregisterData.DsmContext = gDsmInitData.DsmContext; - deregisterData.MpioContext = ((PDSM_CONTEXT)(gDsmInitData.DsmContext))->MPIOContext; - // - // Send the IOCTL to mpio.sys to de-register ourselves. - // - DsmSendDeviceIoControlSynchronous(IOCTL_MPDSM_DEREGISTER, - gMPIOControlObject, - &deregisterData, - NULL, - sizeof(DSM_DEREGISTER_DATA), - 0, - TRUE, - &ioStatus); - - NT_ASSERT(NT_SUCCESS(ioStatus.Status)); - - - - return; -} - - -NTSTATUS -DsmInquire( - _In_ IN PVOID DsmContext, - _In_ IN PDEVICE_OBJECT TargetDevice, - _In_ IN PDEVICE_OBJECT PortObject, - _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, - _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList, - _Out_ OUT PVOID *DsmIdentifier - ) -/*++ - -Routine Description: - - This routine is used to determine if TargetDevice belongs to - the DSM. If this is a supported device DsmIdentifier will be - updated with 'deviceInfo'. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - TargetDevice - DeviceObject for the child device. - PortObject - The Port driver FDO on which TargetDevice resides. - Descriptor - Pointer to the device descriptor corresponding to TargetDevice. - Rehash of inquiry data, plus serial number information - (if applicable). - DeviceIdList - VPD Page 0x83 information. - DsmIdentifier - Pointer to be filled in by the DSM on success. - -Return Value: - - STATUS_NOT_SUPPORTED - if not on the SupportList. - STATUS_INSUFFICIENT_RESOURCES - No mem. - STATUS_SUCCESS ---*/ -{ - PDSM_CONTEXT dsmContext = DsmContext; - PDSM_DEVICE_INFO deviceInfo = NULL; - PDSM_GROUP_ENTRY group; - BOOLEAN newGroup; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroupEntry = NULL; - PDSM_TARGET_PORT_LIST_ENTRY targetPortEntry = NULL; - PSTR serialNumber = NULL; - SIZE_T serialNumberLength = 0; - NTSTATUS status; - ULONG allocationLength; - BOOLEAN serialNumberAllocated = FALSE; - KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error - BOOLEAN supported = FALSE; - BOOLEAN spinlockHeld = FALSE; - UCHAR vendorId[9] = {0}; - UCHAR productId[17] = {0}; - INQUIRYDATA inquiryData; - UCHAR alua = DSM_DEVINFO_ALUA_NOT_SUPPORTED; - ULONG index; - PDSM_IDS controllerObjects = NULL; - PDEVICE_OBJECT controllerDeviceObject; - PLIST_ENTRY entry = NULL; - PSTORAGE_DESCRIPTOR_HEADER controllerIdHeader = NULL; - PULONG relativeTargetPortId = NULL; - PUSHORT targetPortGroupId = NULL; - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength = 0; - PSTR controllerSerialNumber; - BOOLEAN match = FALSE; - BOOLEAN doneUpdating = FALSE; - PDSM_CONTROLLER_LIST_ENTRY controllerEntry = NULL; - PDSM_TARGET_PORT_DEVICELIST_ENTRY tp_device = NULL; - PWSTR hardwareId = NULL; - PWCHAR deviceName = NULL; - ULONG tempResult = 0; - ULONG maxPRRetryTimeDuringStateTransition = DSM_MAX_PR_UNIT_ATTENTION_RETRY_TIME; - BOOLEAN useCacheForLeastBlocks = FALSE; - ULONGLONG cacheSizeForLeastBlocks = 0; - BOOLEAN fakeControllerEntryExists = FALSE; - STORAGE_IDENTIFIER_CODE_SET serialNumberCodeSet = StorageIdCodeSetReserved; - -#if DBG - BOOLEAN multiport; -#endif - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Entering function.\n", - TargetDevice)); - - // - // 1. Get standard inquiry for the device. Check if SPC-3 compliant. - // If not compliant, check SupportedDeviceList. - // 2. Create device serial number. - // 3. Create a partially populated deviceInfo. - // DeviceDescriptor. - // SCSI address. - // Save off serial number. - // ALUA, port FDO, etc. - // 4. Create device name. - // 5. If ALUA support, send down Report Target Port Groups. - // 6. Find the group. If none, build one. - // 7. If new group, build target port groups and target ports info. - // Else, update target port groups and target ports info. - // 8. If both implicit as well as explicit transitions allowed, disable implicit. - // 9. Get list of controllers objects and get VPD 0x83 for each (only if no - // match for existing ones). - // Match returned ids of type 0x5 with what was returned in Report Target Port Groups. - // If no type 0x5 identifier, use SCSI address. - // Create controller list (delete stale entries). - // - - - // - // Query the registry to find out what devices are being supported - // on this machine. - // - DsmpGetDeviceList(dsmContext); - - status = DsmpGetStandardInquiryData(TargetDevice, &inquiryData); - - if (NT_SUCCESS(status)) { - - supported = DsmpCheckScsiCompliance(TargetDevice, - &inquiryData, - Descriptor, - DeviceIdList); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to get inquiry data with status %x.\n", - TargetDevice, - status)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // Since the device isn't SPC-3 compliant, check if the device is on the - // SupportedDeviceList. - // - if (!supported) { - - - if (!supported) { - - // - // Get the inquiry data embedded in the device descriptor. - // - RtlStringCchCopyA((LPSTR)vendorId, - sizeof(vendorId) / sizeof(vendorId[0]), - (LPCSTR)(&inquiryData.VendorId)); - - RtlStringCchCopyA((LPSTR)productId, - sizeof(productId) / sizeof(productId[0]), - (LPCSTR)(&inquiryData.ProductId)); - - supported = DsmpDeviceSupported(dsmContext, - (PCSZ)vendorId, - (PCSZ)productId); - } - - if (!supported) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Unsupported Device.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - } - - // - // Find out if device can be accessed via mulitple ports. This info is - // important since it will determine whether or not to send down a - // ReportTargetPortGroups command. - // -#if DBG - multiport = (inquiryData.MultiPort & 0x10) ? TRUE : FALSE; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Is %ws multiported.\n", - TargetDevice, - multiport ? L"" : L"not")); -#endif - - // - // Query the assymmetric states transition method - // - switch ((inquiryData.Reserved >> 0x4) & 0x3) { - case 1: alua = DSM_DEVINFO_ALUA_IMPLICIT; - break; - - case 2: alua = DSM_DEVINFO_ALUA_EXPLICIT; - break; - - case 3: alua = DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT; - break; - - default: alua = DSM_DEVINFO_ALUA_NOT_SUPPORTED; - break; - } - - // - // Get some information about this device. The preferred info is - // from the Device ID Page. - // - if (DeviceIdList) { - - // - // This will parse out the 'best' identifier and return - // a NULL-terminated ascii string. - // - serialNumber = (PSTR)DsmpParseDeviceID(DeviceIdList, - DSM_DEVID_SERIAL_NUMBER, - NULL, - &serialNumberCodeSet, - FALSE); - - if (!serialNumber) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): NULL serial number.\n", - TargetDevice)); - - // - // Either an allocation failed, or the DeviceIdList is malformed. - // - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // Indicate that the serialnumber buffer is allocated. - // - serialNumberAllocated = TRUE; - serialNumberLength = strlen((const char*)serialNumber); - - } else { - - // - // Get the serial number of this device. Use the serial number - // page (0x80). Ensure that the device's serial number is - // present. If not, can't claim support for this drive. - // - - if (!Descriptor || - (Descriptor->SerialNumberOffset == MAXULONG) || - (Descriptor->SerialNumberOffset == 0)) { - - // - // The port driver currently doesn't get the VPD page 0x80, - // if the device doesn't support GET_SUPPORTED_PAGES. Check to - // see whether there actually is a serial number. - // - serialNumber = DsmpGetSerialNumber(TargetDevice); - - if (!serialNumber) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): serialNumber = NULL.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - - } else { - serialNumberAllocated = TRUE; - serialNumberLength = strlen((const char*)serialNumber); - } - } - } - - // - // Allocate for the device. This is also used as DsmId. - // - allocationLength = sizeof(DSM_DEVICE_INFO); - - // - // As DSM_DEVICE_INFO has storage for the descriptor, add only - // the additional stuff that's at the end. - // - if (Descriptor) { - status = RtlULongSub(Descriptor->Size, sizeof(STORAGE_DEVICE_DESCRIPTOR), &tempResult); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Arithmetic underflow - status %x.\n", - TargetDevice, - status)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - } - - status = RtlULongAdd(allocationLength, tempResult, &allocationLength); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Arithmetic overflow - status %x.\n", - TargetDevice, - status)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - deviceInfo = DsmpAllocatePool(NonPagedPoolNx, - allocationLength, - DSM_TAG_DEV_INFO); - if (!deviceInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to allocate Device Info.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - deviceInfo->State = deviceInfo->PreviousState = deviceInfo->TempPreviousStateForLB = deviceInfo->ALUAState = deviceInfo->LastKnownGoodState = DSM_DEV_NOT_USED_STATE; - deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; - // - // Copy over the StorageDescriptor. - // - if (Descriptor) { - RtlCopyMemory(&deviceInfo->Descriptor, - Descriptor, - Descriptor->Size); - } - - // - // Get the scsi address for this device. Note that on success, DsmGetScsiAddress() - // will allocate memory which we are responsible for freeing. - // - status = DsmGetScsiAddress(TargetDevice, - &deviceInfo->ScsiAddress); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Error %x while getting scsi address.\n", - TargetDevice, - status)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // Capture the serial number allocated flag. - // - deviceInfo->SerialNumberAllocated = serialNumberAllocated; - - // - // Set the serial number. - // - if (!serialNumberAllocated) { - - PSTORAGE_DEVICE_DESCRIPTOR descriptor; - - // - // serialNumber is not pointing to the buffer passed by MPIO. Update - // it to point to the Device Descriptor allocated by the DSM. - // - descriptor = &(deviceInfo->Descriptor); - - NT_ASSERT(descriptor->SerialNumberOffset != 0 && descriptor->SerialNumberOffset != MAXULONG); - - serialNumber = (PCHAR)descriptor + descriptor->SerialNumberOffset; - serialNumberLength = strlen((const char*)serialNumber); - } - - if (alua == (DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT)) { - - BOOLEAN disableImplicit = FALSE; - - status = DsmpDisableImplicitStateTransition(TargetDevice, &disableImplicit); - - if (NT_SUCCESS(status)) { - - if (disableImplicit) { - - alua &= ~DSM_DEVINFO_ALUA_IMPLICIT; - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Disabled implicit ALUA state transition.\n", - TargetDevice)); - - // - // Record that the storage actually supported implicit also, but we - // turned it OFF. - // - deviceInfo->ImplicitDisabled = TRUE; - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Storage support both transitions but does NOT allow disabling Implicit.\n", - TargetDevice)); - } - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to disable implicit ALUA state transitions - status %x.\n", - TargetDevice, - status)); - } - } - - deviceInfo->SerialNumber = serialNumber; - - // - // Save the Physical Device Object (PDO) of the device. - // Used to verify that no two devices have the same PDO. - // - deviceInfo->PortPdo = TargetDevice; - - // - // Save the FDO of the adapter. Used for handling reserve\release - // - deviceInfo->PortFdo = PortObject; - - // - // Set the signature. - // - deviceInfo->DeviceSig = DSM_DEVICE_SIG; - - deviceInfo->DsmContext = DsmContext; - - deviceInfo->ALUASupport = alua; - - // - // Build the name (using serialnumber) that will be used as registry key - // to store Load Balance settings for this device. - // - deviceName = DsmpBuildDeviceName(deviceInfo, serialNumber, serialNumberLength); - - if (!deviceName) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to allocate device name for %p.\n", - TargetDevice, - deviceInfo)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - - // - // Send down ReportTargetPortGroups command and keep the info handy. - // - if (alua != DSM_DEVINFO_ALUA_NOT_SUPPORTED) { - - status = DsmpReportTargetPortGroups(TargetDevice, - &targetPortGroupsInfo, - &targetPortGroupsInfoLength); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to report target port groups for %p. Status %x.\n", - TargetDevice, - deviceInfo, - status)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // We've just sent down an RTPG (relatively expensive operation), and it - // succeeded, so sending down one more as part part of the initialization - // in PathVerify() since it is going to be called almost immediately. - // - deviceInfo->IgnorePathVerify = TRUE; - } - - // - // Query the registry for max time to retry failed PR requests - // - DsmpGetMaxPRRetryTime(DsmContext, &maxPRRetryTimeDuringStateTransition); - - // - // Query the registry to see if the user has overridden the default - // Least Blocks settings. - // - status = DsmpQueryCacheInformationFromRegistry(DsmContext, - &useCacheForLeastBlocks, - &cacheSizeForLeastBlocks); - - if (!NT_SUCCESS(status)) { - // - // Couldn't get the settings from the registry so fall back on the - // default for Least Blocks. - // - useCacheForLeastBlocks = TRUE; - cacheSizeForLeastBlocks = DSM_LEAST_BLOCKS_DEFAULT_THRESHOLD; - } - - // - // Build LUN's hardware id. Needs to be called at PASSIVE_LEVEL, so - // do it before grabbing the lock. The hardware id of the group is - // later set under the protection of the lock. - // - hardwareId = DsmpBuildHardwareId(deviceInfo); - - irql = ExAcquireSpinLockExclusive(&(((PDSM_CONTEXT)DsmContext)->DsmContextLock)); - spinlockHeld = TRUE; - - status = STATUS_SUCCESS; - - // - // See if there is an existing Multi-path group to which this belongs. - // (same serial number). - // - group = DsmpFindDevice(DsmContext, deviceInfo, FALSE); - if (!group) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): First device %p in the group.\n", - TargetDevice, - deviceInfo)); - - newGroup = TRUE; - - // - // This device doesn't belong to any group yet. So Build a multi-path - // group entry. This'll represents all paths to a particular device. - // - group = DsmpBuildGroupEntry(DsmContext, deviceInfo); - if (group) { - - // - // Set the registry key name for the new group - // - group->RegistryKeyName = deviceName; - deviceName = NULL; - - // - // Cache the LUN's hardware id - // - if (!hardwareId) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to build a hardwareId for %p.\n", - TargetDevice, - deviceInfo)); - } - - group->HardwareId = hardwareId; - hardwareId = NULL; - - group->UseCacheForLeastBlocks = useCacheForLeastBlocks; - group->CacheSizeForLeastBlocks = cacheSizeForLeastBlocks; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to allocate Group Entry for %p.\n", - TargetDevice, - deviceInfo)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - } else { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Found group %p for device %p.\n", - TargetDevice, - group, - deviceInfo)); - - newGroup = FALSE; - - if (!group->HardwareId) { - - // - // If we weren't successful in previously building the hardware id for this LUN, - // retry doing it again now. - // - hardwareId = DsmpBuildHardwareId(deviceInfo); - if (!hardwareId) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to build a hardwareId for %p.\n", - TargetDevice, - deviceInfo)); - } - - group->HardwareId = hardwareId; - hardwareId = NULL; - } - - // - // Sanity check that we haven't been presented with device instances - // with different ALUA support. So compare with the first device instance. - // - for (index = 0; index < DSM_MAX_PATHS; index++) { - - if (group->DeviceList[index]) { - - break; - } - } - - if (index < DSM_MAX_PATHS) { - - // - // Only acceptable conditions are: - // 1. both have same support, - // 2. one has explicit, while other has both explicit-and-implicit (this - // is a potential valid case because DsmpDisableImplicitStateTransition - // may have failed). - // - if (!((deviceInfo->ALUASupport == group->DeviceList[index]->ALUASupport) || - ((deviceInfo->ALUASupport == DSM_DEVINFO_ALUA_EXPLICIT && deviceInfo->ImplicitDisabled) && - (group->DeviceList[index]->ALUASupport == (DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT))) || - ((group->DeviceList[index]->ALUASupport == DSM_DEVINFO_ALUA_EXPLICIT && group->DeviceList[index]->ImplicitDisabled) && - (deviceInfo->ALUASupport == (DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT))))) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Mismatch in device instances' ALUA support %d vs %d.\n", - TargetDevice, - deviceInfo->ALUASupport, - group->DeviceList[index]->ALUASupport)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - } - } - - if (NT_SUCCESS(status)) { - - NT_ASSERT(group); - - group->MaxPRRetryTimeDuringStateTransition = maxPRRetryTimeDuringStateTransition; - - if (alua == DSM_DEVINFO_ALUA_NOT_SUPPORTED) { - - // - // Since the device doesn't support ALUA, it is automatically - // symmetric LU access. - // - group->Symmetric = TRUE; - - if (newGroup) { - - // - // This is the first in the group, so make it the active device. - // The actual active/passive devices will be set-up when - // LB policies are set by the user. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - } else { - - // - // Already something active, this will be the fail-over device - // until the load-balance groups are set-up. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_STANDBY; - } - - } else { - - if (DeviceIdList == NULL) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): No Device ID List.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - if (alua == DSM_DEVINFO_ALUA_IMPLICIT) { - - // - // Assume that the LU access is symmetric. When parsing the TPG - // info, if we find that not all TPGs are in the same LU access - // state, then we know that this the access is asymmetric. - // - group->Symmetric = TRUE; - } - - // - // Build TPG and TP info - // - status = DsmpParseTargetPortGroupsInformation(DsmContext, - group, - targetPortGroupsInfo, - targetPortGroupsInfoLength); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to build TPG information - status %x.\n", - TargetDevice, - status)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - for (index = 0; index < DSM_MAX_PATHS; index++) { - - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup; - - targetPortGroup = group->TargetPortGroupList[index]; - - if (targetPortGroup) { - - DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); - } - } - - // - // Find the target port through which this devInfo was exposed. - // - relativeTargetPortId = (PULONG)DsmpParseDeviceID(DeviceIdList, - DSM_DEVID_RELATIVE_TARGET_PORT, - NULL, - NULL, - FALSE); - NT_ASSERT(relativeTargetPortId); - - if (!relativeTargetPortId) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Couldn't retrieve relative TP id.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // Find the target port group - // - targetPortGroupId = (PUSHORT)DsmpParseDeviceID(DeviceIdList, - DSM_DEVID_TARGET_PORT_GROUP, - NULL, - NULL, - FALSE); - NT_ASSERT(targetPortGroupId); - - if (targetPortGroupId) { - - // - // Find the target port group entry - // - targetPortGroupEntry = DsmpFindTargetPortGroup(DsmContext, - group, - targetPortGroupId); - - NT_ASSERT(targetPortGroupEntry); - - if (targetPortGroupEntry) { - - // - // Look through the target port group to find the target port - // - targetPortEntry = DsmpFindTargetPort(DsmContext, - targetPortGroupEntry, - relativeTargetPortId); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Couldn't find TPG Id %x's entry.\n", - TargetDevice, - *targetPortGroupId)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - NT_ASSERT(targetPortEntry); - - if (!targetPortEntry) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Couldn't find relative TP %x's entry.\n", - TargetDevice, - *relativeTargetPortId)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // Update the devInfo with the target port and target port group - // info - // - deviceInfo->TargetPortGroup = targetPortGroupEntry; - deviceInfo->TargetPort = targetPortEntry; - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = deviceInfo->ALUAState = deviceInfo->TargetPortGroup->AsymmetricAccessState; - - tp_device = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_TARGET_PORT_DEVICELIST_ENTRY), - DSM_TAG_TP_DEVICE_LIST_ENTRY); - - if (!tp_device) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Insufficient resources allocating TP device list entry.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - - // - // Add the device to the list of devices that are exposed via this target port. - // - tp_device->DeviceInfo = deviceInfo; - InterlockedIncrement((LONG volatile*)&targetPortEntry->Count); - InsertTailList(&targetPortEntry->TP_DeviceList, &tp_device->ListEntry); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to retrieve TPG Id.\n", - TargetDevice)); - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - } - - if (NT_SUCCESS(status)) { - - // - // Add the deviceInfo to the list. DO NOT modify the status - // variable if this function returns SUCCESS. - // - status = DsmpAddDeviceEntry(DsmContext, - group, - deviceInfo); - if (NT_SUCCESS(status)) { - - *DsmIdentifier = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Added device %p to group %p.\n", - TargetDevice, - *DsmIdentifier, - group)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to add device %p to group %p - status %x.\n", - TargetDevice, - deviceInfo, - group, - status)); - - // - // We weren't able to add this deviceInfo to the list so we must - // remove its entry on the target port list before the deviceInfo - // is freed. - // - DsmpRemoveDeviceFromTargetPortList(deviceInfo); - - if (newGroup) { - - DsmpRemoveGroupEntry(DsmContext, group, FALSE); - - DsmpFreePool(group); - group = NULL; - } - - status = STATUS_NOT_SUPPORTED; - goto __Exit_DsmInquire; - } - } - } - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - spinlockHeld = FALSE; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Device %p added. State %d, Desired State %d\n", - TargetDevice, - deviceInfo, - deviceInfo->State, - deviceInfo->DesiredState)); - - // - // Update the global list of controller objects - // - controllerObjects = DsmGetAssociatedDevice(dsmContext->MPIOContext, - PortObject, - 0x0C); - if (controllerObjects) { - - // - // This loop needs its own status variable so that it does not - // inadvertently overwrite a STATUS_SUCCESS from the code above. - // - NTSTATUS matchStatus = STATUS_SUCCESS; - PSCSI_ADDRESS controllerScsiAddress = NULL; - - // - // Walk through the list and get VPD 0x83 data and associate the devInfo - // with the controller object. - // - for (index = 0; index < controllerObjects->Count; index++) { - - STORAGE_IDENTIFIER_CODE_SET codeSet = StorageIdCodeSetReserved; - - // - // Free the previously allocated SCSI address, if any. - // - if (controllerScsiAddress) { - DsmpFreePool(controllerScsiAddress); - controllerScsiAddress = NULL; - } - - controllerDeviceObject = (PDEVICE_OBJECT)controllerObjects->IdList[index]; - NT_ASSERT(controllerDeviceObject); - - if (!controllerDeviceObject) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Controller list %p's index %x is NULL.\n", - TargetDevice, - controllerObjects, - index)); - - continue; - } - - matchStatus = DsmpGetDeviceIdList(controllerDeviceObject, &controllerIdHeader); - NT_ASSERT(NT_SUCCESS(matchStatus)); - - if (!NT_SUCCESS(matchStatus)) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to get DeviceId list for controller %p - status %x.\n", - TargetDevice, - controllerDeviceObject, - matchStatus)); - - continue; - } - - controllerSerialNumber = DsmpParseDeviceID((PSTORAGE_DEVICE_ID_DESCRIPTOR)controllerIdHeader, - DSM_DEVID_SERIAL_NUMBER, - NULL, - &codeSet, - FALSE); - NT_ASSERT(controllerSerialNumber); - DsmpFreePool(controllerIdHeader); - - if (!controllerSerialNumber) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to parse serial number for controller %p.\n", - TargetDevice, - controllerDeviceObject)); - - continue; - } - - // - // Note that on success, DsmGetScsiAddress() will allocate memory - // which we are responsible for freeing. - // - matchStatus = DsmGetScsiAddress(controllerDeviceObject, &controllerScsiAddress); - NT_ASSERT(NT_SUCCESS(matchStatus)); - - if (!NT_SUCCESS(matchStatus)) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to get controller %p's scsi address - status %x.\n", - TargetDevice, - controllerDeviceObject, - matchStatus)); - - continue; - } - - controllerEntry = DsmpFindControllerEntry(DsmContext, - PortObject, - controllerScsiAddress, - controllerSerialNumber, - strlen(controllerSerialNumber), - codeSet, - TRUE); - - if (!controllerEntry) { - - controllerEntry = DsmpBuildControllerEntry(DsmContext, - controllerDeviceObject, - PortObject, - controllerScsiAddress, - controllerSerialNumber, - codeSet, - TRUE); - - if (!controllerEntry) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to build an entry for controller %p.\n", - TargetDevice, - controllerDeviceObject)); - - continue; - } - - InsertHeadList(&dsmContext->ControllerList, &controllerEntry->ListEntry); - InterlockedIncrement((LONG volatile*)&dsmContext->NumberControllers); - } - - controllerEntry->DeviceObject = controllerDeviceObject; - - // - // Parse the DeviceIdList for all the 0x5 type identifiers - // and for each, compare the target port groups and target ports to match - // the device to its controller. - // - if (!match) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Failed to match devInfo %p with controller %p's Ids.\n", - TargetDevice, - deviceInfo, - controllerDeviceObject)); - - match = DsmpIsDeviceBelongsToController(DsmContext, - deviceInfo, - controllerEntry); - } - - if (match && !doneUpdating) { - - InterlockedIncrement((LONG volatile*)&(controllerEntry->RefCount)); - deviceInfo->Controller = controllerEntry; - doneUpdating = TRUE; - } - } - - // - // Free the last SCSI address allocated in the loop, if any. - // - if (controllerScsiAddress) { - DsmpFreePool(controllerScsiAddress); - controllerScsiAddress = NULL; - } - } - - // - // If there was no controller to associate this device with, use a fake one. - // Note that we only really care about matching on the Port and Target - // portions of the SCSI address. - // - if (!deviceInfo->Controller) { - - for (entry = dsmContext->ControllerList.Flink; - entry != &dsmContext->ControllerList; - entry = entry->Flink) { - - controllerEntry = CONTAINING_RECORD(entry, DSM_CONTROLLER_LIST_ENTRY, ListEntry); - - if ((controllerEntry->IsFakeController) && - (controllerEntry->ScsiAddress->PortNumber == deviceInfo->ScsiAddress->PortNumber) && - (controllerEntry->ScsiAddress->TargetId == deviceInfo->ScsiAddress->TargetId)) { - - fakeControllerEntryExists = TRUE; - break; - } - } - - // - // If no fake one exists as yet for this port FDO, create one now. - // - if (!fakeControllerEntryExists) { - - CHAR fakeControllerSerialNumber[] = "FakeController"; - SCSI_ADDRESS fakeControllerScsiAddress = {0}; - fakeControllerScsiAddress.PortNumber = deviceInfo->ScsiAddress->PortNumber; - fakeControllerScsiAddress.TargetId = deviceInfo->ScsiAddress->TargetId; - - controllerEntry = DsmpBuildControllerEntry(DsmContext, - NULL, - PortObject, - &fakeControllerScsiAddress, - fakeControllerSerialNumber, - StorageIdCodeSetBinary, - TRUE); - - if (controllerEntry) { - - InsertHeadList(&dsmContext->ControllerList, &controllerEntry->ListEntry); - InterlockedIncrement((LONG volatile*)&dsmContext->NumberControllers); - controllerEntry->IsFakeController = TRUE; - } - } - - if (controllerEntry) { - InterlockedIncrement((LONG volatile*)&(controllerEntry->RefCount)); - } - - deviceInfo->Controller = controllerEntry; - } - -__Exit_DsmInquire: - - if (spinlockHeld) { - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - } - - if (NT_SUCCESS(status)) { - - NT_ASSERT(*DsmIdentifier); - - } else { - - // - // If there was any sort of ERROR, the deviceInfo will NOT be put on - // MSDSM's internal list that is accessible to other threads. Thus, - // we are safe to free the memory below and we do not require any - // synchronization mechanism to do so. - // - - // - // Check to see whether the serial number buffer was allocated, or just - // an offset into the Descriptor. - // - if (serialNumberAllocated) { - - // - // Need to free this before returning. - // - DsmpFreePool(serialNumber); - } - - if (deviceInfo) { - - if (deviceInfo->ScsiAddress) { - DsmpFreePool(deviceInfo->ScsiAddress); - } - - DsmpFreePool(deviceInfo); - } - } - - // - // If deviceName is not NULL then it hasn't been assigned to any GROUP. - // Free the allocated memory. - // - if (deviceName) { - DsmpFreePool(deviceName); - } - - // - // If hardwareId is not NULL then it hasn't been assigned to any GROUP. - // Free the allocated memory. - // - if (hardwareId) { - DsmpFreePool(hardwareId); - } - - if (targetPortGroupsInfo) { - DsmpFreePool(targetPortGroupsInfo); - } - - if (relativeTargetPortId) { - DsmpFreePool(relativeTargetPortId); - } - - if (targetPortGroupId) { - DsmpFreePool(targetPortGroupId); - } - - if (controllerObjects) { - DsmpFreePool(controllerObjects); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmInquire (DevObj %p): Exiting function with status %x.\n", - TargetDevice, - status)); - - return status; -} - - -BOOLEAN -DsmCompareDevices( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId1, - _In_ IN PVOID DsmId2 - ) -/*++ - -Routine Description: - - This routine is called to determine if the device ids represent - the same underlying physical device. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - DsmId1/2 - Identifers returned from DMS_INQUIRE_DRIVER. - -Return Value: - - TRUE if DsmIds correspond to the same underlying device. - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo0 = DsmId1; - PDSM_DEVICE_INFO deviceInfo1 = DsmId2; - PSTR serialNumber0; - PSTR serialNumber1; - SIZE_T length; - BOOLEAN match = FALSE; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmCompareDevices (DevInfo %p): Entering function - comparing with %p.\n", - deviceInfo0, - deviceInfo1)); - - // - // Get the two serial numbers. They were either embedded in - // the STORAGE_DEVICE_DESCRIPTOR or built by directly issuing - // the VPD request. - // - serialNumber0 = deviceInfo0->SerialNumber; - serialNumber1 = deviceInfo1->SerialNumber; - - if (serialNumber0 && serialNumber1) { - - // - // Get the length of the base-device Serial Number. - // - length = strlen((const char*)serialNumber0); - - // - // If the lengths match, compare the contents. - // - if (length == strlen((const char*)serialNumber1)) { - - if (RtlEqualMemory(serialNumber0, serialNumber1, length)) { - match = TRUE; - } - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmCompareDevices (DevInfo %p): Serialnumber not assigned for %p and\\or %p.\n", - DsmId1, - deviceInfo0, - deviceInfo1)); - } - - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmCompareDevices (DevInfo %p): Exiting function with match = %!bool!.\n", - DsmId1, - match)); - - return match; -} - - -NTSTATUS -DsmGetControllerInfo( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN ULONG Flags, - _Inout_ IN OUT PCONTROLLER_INFO *ControllerInfo - ) -/*++ - -Routine Description: - - This routine is used to get information about the controller that - the device corresponding to DsmId in on. Currently this DSM controls - hardware that doesn't expose controllers directly. Therefore State - is always NO_CNTRL. This information is used mainly by whatever - WMI admin utilities want it. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - - DsmId - Value returned from DMSInquireDriver. - - Flags - Bitfield of modifiers. If ALLOCATE is not set, ControllerInfo - will have a valid buffer for the DSM to operate on. - - ControllerInfo - Pointer for the DSM to place the allocated controller - info pertaining to DsmId - -Return Value: - - STATUS_INSUFFICIENT_RESOURCES if memory allocation fails. - - STATUS_SUCCESS on success - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo = DsmId; - PDSM_CONTROLLER_LIST_ENTRY controllerEntry = deviceInfo->Controller; - PCONTROLLER_INFO controllerInfo = NULL; - LARGE_INTEGER time; - ULONG controllerId = 0; - NTSTATUS status = STATUS_SUCCESS; - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmGetControllerInfo (DevInfo %p): Entering function.\n", - DsmId)); - - // - // Check to see whether a controller id has already been made-up. - // - if (!controllerEntry) { - - // - // Since this device is in an enclosure that doesn't have controllers, - // e.g. JBOD, make one up. - // - KeQuerySystemTime(&time); - - // - // Use only the lower 32-bits. - // - controllerId = time.LowPart; - } - - // - // Check the Flags - // - if (Flags & DSM_CNTRL_FLAGS_ALLOCATE) { - - // - // This is the first call. Need to allocate the controller structure. - // - controllerInfo = DsmpAllocatePool(NonPagedPoolNx, - sizeof(CONTROLLER_INFO), - DSM_TAG_CTRL_INFO); - if (!controllerInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmGetControllerInfo (DevInfo %p): Failed to allocate memory for Controller Info\n", - DsmId)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmGetControllerInfo; - } - - if (!controllerEntry) { - - // - // Indicate that there are no specific controllers. - // - controllerInfo->State = DSM_CONTROLLER_NO_CNTRL; - - // - // Set the identifier to the value generated earlier. - // Indicate that it's Binary, not ASCII. - // - controllerInfo->Identifier.Type = StorageIdCodeSetBinary; - controllerInfo->Identifier.Length = 8; - - RtlCopyMemory(controllerInfo->Identifier.SerialNumber, - &controllerId, - sizeof(controllerId)); - - } else { - - // - // If either implicit or explicit ALUA state transition is supported, - // every controller is active. Else, if the devInfo's is in Active - // state, the controller is obviously in the active state. - // - if ((deviceInfo->ALUASupport != DSM_DEVINFO_ALUA_NOT_SUPPORTED) || - (DsmpIsDeviceStateActive(deviceInfo->State))) { - - controllerInfo->State = DSM_CONTROLLER_ACTIVE; - - } else { - - controllerInfo->State = DSM_CONTROLLER_STANDBY; - } - - controllerInfo->Identifier.Type = controllerEntry->IdCodeSet; - controllerInfo->Identifier.Length = controllerEntry->IdLength; - - if (controllerInfo->Identifier.Length > 32) { - - controllerInfo->Identifier.Length = 32; - } - - RtlCopyMemory(controllerInfo->Identifier.SerialNumber, - controllerEntry->Identifier, - controllerInfo->Identifier.Length); - - controllerInfo->DeviceObject = controllerEntry->DeviceObject; - } - - *ControllerInfo = controllerInfo; - - } else if (Flags & DSM_CNTRL_FLAGS_CHECK_STATE) { - - // - // Get the passed in struct. - // - controllerInfo = *ControllerInfo; - - // - // If the enclosures supported by this DSM actually had controllers, - // there would be a list of them and a search based on - // ControllerIdentifier would be made. - // - controllerEntry = deviceInfo->Controller; - - if (!controllerEntry) { - - controllerInfo->State = DSM_CONTROLLER_NO_CNTRL; - - } else { - - // - // If either implicit or explicit ALUA state transition is supported, - // every controller is active. Else, if the devInfo's is in Active - // state, the controller is obviously in the active state. - // - if ((deviceInfo->ALUASupport != DSM_DEVINFO_ALUA_NOT_SUPPORTED) || - (DsmpIsDeviceStateActive(deviceInfo->State))) { - - controllerInfo->State = DSM_CONTROLLER_ACTIVE; - - } else { - - controllerInfo->State = DSM_CONTROLLER_STANDBY; - } - } - } - -__Exit_DsmGetControllerInfo: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmGetControllerInfo (DevInfo %p): Exiting function with status %x.\n", - DsmId, - status)); - - return status; -} - - -NTSTATUS -DsmSetDeviceInfo( - _In_ IN PVOID DsmContext, - _In_ IN PDEVICE_OBJECT TargetObject, - _In_ IN PVOID DsmId, - _Inout_ IN OUT PVOID *PathId - ) -/*++ - -Routine Description: - - This routine associates the DsmId to the controlling MPDisk PDO, - the targetObject for DSM-initiated requests, and to a Path - (given by PathId). - This routine will update the PathId in a way that better explains - the topology to MPIO. - Additionally, if we are in failover LB policy, failback if this - path is preferred path. - Also, if PR is being used, send registration down this path. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - TargetObject - The D.O. to which DSM-initiated requests should be sent. - DsmId - Value returned from DMSInquireDriver. - PathId - Id that represents the path. The value passed in may be used - as is, or the DSM optionally can update it if it requires - additional state info to be kept. - -Return Value: - - INSUFFICENT_RESOURCES for no-mem conditions. - STATUS_SUCCESS - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo = DsmId; - PDSM_GROUP_ENTRY group = deviceInfo->Group; - PDSM_FAILOVER_GROUP failGroup; - PDSM_CONTEXT dsmContext; - PSCSI_ADDRESS scsiAddress; - ULONG primaryPath = 0; - ULONG optimizedPath = 0; - ULONG pathWeight = 0; - ULONG pathId; - NTSTATUS status = STATUS_SUCCESS; - WCHAR registryKeyName[256] = {0}; - BOOLEAN newFOGroup = FALSE; - BOOLEAN registryKeyExists = FALSE; - KIRQL irql; - PVOID tempPathId = *PathId; - DSM_LOAD_BALANCE_TYPE loadBalanceType; - ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - UCHAR explicitlySet = FALSE; - BOOLEAN vidpidPolicySet = FALSE; - BOOLEAN overallPolicySet = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Entering function.\n", - DsmId)); - - // - // 1. Set default LB policy. - // 2. Query LB policy from registry and update if necessary. - // 3. Set default value for primaryPath and optimizedPath based on device's - // access state - // 4. Map deviceInfo to real LUN by saving off the target for I/O - // 5. Build pathId from SCSI address - // 6. Find FOG for device. If none found, build one. - // Add deviceInfo to FOG. - // 7. Query registry for pathWeight, primaryPath and optimizedPath - // Update deviceInfo with results of query. - // 8. Compare deviceInfo access state with persistent value (based on - // primaryPath and optimizedPath) and update its DesiredState. - // - - if (!TargetObject) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): No target object.\n", - deviceInfo)); - - // - // This deviceInfo will have no path or targetObject associated with it. - // Mark it in a failed state so it won't be used to handle any requests. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_UNDETERMINED; - - goto __Exit_DsmSetDeviceInfo; - } - - // - // Default LB type is Round Robin. - // - loadBalanceType = DSM_LB_ROUND_ROBIN; - - // - // Override the default with whatever is the overall policy that needs to be - // applied for all LUNs controlled by MSDSM. - // - // Override that policy if one has been set for this device's VID/PID. - // - // Override that policy with whatever has been explicitly set for this particular - // device. - // - // In order to perform the above, first query the policy for this particular device. - // If it has not been explicity set, use MSDSM's overall policy or VID/PID policy. - // - status = DsmpQueryDeviceLBPolicyFromRegistry(deviceInfo, - group->RegistryKeyName, - &loadBalanceType, - &preferredPath, - &explicitlySet); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Failed to query LB policy from registry. Status %x.\n", - deviceInfo, - status)); - - NT_ASSERT(NT_SUCCESS(status)); - - // - // This deviceInfo will have no path or targetObject associated with it. - // Mark it in a failed state so it won't be used to handle any requests. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_UNDETERMINED; - - goto __Exit_DsmSetDeviceInfo; - } - - // - // If this device's policy was not explicitly set, check to see if a policy - // was set for this device's VID/PID and use that. - // If VID/PID policy is not set, query the overall default policy - // that needs to be applied to all devices controlled by this DSM. - // If this setting hasn't been set, we'll fall back to using the default that was - // determined based on the storage's ALUA capabilities. - // - if (!explicitlySet) { - - status = DsmpQueryTargetLBPolicyFromRegistry(deviceInfo, - &loadBalanceType, - &preferredPath); - - if (NT_SUCCESS(status)) { - - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_VID_PID; - vidpidPolicySet = TRUE; - - } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - - // - // Since the policy hasn't been set for this VID/PID, check if - // overall MSDSM-wide policy has been set. - // - status = DsmpQueryDsmLBPolicyFromRegistry(&loadBalanceType, - &preferredPath); - if (NT_SUCCESS(status)) { - - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; - overallPolicySet = TRUE; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Failed to query Dsm overall LB policy from registry. Status %x.\n", - deviceInfo, - status)); - - NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); - status = STATUS_SUCCESS; - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Failed to query VID/PID LB policy from registry. Status %x.\n", - deviceInfo, - status)); - - NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); - status = STATUS_SUCCESS; - } - } else { - - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT; - } - - if (!explicitlySet && !vidpidPolicySet && !overallPolicySet) { - - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; - - } - - // - // If ALUA is enabled and the load balance policy is set to Round Robin, - // we need to set it to Round Robin with Subset instead. - // - if (!DsmpIsSymmetricAccess(deviceInfo) && loadBalanceType == DSM_LB_ROUND_ROBIN) { - loadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; - } - - group->LoadBalanceType = loadBalanceType; - group->PreferredPath = preferredPath; - dsmContext = (PDSM_CONTEXT) DsmContext; - - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - - // - // Save the registry key name under which Load balance policies - // are stored. This will be used to query the LB policy later. - // - if (group->RegistryKeyName) { - - registryKeyExists = TRUE; - - if (!NT_SUCCESS(RtlStringCchCopyNW(registryKeyName, - sizeof(registryKeyName) / sizeof(registryKeyName[0]), - group->RegistryKeyName, - ((sizeof(registryKeyName) / sizeof(registryKeyName[0])) - sizeof(WCHAR))))) { - - registryKeyName[(sizeof(registryKeyName) / sizeof(registryKeyName[0])) - 1] = L'\0'; - } - } - - // - // TargetObject is the destination for any requests created by this driver. - // Save this for future reference. - // - deviceInfo->TargetObject = TargetObject; - - // - // Set the PathId - All devices on the same PathId will - // failover together. Currently the pathId is constructed - // from Port Number, Bus Number, and Target Id of the device. - // - scsiAddress = deviceInfo->ScsiAddress; - NT_ASSERT(scsiAddress); - - pathId = 0x77; - pathId <<= 8; - pathId |= scsiAddress->PortNumber; - pathId <<= 8; - pathId |= scsiAddress->PathId; - pathId <<= 8; - pathId |= scsiAddress->TargetId; - - *PathId = ((PVOID)((ULONG_PTR)(pathId))); - - // - // PathId indicates the path on which this device resides. Meaning - // that when a Fail-Over occurs all device's on the same path fail - // together. Search for a matching F.O. Group - // - failGroup = DsmpFindFOGroup(DsmContext, *PathId); - - // - // If not found, create a new failover group - // - if (!failGroup) { - - failGroup = DsmpBuildFOGroup(DsmContext, deviceInfo, PathId); - - if (failGroup) { - - newFOGroup = TRUE; - failGroup->MPIOPath = tempPathId; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Failed to build FO Group.\n", - DsmId)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) { - - // - // If this path is in the midst of failover processing, mark it as "good" - // again. - // - failGroup->State = DSM_FG_NORMAL; - - // - // add this deviceInfo to the f.o. group. - // - status = DsmpUpdateFOGroup(DsmContext, failGroup, deviceInfo); - NT_ASSERT(NT_SUCCESS(status)); - } - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - - if (NT_SUCCESS(status)) { - - if (registryKeyExists) { - - NTSTATUS queryStatus = STATUS_INVALID_PARAMETER; - ULONGLONG pathId64; - - // - // If the overall default policy or a target-level policy has been set and - // this device's policy has not been explicitly set, there's no use querying - // its individual path (desired) states. - // - if ((!overallPolicySet && !vidpidPolicySet) || (explicitlySet)) { - - // - // Created a new failover group. Query the LB policy - // for this device from registry. - // - pathId64 = (ULONGLONG)((ULONG_PTR)*PathId); - - queryStatus = DsmpQueryLBPolicyForDevice(registryKeyName, - pathId64, - loadBalanceType, - &primaryPath, - &optimizedPath, - &pathWeight); - } - - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - - if (NT_SUCCESS(queryStatus)) { - - deviceInfo->PathWeight = pathWeight; - - // - // If device doesn't support ALUA, update the device state - // based on the primary path info in the registry. - // - if (DsmpIsSymmetricAccess(deviceInfo)) { - - if (primaryPath) { - - deviceInfo->DesiredState = DSM_DEV_ACTIVE_OPTIMIZED; - - } else { - - deviceInfo->DesiredState = DSM_DEV_STANDBY; - } - - } else { - - DSM_DEVICE_STATE devState; - - if (primaryPath) { - - devState = optimizedPath ? DSM_DEV_ACTIVE_OPTIMIZED : DSM_DEV_ACTIVE_UNOPTIMIZED; - - } else { - - devState = optimizedPath ? DSM_DEV_STANDBY : DSM_DEV_UNAVAILABLE; - } - - // - // For ALUA, desired state makes sense for FOO. - // For RRWS, we assume desired state was explicitly selected - // by Admin if the ALUA state is different from the path - // state. Only under such cases would the path state have - // been saved in registry. - // In all other policies, state must just match the TPG state. - // - if (group->LoadBalanceType == DSM_LB_FAILOVER || - group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { - - deviceInfo->DesiredState = devState; - - } else { - - deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; - } - } - } else if (queryStatus == STATUS_OBJECT_NAME_NOT_FOUND) { - - deviceInfo->PathWeight = pathWeight; - deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; - - } else { - - deviceInfo->PathWeight = 0; - deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; - } - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - } - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): PathWeight %x, DesiredState %x, State %x, PrevState %x.\n", - deviceInfo, - deviceInfo->PathWeight, - deviceInfo->DesiredState, - deviceInfo->State, - deviceInfo->PreviousState)); - - if (NT_SUCCESS(status)) { - - deviceInfo->Initialized = TRUE; - - } else if (!NT_SUCCESS(status) && newFOGroup) { - - // - // This deviceInfo will have no path associated with it. - // Mark it in a failed state so it won't be used to handle any requests. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_UNDETERMINED; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): No path associated with instance. Changing state from %u to %u.\n", - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - - DsmpRemoveDeviceFailGroup(DsmContext, failGroup, deviceInfo, TRUE); - - if (failGroup->Count == 0) { - - // - // Yank it from the list. - // - RemoveEntryList(&failGroup->ListEntry); - InterlockedDecrement((LONG volatile*)&dsmContext->NumberFOGroups); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Removing FOGroup %p with path %p. Count of FOGroups %d.\n", - DsmId, - failGroup, - failGroup->PathId, - dsmContext->NumberFOGroups)); - - // - // Free the zombie group list and then the failover group. - // - DsmpFreeZombieGroupList(failGroup); - DsmpFreePool(failGroup); - } - } - -__Exit_DsmSetDeviceInfo: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmSetDeviceInfo (DevInfo %p): Exiting function with status %x.\n", - DsmId, - status)); - - return status; -} - - -BOOLEAN -DsmIsPathActive( - _In_ IN PVOID DsmContext, - _In_ IN PVOID PathId, - _In_ IN PVOID DsmId - ) -/*++ - -Routine Description: - - This routine is used to determine whether the path to DsmId is usable - (ie. able to handle requests without a failover). - - Also, after a failover, the path validity will be queried. - If the path error was transitory and the DSM feels that the path is good, - then this request will be re-issued to determine whether it is usable. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - PathId - Value set in SetPathId. - DsmId - DSM Id returned during DsmInquire. - -Return Value: - - TRUE if the path is active. FALSE otherwise. ---*/ -{ - PDSM_FAILOVER_GROUP foGroup; - PDSM_DEVICE_INFO deviceInfo = DsmId; - PDSM_GROUP_ENTRY group = deviceInfo->Group; - PDSM_CONTEXT dsmContext = (PDSM_CONTEXT) DsmContext; - KIRQL irql; - BOOLEAN retVal; - ULONG SpecialHandlingFlag = 0; - - // - // 1. If PR and reserved by this node, register the PR keys. - // 2. Find the FOG for the passed in PathId - // 3. Depending on the LB policy, set the appropriate devInfo states - // If FailOver, and DesiredState is AO, change the active - // devInfos to non-active state and make this one AO. - // If ALUA supported, send down SetTPG to make this change, - // else directly make the change. - // If RR/LWP/LQD, make this DevInfo ActiveOptimized. - // If RRS, and DesiredState is AO, change the active devInfos to - // their desired states and then make this one AO. - // If DesiredState is not AO, find a devInfo in AO state. If - // one is found, make this devInfo's state its desired state, - // else if one isn't found, make this one AO. - // 3. If this is preferredPath, and LB policy is failover-only, change the - // access state of deviceInfo to AO. - // If there is another devInfo currently in AO, change its state too. - // If ALUA supported, send down SetTPG to make these changes. - // 4. Get the appropriate AO DeviceInfo and mark the group's PTBU to its - // pathId. - // - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): Entering function.\n", - DsmId)); - - // - // Initialize this instance to be usable so that during the possible processing - // of PR register, this device can be a candidate for certain kind of requests. - // - deviceInfo->Usable = TRUE; - - // - // New path arriving. If this Node owns the reservation register this path. - // - if (group->PRKeyValid) { - - NTSTATUS prRegStatus; - ULONG i; - PDSM_DEVICE_INFO devInfo; - ULONG ordinal; - - prRegStatus = DsmpRegisterPersistentReservationKeys(deviceInfo, TRUE); - - deviceInfo->RegisterServiced = TRUE; - - if (NT_SUCCESS(prRegStatus)) { - - deviceInfo->PRKeyRegistered = TRUE; - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): Failed (status %x) to register PR key\n", - deviceInfo, - prRegStatus)); - } - - for (i = 0; i < group->NumberDevices; i++) { - - devInfo = group->DeviceList[i]; - if (devInfo && devInfo == deviceInfo) { - - ordinal = (1 << i); - group->ReservationList |= ordinal; - break; - } - } - } - - - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - - // - // Get the F.O. Group information. - // - foGroup = DsmpFindFOGroup(DsmContext, PathId); - - // - // If there are any devices on this path, and it's not in a failed state - // it's capable of handling requests. So it's active. - // - if ((foGroup) && - (foGroup->Count) && - (foGroup->State == DSM_FG_NORMAL)) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): Path %p is usable.\n", - DsmId, - PathId)); - - retVal = TRUE; - - // - // Update the next path to be used for the group if it not set already. - // - deviceInfo = (PDSM_DEVICE_INFO)DsmId; - - group = deviceInfo->Group; - DSM_ASSERT(group != NULL); - DSM_ASSERT(group->GroupSig == DSM_GROUP_SIG); - - // - // If an invalidated path came back online before PnP removes came in, - // then MPIO's path recovery thread would have sent down a PathVerify - // just moments before by which we changed the state of the FOG to - // normal. Now it is time to change the deviceInfo's state to a "good" - // state. - // - if (deviceInfo->State >= DSM_DEV_FAILED) { - - DSM_ASSERT(deviceInfo->State == DSM_DEV_INVALIDATED); - - if (DsmpIsSymmetricAccess(deviceInfo)) { - - // - // Mark it as AO. The SetLBForPathArrival will update the state - // appropriately. - // - deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - - } else { - - // - // Set it to the state that was reported during the last RTPG - // call that was made. - // - deviceInfo->State = deviceInfo->ALUAState; - } - } - - if (DsmpIsSymmetricAccess(deviceInfo)) { - - DsmpSetLBForPathArrival(DsmContext, deviceInfo, SpecialHandlingFlag); - - } else { - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - DsmpSetLBForPathArrivalALUA(DsmContext, deviceInfo, SpecialHandlingFlag); - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): State set to %d\n", - deviceInfo, - deviceInfo->State)); - - if (group->PathToBeUsed == NULL) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): Will set PathToBeUsed for %p\n", - deviceInfo, - group)); - - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess(deviceInfo), - SpecialHandlingFlag); - if (deviceInfo != NULL) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): FOG %p set for PathToBeUsed for %p\n", - deviceInfo, - deviceInfo->FailGroup, - group)); - - InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): No active/alternative path available for group %p\n", - DsmId, - group)); - - InterlockedExchangePointer(&(group->PathToBeUsed), NULL); - } - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): Path %p is NOT usable.\n", - DsmId, - PathId)); - - retVal = FALSE; - } - - ((PDSM_DEVICE_INFO)DsmId)->Usable = retVal; - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmIsPathActive (DevInfo %p): Exiting function with retVal = %!bool!.\n", - DsmId, - retVal)); - - return retVal; -} - - -NTSTATUS -DsmPathVerify( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PVOID PathId - ) -/*++ - -Routine Description: - - This routine ensures that the path to the device indicated by DsmId - is healthy. It's called periodically by the bus driver, and also - after a fail-over condition has been dealt with to ensure that - the path is able to handle requests. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - DsmId - Value returned from DMSInquire. - PathId - Value set in SetPathId. - -Return Value: - - NTSTATUS ---*/ - -{ - PDSM_CONTEXT dsmCtxt = (PDSM_CONTEXT) DsmContext; - PDSM_DEVICE_INFO deviceInfo = DsmId; - PDSM_FAILOVER_GROUP foGroup; - NTSTATUS status = STATUS_UNSUCCESSFUL; - BOOLEAN found = FALSE; - KIRQL irql; - PLIST_ENTRY entry; - PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry = NULL; - PDSM_GROUP_ENTRY group = deviceInfo->Group; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmPathVerify (DevInfo %p): Entering function.\n", - DsmId)); - - if (DsmpIsDeviceInitialized(deviceInfo)) { - - irql = ExAcquireSpinLockExclusive(&(dsmCtxt->DsmContextLock)); - - // - // Get the failover group - // - foGroup = DsmpFindFOGroup(DsmContext, PathId); - - if (foGroup) { - - // - // Find the device. - // - for (entry = foGroup->FOG_DeviceList.Flink; - entry != &foGroup->FOG_DeviceList; - entry = entry->Flink) { - - fogDeviceListEntry = CONTAINING_RECORD(entry, DSM_FOG_DEVICELIST_ENTRY, ListEntry); - - if (fogDeviceListEntry && fogDeviceListEntry->DeviceInfo == deviceInfo) { - - status = STATUS_SUCCESS; - found = TRUE; - - break; - } - } - } else { - - // - // This is not a good thing. It indicates that either we - // returned a bogus path to the bus-driver on a fail-over, - // or that the path evaporated between polls and PnP hasn't - // torn stuff down. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmPathVerify (DevInfo %p): Failed to find failover group for path %p.\n", - DsmId, - PathId)); - - status = STATUS_DEVICE_NOT_CONNECTED; - } - - ExReleaseSpinLockExclusive(&(dsmCtxt->DsmContextLock), irql); - - if (NT_SUCCESS(status)) { - - if (found) { - - // - // Send down TUR if ALUA is not supported. - // Else, send down ReportTargetPortGroups (sending TUR down non-A/O path will - // always result in a check condition). - // - if (deviceInfo->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmPathVerify (DevInfo %p): Sending TUR using %p to verify path %p.\n", - DsmId, - deviceInfo, - deviceInfo->FailGroup->PathId)); - - status = DsmSendTUR(deviceInfo->TargetObject); - - } else { - - // - // Check for whether we should ignore sending down an RTPG: - // Flag set indicates that this PathVerify() is happening in response to device - // arrival and can be skipped since Inquire() has just already sent down an RTPG. - // All that needs to be done is to clear the flag so that subsequent PathVerify() - // sent in response to InitiateFO will send RTPG as a ping. - // This is an optimization with the idea of helping speed up boot time, which is - // is adversely impacted, especially if there are many LUNs, each with many paths. - // - if (deviceInfo->IgnorePathVerify) { - - deviceInfo->IgnorePathVerify = FALSE; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmPathVerify (DevInfo %p): Returning success immediately since RTPG was already just sent.\n", - DsmId)); - - status = STATUS_SUCCESS; - - } else { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmPathVerify (DevInfo %p): Sending RTPG using %p to verify path %p.\n", - DsmId, - deviceInfo, - deviceInfo->FailGroup->PathId)); - - status = DsmpGetDeviceALUAState(dsmCtxt, deviceInfo, NULL); - - // - // Since this RTPG may have resulted in us losing a UA, adjust - // the states if needed. - // - if (NT_SUCCESS(status)) { - - DsmpAdjustDeviceStatesALUA(group, NULL, SpecialHandlingFlag); - } - } - } - } - - if (NT_SUCCESS(status)) { - - if (deviceInfo->State >= DSM_DEV_FAILED) { - - foGroup->State = DSM_FG_NORMAL; - deviceInfo->State = deviceInfo->LastKnownGoodState; - } - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmPathVerify (DevInfo %p): Exiting function with status %x.\n", - DsmId, - status)); - - return status; -} - - -NTSTATUS -DsmInvalidatePath( - _In_ IN PVOID DsmContext, - _In_ IN ULONG ErrorMask, - _In_ IN PVOID PathId, - _Inout_ IN OUT PVOID *NewPathId - ) -/*++ - -Routine Description: - - This routine will mark up devices as failed on PathId, and find - an appropriate path to return to MPIO. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - ErrorMask - Value returned from InterpretError. - PathId - The failing path. - NewPathId - Pointer to the new path. - -Return Value: - - NTSTATUS of the operation. - ---*/ -{ - PDSM_CONTEXT context = DsmContext; - PDSM_FAILOVER_GROUP failGroup; - PDSM_FAILOVER_GROUP newPath = NULL; - PDSM_FAILOVER_GROUP pathId; - PDSM_DEVICE_INFO deviceInfo; - LIST_ENTRY reservedDeviceList; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql; - PLIST_ENTRY entry; - PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry = NULL; - BOOLEAN lockHeld = FALSE; - - UNREFERENCED_PARAMETER(ErrorMask); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): Entering function.\n", - PathId)); - - DSM_ASSERT(ErrorMask & DSM_FATAL_ERROR); - - *NewPathId = NULL; - - InitializeListHead(&reservedDeviceList); - - irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); - lockHeld = TRUE; - - // - // Get the fail-over group corresponding to the PathId. - // - failGroup = DsmpFindFOGroup(DsmContext, PathId); - - if (!failGroup || failGroup->State == DSM_FG_FAILED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): Failed to find FailOver group.\n", - PathId)); - - status = STATUS_NO_SUCH_DEVICE; - goto __Exit_DsmInvalidatePath; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): Context %p, FOG %p failing.\n", - PathId, - DsmContext, - failGroup)); - - // - // Mark the path as failed. - // - failGroup->State = DSM_FG_FAILED; - - // - // Check to see whether the port driver and PnP removed the devices - // BEFORE the fail-over indication actually occurred. Work-around - // of several Fibre miniports. - // - if (failGroup->Count == 0) { - - // - // There are no longer any devices in this fail-over group, which means - // in order to get a back-pointer to the groups using this fail-over - // group, we need to go through the "zombie" group list. This should - // allow us to find a new path ID to return. - //Then go through failGroup->ZombieGroupList to do failover for each group. - // - PDSM_ZOMBIEGROUP_ENTRY group; - PDSM_GROUP_ENTRY groupEntry; - - // - // Initialize all the entries to indicate that they haven't been processed. - // - for (entry = failGroup->ZombieGroupList.Flink; entry != &(failGroup->ZombieGroupList); entry = entry->Flink) { - - group = CONTAINING_RECORD(entry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); - group->Processed = FALSE; - } - - // - // Since we need to drop the spin lock while processing an entry, it is possible - // that a removal in parallel frees up this entry during that time, thus making it - // impossible for us to move to the next entry in the list. - // In order to safely access each of the entries, we mark an entry as being processed - // just before dropping the spinlock, and always start processing from the beginning - // of the list, skipping over the already processed ones. - // - entry = failGroup->ZombieGroupList.Flink; - - while (entry != &(failGroup->ZombieGroupList)) { - - group = CONTAINING_RECORD(entry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); - entry = entry->Flink; - - if (!group || !group->Group || group->Processed) { - continue; - } - - group->Processed = TRUE; - groupEntry = group->Group; - - ExReleaseSpinLockExclusive(&context->DsmContextLock, irql); - lockHeld = FALSE; - - pathId = DsmpSetNewPathUsingGroup((PDSM_CONTEXT)DsmContext, groupEntry); - - if (!newPath) { - newPath = pathId; // Save off first good alternative path that we find - } - - if (!lockHeld) { - irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); - lockHeld = TRUE; - entry = failGroup->ZombieGroupList.Flink; - } - } - - if (!newPath) { - // - // This indicates that all of the devices have already been removed. - // If there were reservations outstanding, the RemoveDevice code - // should have updated them. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): Failed to find new path using zombie group list.\n", - PathId)); - } - - } else { - - - // - // Process each device in the fail-over group - // - for (entry = failGroup->FOG_DeviceList.Flink; - entry != &failGroup->FOG_DeviceList; - entry = entry->Flink) { - - fogDeviceListEntry = CONTAINING_RECORD(entry, DSM_FOG_DEVICELIST_ENTRY, ListEntry); - - if (!fogDeviceListEntry) { - continue; - } - - // - // Get the deviceInfo. - // - deviceInfo = fogDeviceListEntry->DeviceInfo; - - if (!(DsmpIsDeviceFailedState(deviceInfo->State))) { - - deviceInfo->LastKnownGoodState = deviceInfo->State; - } - - // - // Set the state of the Failing Device - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_INVALIDATED; - - InterlockedIncrement(&deviceInfo->BlockRemove); - - ExReleaseSpinLockExclusive(&(context->DsmContextLock), irql); - lockHeld = FALSE; - - pathId = DsmpSetNewPath(DsmContext, deviceInfo); - - if (!newPath) { - newPath = pathId; // Save off first good alternative path that we find - } - - if (!lockHeld) { - irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); - lockHeld = TRUE; - } - - InterlockedDecrement(&deviceInfo->BlockRemove); - } - } - - if (!newPath) { - - // - // This indicates that no acceptable paths - // were found. Return the error to mpctl. - // - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): No valid path found.\n", - PathId)); - - status = STATUS_NO_SUCH_DEVICE; - - } else { - - // - // return the new path. - // - *NewPathId = newPath->PathId; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): Returning %p as newPath.\n", - PathId, - newPath->PathId)); - } - -__Exit_DsmInvalidatePath: - - if (lockHeld) { - ExReleaseSpinLockExclusive(&(context->DsmContextLock), irql); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmInvalidatePath (PathId %p): Exiting function with status %x.\n", - PathId, - status)); - - return status; -} - - -NTSTATUS -DsmMoveDevice( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PVOID MPIOPath, - _In_ IN PVOID SuggestedPath, - _In_ IN ULONG Flags - ) -/*++ - -Routine Description: - - This routine is invoked in response to an administrative request. - The device that's associated with SuggestedPath will be made active, and the - current active device, moved to stand-by. - -Arguments: - - DsmContext - Context value given to the multipath driver during registration. - DsmIds - The collection of DSM IDs that pertain to the MPDisk. - MPIOPath - The original path value passed to SetDeviceInfo. - SuggestedPath - The path which should become the active path. - Flags - Bitmask indicating the intent of the move. - -Return Value: - - NTSTATUS - STATUS_SUCCESS, unless SuggestedPath is somehow invalid. - STATUS_INVALID_PARAMETER is ADMIN is set and the path is invalid. - ---*/ -{ - PDSM_CONTEXT context = DsmContext; - PDSM_DEVICE_INFO deviceInfo; - PDSM_FAILOVER_GROUP failGroup; - ULONG i; - NTSTATUS status; - KIRQL irql; - BOOLEAN adminRequest = FALSE; - PDSM_GROUP_ENTRY group = NULL; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmMoveDevice (DsmIds %p): Entering function - DsmContext %p MPIOPath (%p) SuggestedPath %p.\n", - DsmIds, - DsmContext, - MPIOPath, - SuggestedPath)); - - // - // Capture the value of the ADMIN flag bit. - // Currently, permanent assignment of the device to "preferred path" isn't supported. - // This driver doesn't care about the pending remove flag (currently). - // - adminRequest = (BOOLEAN)(Flags & DSM_MOVE_ADMIN_REQUEST); - - irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); - - group = ((PDSM_DEVICE_INFO)(DsmIds->IdList[0]))->Group; - - // - // Find the first active device. - // - deviceInfo = DsmpGetActivePathToBeUsed(group, - DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmIds->IdList[0]), - SpecialHandlingFlag); - - if (!deviceInfo) { - - // - // Didn't find an active device. Should LOG. - // Use the first one to piggy-back the request. - // - deviceInfo = DsmIds->IdList[0]; - } - - // - // Get the fail-over group associated with the Path. - // - failGroup = DsmpFindFOGroup(DsmContext, - SuggestedPath); - - if (!failGroup) { - - // - // The caller has made a terrible mistake. - // If it's an ADMIN request, blow it off. - // - if (adminRequest) { - status = STATUS_INVALID_PARAMETER; - } else { - - // - // Try to set another path. - // - // Note that failGroup will be NULL going into - // SetNewPath. This is OK. - // - status = STATUS_SUCCESS; - } - } else { - status = STATUS_SUCCESS; - } - - if (status == STATUS_SUCCESS) { - - // - // Set the new path, using SuggestedPath. - // - InterlockedIncrement(&deviceInfo->BlockRemove); - ExReleaseSpinLockExclusive(&context->DsmContextLock, irql); - failGroup = DsmpSetNewPath(context, - deviceInfo); - irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); - InterlockedDecrement(&deviceInfo->BlockRemove); - - // - // If we were able to make the suggested path active, that should be used. - // - for (i = 0, status = STATUS_UNSUCCESSFUL; i < DsmIds->Count && !NT_SUCCESS(status); i++) { - - deviceInfo = DsmIds->IdList[i]; - - if (deviceInfo->FailGroup == failGroup) { - - if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { - - InterlockedExchangePointer(&(group->PathToBeUsed), (PVOID)failGroup); - status = STATUS_SUCCESS; - } - } - } - } - - ExReleaseSpinLockExclusive(&(context->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmMoveDevice (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmRemovePending( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId - ) -/*++ - -Routine Description: - - This routine indicates that the device represented by DsmId will be - removed, so the deviceInfo is marked up to indicate the pending removal, - so that it won't be used. - -Arguments: - - DsmContext - Context value given to the multipath driver - during registration. - DsmId - Value referring to the failed device. - -Return Value: - - STATUS_SUCCESS - ---*/ - -{ - PDSM_CONTEXT dsmContext = DsmContext; - PDSM_DEVICE_INFO deviceInfo = DsmId; - KIRQL irql; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmRemovePending (DevInfo %p): Entering function.\n", - DsmId)); - - // - // DsmpSetNewPath then finds the next available device. This is basically a - // fail-over for just this device. - // - InterlockedIncrement(&deviceInfo->BlockRemove); - DsmpSetNewPath(DsmContext, deviceInfo); - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - InterlockedDecrement(&deviceInfo->BlockRemove); - - if (!(DsmpIsDeviceFailedState(deviceInfo->State))) { - - deviceInfo->LastKnownGoodState = deviceInfo->State; - } - - // - // Mark the device as being unavailable since remove will be sent shortly. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_REMOVE_PENDING; - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmRemovePending (DevInfo %p): Exiting function.\n", - DsmId)); - - return STATUS_SUCCESS; -} - -NTSTATUS -DsmRemoveDevice( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PVOID PathId - ) -/*++ - -Routine Description: - - The device is gone and the port pdo has been removed. This routine will - update the internal structures and free any allocations. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - DsmId - Value referring to the failed device. - PathId - The path on which the Device lives. - -Return Value: - - STATUS_SUCCESS - ---*/ - -{ - PDSM_CONTEXT dsmContext = DsmContext; - PDSM_DEVICE_INFO deviceInfo = DsmId; - KIRQL irql; - PDSM_FAILOVER_GROUP failGroup = deviceInfo->FailGroup; - PDSM_GROUP_ENTRY group = deviceInfo->Group; - LONG block; - - UNREFERENCED_PARAMETER(PathId); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmRemoveDevice (DevInfo %p): Entering function.\n", - DsmId)); - - do { - - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - block = deviceInfo->BlockRemove; - NT_ASSERT(block >= 0); - - if (block) { - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - KeStallExecutionProcessor(10000); - } - - } while (block); - - if (!(DsmpIsDeviceFailedState(deviceInfo->State))) { - - deviceInfo->LastKnownGoodState = deviceInfo->State; - } - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = DSM_DEV_REMOVED; - - // - // Decrement the reference count for this device's controller entry and - // delete the entry if its reference count is now zero. - // - if (deviceInfo->Controller) { - - if (InterlockedDecrement((LONG volatile*)&(deviceInfo->Controller->RefCount)) == 0) { - - RemoveEntryList(&(deviceInfo->Controller->ListEntry)); - DsmpFreeControllerEntry(dsmContext, deviceInfo->Controller); - deviceInfo->Controller = NULL; - InterlockedDecrement((LONG volatile*)&(dsmContext->NumberControllers)); - } - } - - // - // Ensure that the device has been fully initialized before trying to - // remove it from the FOG. If SetDeviceInfo has yet to be invoked, there - // will yet to be an association set. - // - if (failGroup) { - - // - // Remove its entry from the Fail-Over Group. - // - DsmpRemoveDeviceFailGroup(DsmContext, failGroup, deviceInfo, FALSE); - } - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - - // - // Remove it from it's multi-path group. This has the side-effect - // of cleaning up the Group if the number of devices goes to zero. - // - DsmpRemoveDeviceEntry(DsmContext, group, deviceInfo); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmRemoveDevice (DevInfo %p): Exiting function.\n", - DsmId)); - - return STATUS_SUCCESS; -} - - -NTSTATUS -DsmRemovePath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PVOID PathId - ) -/*++ - -Routine Description: - - This routine indicates that the path is no longer valid, and that it should - be removed. Internal counts will be updated and any allocations associated - with this path freed. - -Arguments: - - DsmContext - Context value given to the multipath driver during registration. - PathId - The path to remove. - -Return Value: - - NTSTATUS of the operation. - ---*/ - -{ - PDSM_FAILOVER_GROUP failGroup; - KIRQL irql; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmRemovePath (PathId %p): Entering function.\n", - PathId)); - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - failGroup = DsmpFindFOGroup(DsmContext, PathId); - - if (failGroup) { - - // - // The claim is that a path won't be removed, until all - // the devices on it are. - // - if (failGroup->Count == 0) { - - // - // Yank it from the list. - // - RemoveEntryList(&failGroup->ListEntry); - InterlockedDecrement((LONG volatile*)&DsmContext->NumberFOGroups); - - // - // Move this over to the stale FOG list if there are inflight requests. - // Otherwise free the allocation. - // - if (InterlockedCompareExchange(&failGroup->NumberOfRequestsInFlight, 0, 0) > 0) { - - failGroup->State = DSM_FG_PENDING_REMOVE; - InsertTailList(&DsmContext->StaleFailGroupList, &failGroup->ListEntry); - InterlockedIncrement((LONG volatile*)&DsmContext->NumberStaleFOGroups); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmRemovePath (PathId %p): Outstanding requests %d. Moving FOGroup %p with path %p to stale path list.\n", - PathId, - failGroup->NumberOfRequestsInFlight, - failGroup, - failGroup->PathId)); - } else { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmRemovePath (PathId %p): Removing FOGroup %p with path %p. Count of FOGroups %d.\n", - PathId, - failGroup, - failGroup->PathId, - DsmContext->NumberFOGroups)); - - // - // Free the zombie group list and then the failover group. - // - DsmpFreeZombieGroupList(failGroup); - DsmpFreePool(failGroup); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmRemovePath (PathId %p): Count %d. Not removing FOGroup %p.\n", - PathId, - failGroup->Count, - failGroup)); - - // - // Should never be here. - // - NT_ASSERT(failGroup->Count == 0); - } - } else { - - // - // It's already been removed. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmRemovePath (PathId %p): Did not find the FO group.\n", - PathId)); - - NT_ASSERT(failGroup); - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmRemovePath (PathId %p): Exiting function.\n", - PathId)); - - return STATUS_SUCCESS; -} - - -PVOID -DsmLBGetPath( - _In_ IN PVOID DsmContext, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PDSM_IDS DsmList, - _In_ IN PVOID CurrentPath, - _Out_ OUT NTSTATUS *Status - ) -/*++ - -Routine Description: - - This routine is used by mpio to handle load-balancing. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - Srb - The current read/write Srb. - DsmList - List of our DSM IDs. - CurrentPath - The last path that was returned for this multi-path group. - Status - Storage to place NTSTATUS of the call. - -Return Value: - - The path ID to which the request should be sent. - ---*/ - -{ - PDSM_CONTEXT dsmContext = DsmContext; - PDSM_DEVICE_INFO deviceInfo; - PDSM_GROUP_ENTRY group; - PDSM_FAILOVER_GROUP failGroup = NULL; - PVOID newPath = NULL; - PDSM_FAILOVER_GROUP oldFailGroup = NULL; - PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failPathDevInfoEntry = NULL; - PCDB cdb = NULL; - UCHAR opCode = 0xFF; - BOOLEAN lockInExclusiveMode = FALSE; - ULONG SpecialHandlingFlag = 0; - - - if (Srb) { - cdb = SrbGetCdb(Srb); - if (cdb) { - opCode = cdb->AsByte[0]; - - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmLBGetPath (DsmIds %p): Entering function.\n", - DsmList)); - - // - // Up-front checking to minimally validate the list of - // DsmId's being passed in. - // - NT_ASSERT(DsmList->Count && DsmList->IdList[0]); - if (!(DsmList->Count && DsmList->IdList[0])) { - - *Status = STATUS_NO_SUCH_DEVICE; - goto __Exit_DsmLBGetPath; - } - - deviceInfo = DsmList->IdList[0]; - group = deviceInfo->Group; - - - failGroup = DsmpGetPath(dsmContext, DsmList, Srb, SpecialHandlingFlag); - - // - // If there wasn't a single active/optimized path found, check to see if - // there is an STPG in progress that may be making a path A/O. - // - if (!failGroup) { - - // - // Take the last path used. - // - oldFailGroup = DsmpFindFOGroup(dsmContext, CurrentPath); - - // - // Find the devInfo corresponding to this path. - // - deviceInfo = DsmpFindDevInfoFromGroupAndFOGroup(dsmContext, - group, - oldFailGroup); - - if (deviceInfo) { - - // - // Check if there is an alternate devInfo to be used temporarily - // for this deviceInfo - // - failPathDevInfoEntry = DsmpFindFailPathDevInfoEntry(dsmContext, - group, - deviceInfo); - - if (failPathDevInfoEntry) { - - // - // Use the alternate devInfo for now temporarily while the STPG - // that was previously sent (asynchronously) works on making the - // appropriate path active/optimized. - // - failGroup = (failPathDevInfoEntry->TempDeviceInfo)->FailGroup; - } - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmLBGetPath (DsmIds %p): Couldn't find FOG but FO in progress, so returning devInfo %p (FOG %p path %p).\n", - DsmList, - deviceInfo, - deviceInfo->FailGroup, - deviceInfo->FailGroup->PathId)); - } else { - - // - // Check if there is an RTPG in progress, if yes, return some path - // for the IO to be sent down. - // - if (InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 0, 0)) { - - BOOLEAN sendTPG = FALSE; - deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); - - if (deviceInfo) { - - failGroup = deviceInfo->FailGroup; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmLBGetPath (DsmIds %p): Couldn't find FOG but RTPG inflight, so returning devInfo %p (FOG %p path %p).\n", - DsmList, - deviceInfo, - deviceInfo->FailGroup, - deviceInfo->FailGroup->PathId)); - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmLBGetPath (DsmIds %p): Couldn't find FOG but RTPG inflight, even then couldn't find alternative devInfo.\n", - DsmList)); - } - } - } - } - - if (failGroup) { - - newPath = failGroup->PathId; - *Status = STATUS_SUCCESS; - - // - // If this is a retried request, our SetCompletion would have been bypassed, - // and our completion routine won't yet get called, so update the old and - // the new paths' stats. - // - if (Srb && DsmIsReadWrite(opCode)) { - - PDSM_FAILOVER_GROUP oldPath; - PIRP irp = (PIRP)SrbGetOriginalRequest(Srb); - PIO_STACK_LOCATION irpStack; - - // - // This indicates that the request is being retried. So we need to: - // 1. Update old path's and new path's request count - // 2. If the old path was supposed to be removed, check if there are - // no more requests are outstanding, and if yes, remove the path - // - - irpStack = IoGetCurrentIrpStackLocation(irp); - oldPath = irpStack->Parameters.Others.Argument3; - - if (oldPath) { - - NT_ASSERT(oldPath->FailOverSig == DSM_FOG_SIG); - - if (DsmpDecrementCounters(oldPath, Srb)) { - - // - // If there are no requests on a path that is supposed to be removed, - // remove it now. - // - if (oldPath->State == DSM_FG_PENDING_REMOVE) { - KIRQL irql; - - NT_ASSERT(oldPath->Count == 0); - - // - // We need to acquire the DsmContextLock in Exclusive mode since - // we are removing a path from the Failover Group list. - // - irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); - lockInExclusiveMode = TRUE; - - RemoveEntryList(&oldPath->ListEntry); - InterlockedDecrement((LONG volatile*)&dsmContext->NumberStaleFOGroups); - - ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmLBGetPath (DsmIds %p): Removing FOGroup %p with path %p.\n", - DsmList, - oldPath, - oldPath->PathId)); - - DsmpFreePool(oldPath); - } - } - - irpStack->Parameters.Others.Argument3 = failGroup; - - DsmpIncrementCounters(failGroup, Srb); - } - } - - } else { - - *Status = STATUS_NO_SUCH_DEVICE; - - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmLBGetPath (DsmIds %p): Failed to get FO group in LBGetPath.\n", - DsmList)); - - - } - -__Exit_DsmLBGetPath: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmLBGetPath (DsmIds %p): Exiting function returning path %p for request %p.\n", - DsmList, - newPath, - Srb)); - - return newPath; -} - -_Success_(return == DSM_PATH_SET) -ULONG -DsmCategorizeRequest( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PVOID CurrentPath, - _Outptr_result_maybenull_ OUT PVOID *PathId, - _Out_ OUT NTSTATUS *Status - ) -/*++ - -Routine Description: - - This routine is called when a request is received other than a read/write. - It will determine the best path to which the request is to be sent. - - In order to support clusters, reserve and release need to be handled - via SrbControl. - -Arguments: - - DsmContext - Context value given to the multipath driver during - registration. - DsmIds - List of our DSM IDs. - Irp - The Irp containing Srb. - Srb - The current non-read/write Srb. - CurrentPath - The last path that was returned for this multi-path group. - PathId - Placeholder for the PathID - Status - Storage to place NTSTATUS of the call. - -Return Value: - - DSM_PATH_SET - Indicates PathID is valid. - DSM_ERROR - Couldn't get a path. - ---*/ -{ - ULONG dsmStatus; - NTSTATUS status = STATUS_UNSUCCESSFUL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmCategorizeRequest (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // Determine whether this is a special-case request. - // - if (DsmpReservationCommand(Irp, Srb)) { - - dsmStatus = DSM_WILL_HANDLE; - goto __Exit_DsmCategorizeRequest; - } - - - // - // If this is a mpio pass through or a mpio pass through direct request, - // pick the path that corresponds to the pathId specified. - // - if (DsmpMpioPassThroughPathCommand(Irp)) { - - *PathId = DsmpGetPathIdFromPassThroughPath(DsmContext, - DsmIds, - Irp, - &status); - } else { - - // - // For requests other than reservation-handling and pass through, punt - // it back to the bus-driver. Need to get a path for the request first, - // so call the Load-Balance function. - // - *PathId = DsmLBGetPath(DsmContext, - Srb, - DsmIds, - CurrentPath, - &status); - } - - if (NT_SUCCESS(status)) { - - if (!*PathId) { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmCategorizeRequest (DsmIds %p): DSM_PATH_SET didn't return a path.\n", - DsmIds)); - } - - // - // Indicate that the path is updated, and mpctl should handle the request. - // - dsmStatus = DSM_PATH_SET; - - } else { - - // - // Indicate the error back to mpctl. - // - dsmStatus = DSM_ERROR; - - // - // Mark-up the Srb to show that a failure has occurred. - // This value is really only for this DSM to know what to do - // in the InterpretError routine - Fatal Error. - // It could be something more meaningful. - // - if (Srb) { - Srb->SrbStatus = SRB_STATUS_NO_DEVICE; - } - - *PathId = NULL; - } - - // - // Pass back status info to mpctl. - // - *Status = status; - -__Exit_DsmCategorizeRequest: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmCategorizeRequest (DsmIds %p): Exiting function with categorization %x.\n", - DsmIds, - dsmStatus)); - - return dsmStatus; -} - - -NTSTATUS -DsmBroadcastRequest( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ) -/*++ - -Routine Description: - - This routine is called when the DSM has indicated that Srb should be - sent to the device down all paths. The DSM will update IoStatus - information and status, but not complete the request. - - Currently MSDSM doesn't have a need for this. - -Arguments: - - DsmIds - The collection of DSM IDs that pertain to the MPDisk. - Irp - Irp containing SRB. - Srb - Scsi request block - Event - DSM sets this once all sub-requests have completed and - the original request's IoStatus has been setup. - -Return Value: - - NTSTATUS of the operation. - ---*/ -{ - NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; - - UNREFERENCED_PARAMETER(DsmContext); - UNREFERENCED_PARAMETER(Srb); - UNREFERENCED_PARAMETER(Irp); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmBroadcastRequest (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // Currently nothing is handled via Broadcast. Just set the event to - // free up the request handling in the bus-driver. - // - NT_ASSERT(NT_SUCCESS(status)); - KeSetEvent(Event, 0, FALSE); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmBroadcastReqeust (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmSrbDeviceControl( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ) -/*++ - -Routine Description: - - This routine is called when the DSM has indicated that it wants to handle - it internally (via returning DSM_WILL_HANDLE in CategorizeRequest). - - It should set IoStatus (Status and Information) and the Event, but not - complete the request. - -Arguments: - - DsmContext - The DSM's context - DsmIds - The collection of DSM IDs that pertain to the MPDISK. - Irp - Irp containing SRB. - Srb - Scsi request block - Event - Event to be set when the DSM is finished if DsmHandled is TRUE - -Return Value: - - NTSTATUS of the request. - ---*/ -{ - PDSM_CONTEXT dsmContext = DsmContext; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - NTSTATUS status; - UCHAR opCode = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmSrbDeviceControl (DsmIds %p): Entering function.\n", - DsmIds)); - - if (!DsmIds || !DsmIds->Count) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_IOCTL, - "DsmSrbDeviceControl (DsmIds %p): No DsmIds passed in.\n", - DsmIds)); - - status = STATUS_NO_SUCH_DEVICE; - goto __Exit_DsmSrbDeviceControl; - } - - if (irpStack->MajorFunction == IRP_MJ_SCSI) { - - // - // Determine the operation. - // - PCDB cdb = SrbGetCdb(Srb); - if (cdb) { - opCode = cdb->AsByte[0]; - } - - if (opCode == SCSIOP_PERSISTENT_RESERVE_OUT) { - - status = DsmpPersistentReserveOut(dsmContext, - DsmIds, - Irp, - Srb, - Event); - - } else if (opCode == SCSIOP_PERSISTENT_RESERVE_IN) { - - status = DsmpPersistentReserveIn(dsmContext, - DsmIds, - Irp, - Srb, - Event); - - } else { - - // - // Should never be here. - // - DSM_ASSERT(FALSE); - status = STATUS_INVALID_DEVICE_REQUEST; - } - } else { - // - // Should never be here. - // - DSM_ASSERT(irpStack->MajorFunction == IRP_MJ_SCSI); - status = STATUS_INVALID_DEVICE_REQUEST; - } - -__Exit_DsmSrbDeviceControl: - if (status != STATUS_PENDING) { - - // - // Set-up the Irp status for mpio's completion of the request. - // If it was IRP_MJ_SCSI, one of the helper routines set Srb->SrbStatus - // already. - // - if ((irpStack->MajorFunction == IRP_MJ_SCSI) && - (Srb != NULL) && - (Srb->SrbStatus == SRB_STATUS_PENDING)) { - - Srb->SrbStatus = SRB_STATUS_ERROR; - } - - Irp->IoStatus.Status = status; - - // - // Set the event to free up the request handling in the bus-driver. - // - KeSetEvent(Event, 0, FALSE); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmSrbDeviceControl (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -VOID -DsmSetCompletion( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _Inout_ IN OUT PDSM_COMPLETION_INFO DsmCompletion - ) -/*++ - -Routine Description: - - This routine is called before the actual submission of a request, - but after the categorisation of the I/O. This will be called only - for those requests not handled by the DSM directly: - Read/Write - Other requests not handled by SrbControl or Broadcast - -Arguments: - - DsmContext - The DSM's context. - DsmId - Identifer that was indicated when the request was - categorized (or be LBGetPath) - Irp - Irp containing Srb. - Srb - The request - DsmCompletion - Completion info structure to be filled out by DSM. - -Return Value: - - None - ---*/ -{ - PDSM_CONTEXT dsmContext = DsmContext; - PDSM_DEVICE_INFO deviceInfo = DsmId; - PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); - PDSM_FAILOVER_GROUP failGroup = deviceInfo->FailGroup; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmSetCompletion (DevInfo %p): Entering function.\n", - DsmId)); - - // - // Save off the path that was selected to service this request in Argument3. - // - irpStack->Parameters.Others.Argument3 = failGroup; - - DsmpIncrementCounters(failGroup, Srb); - - if (!dsmContext->DisableStatsGathering) { - - // - // Indicate one more request on this device down this path. - // - InterlockedIncrement(&deviceInfo->NumberOfRequestsInProgress); - } - - // - // Update the passed-in struct with our routine and context values. - // - DsmCompletion->DsmCompletionRoutine = DsmpRequestComplete; - DsmCompletion->DsmContext = DsmContext; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmSetCompletion (DevInfo %p): Exiting function.\n", - DsmId)); - - return; -} - - -ULONG -DsmInterpretError( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _Inout_ IN OUT NTSTATUS *Status, - _Out_ OUT PBOOLEAN Retry, - _Out_ OUT PLONG RetryInterval, - ... - ) -/*++ - -Routine Description: - - This routine is invoked by MPIO if Status is other than SUCCESS. - A few NTSTATUS and SRB_STATUS values indicate a fatal error. - Also checked are unit attentions, for which a retry is requested. - -Arguments: - - DsmContext - The DSM's context. - DsmId - Identifers returned from DMS_INQUIRE_DRIVER. - Srb - The Srb with an error. - Status - NTSTATUS of the operation. Can be updated. - Retry - Allows the DSM to indicate whether to retry the IO. - RetryInterval - Lets DSM specify (in seconds) when this specific I/O - should be retried. Use MAXLONG to use the default - retry interval. Use zero to retry immediately. - -Return Value: - - DSM_FATAL_ERROR indicates a fatal error. - ---*/ -{ - // - // The requests that will be encountered can be divided into four categories: - // 1. The request that has failed. - // 2. Subsequent requests that were sent down the failing path that will - // complete with failure. - // 3. Requests that were already submitted to LBGetPath() just before InterpretError() - // was called for the failed request (but have yet to have the LB policy - // algo run). - // 4. Requests that come into the Dispatch() routine after the failed request - // has been processed by InterpretError(). - // - // For the failed request: - // ======================= - // 1. Find a standby path to make active/optimized. - // 2. Send STPG asynchronously as a scsi pass through via IRP_MJ_SCSI (this - // way it can be sent at DISPATCH_IRQL) after setting a completion routine. - // 3. Save the devInfo corresponding to the standby path for the failing devInfo. - // 4. Return FATAL to MPIO so that new IO are queued. - // 5. In the completion routine, update the new states for the devInfos. Then - // clear the saved (previously) standby devInfo for the failing devInfo. - // - // For the subsequent request that will fail (since it was sent on the failing path): - // ================================================================================== - // 1. If a standby devInfo has been saved off, it indicates that an STPG was - // already sent, so no need to send another one. - // 2. Return FATAL to MPIO so that this request gets queued. - // - // For the requests that were already submitted to LBGetPath() during this time: - // ============================================================================= - // 1. If there is no active path, check if a standby devInfo has been saved - // away. If it has, return this path. Such requests will fail with check - // condition saying path used is in standby. - // 2. In InterpretError() retry (since the error indicates that request - // completed before STPG completed) without decrementing the remaining - // retries count. - // - // For new requests that come into Dispatch() after above processing: - // ================================================================== - // We don't need to worry about such requests, since MPIO will queue them - // automatically. - // - - PDSM_DEVICE_INFO deviceInfo = DsmId; - ULONG errorMask = 0; - PVOID senseData = SrbGetSenseInfoBuffer(Srb); - UCHAR senseDataLength = SrbGetSenseInfoBufferLength(Srb); - BOOLEAN failover = FALSE; - BOOLEAN retry = FALSE; - BOOLEAN handled = FALSE; - BOOLEAN sendTPG = FALSE; - BOOLEAN tpgException = FALSE; - BOOLEAN devInfoException = FALSE; - PCDB cdb = SrbGetCdb(Srb); - UCHAR opCode = 0; - UCHAR scsiStatus = SrbGetScsiStatus(Srb); - BOOLEAN validSense = FALSE; - UCHAR senseKey = 0; - UCHAR addSenseCode = 0; - UCHAR addSenseCodeQualifier = 0; - - if (cdb) { - opCode = cdb->AsByte[0]; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Entering function.\n", - DsmId)); - - *RetryInterval = MAXLONG; - - if ((scsiStatus == SCSISTAT_RESERVATION_CONFLICT) || - (*Status == STATUS_DEVICE_BUSY)) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Srb %p. Either busy or res. conflict (%x %x).\n", - DsmId, - Srb, - scsiStatus, - *Status)); - } - - // - // Go ahead and get the sense data if it's valid. - // - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { - - NT_ASSERT(senseData != NULL); - - validSense = ScsiGetSenseKeyAndCodes(senseData, - senseDataLength, - SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, - &senseKey, - &addSenseCode, - &addSenseCodeQualifier); - } - - // - // Sense data relating to logical block provisioning should be failed - // immediately back to the class layer for handling. - // - if (validSense) { - if (senseKey == SCSI_SENSE_NOT_READY && - addSenseCode == SCSI_ADSENSE_LUN_NOT_READY && - addSenseCodeQualifier == SCSI_SENSEQ_SPACE_ALLOC_IN_PROGRESS) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Temporary resource exhaustion. Fail Srb %p.\n", - DsmId, - Srb)); - - handled = TRUE; - - } else if (senseKey == SCSI_SENSE_DATA_PROTECT && - addSenseCode == SCSI_ADSENSE_WRITE_PROTECT && - addSenseCodeQualifier == SCSI_SENSEQ_SPACE_ALLOC_FAILED_WRITE_PROTECT) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Permanent resource exhaustion. Fail Srb %p.\n", - DsmId, - Srb)); - - handled = TRUE; - - } else if (senseKey == SCSI_SENSE_UNIT_ATTENTION && - addSenseCode == SCSI_ADSENSE_LB_PROVISIONING && - addSenseCodeQualifier == SCSI_SENSEQ_SOFT_THRESHOLD_REACHED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Soft threshold reached. Fail Srb %p.\n", - DsmId, - Srb)); - - handled = TRUE; - - } else if (senseKey == SCSI_SENSE_UNIT_ATTENTION && - addSenseCode == SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED && - addSenseCodeQualifier == SCSI_SENSEQ_INQUIRY_DATA_CHANGED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Inquiry data changed. Fail Srb %p.\n", - DsmId, - Srb)); - - handled = TRUE; - } else if (senseKey == SCSI_SENSE_UNIT_ATTENTION && - addSenseCode == SCSI_ADSENSE_PARAMETERS_CHANGED && - addSenseCodeQualifier == SCSI_SENSEQ_CAPACITY_DATA_CHANGED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Capacity data changed. Fail Srb %p.\n", - DsmId, - Srb)); - - handled = TRUE; - } - } - - if (handled) { - return errorMask; - } - - // - // Check the NT Status first. - // Several are clearly failover conditions. - // - switch (*Status) { - case STATUS_DEVICE_NOT_CONNECTED: - case STATUS_DEVICE_DOES_NOT_EXIST: - case STATUS_NO_SUCH_DEVICE: - case STATUS_DELETE_PENDING: { - - // - // The port pdo has either been removed or is - // very broken. A fail-over is necessary. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Will initiate fail over. Status %x. Opcode %x.\n", - DsmId, - *Status, - opCode)); - - handled = TRUE; - failover = TRUE; - break; - } - - case STATUS_IO_DEVICE_ERROR: { - - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { - - if (validSense) { - - // - // See if it's a unit attention. - // - if (senseKey == SCSI_SENSE_UNIT_ATTENTION) { - - switch (addSenseCode) { - - case SCSI_ADSENSE_PARAMETERS_CHANGED: { - - switch (addSenseCodeQualifier) { - - case SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_CHANGED: - case SPC3_SCSI_SENSEQ_IMPLICIT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): TPG states have changed. Requesting retry on Srb %p. Will send asyn RTPG.\n", - DsmId, - Srb)); - - // - // Retry but after sending RTPG, which will update the path states. - // - sendTPG = TRUE; - retry = TRUE; - handled = TRUE; - errorMask = DSM_RETRY_DONT_DECREMENT; - - if (addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_CHANGED) { - - // - // Worth retrying on the same path. - // - devInfoException = TRUE; - NT_ASSERT(!tpgException); - } - - break; - } - - - case SPC3_SCSI_SENSEQ_RESERVATIONS_RELEASED: { - - // - // This request needs to be immediately retried down the same path. - // - retry = TRUE; - *RetryInterval = 0; - handled = TRUE; - InterlockedExchangePointer(&(deviceInfo->Group->PathToBeUsed), deviceInfo->FailGroup); - break; - } - - case SPC3_SCSI_SENSEQ_MODE_PARAMETERS_CHANGED: - case SPC3_SCSI_SENSEQ_RESERVATIONS_PREEMPTED: - case SPC3_SCSI_SENSEQ_REGISTRATIONS_PREEMPTED: - case SPC3_SCSI_SENSEQ_CAPACITY_DATA_HAS_CHANGED: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Failing request. STATUS_IO_DEVICE_ERROR (params changed). SrbStatus (%x) Scsi (%x) AddQual (%u).\n", - DsmId, - Srb->SrbStatus, - scsiStatus, - addSenseCodeQualifier)); - - // - // Just fail these back. - // - handled = TRUE; - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): UNIT_ATTENTION for params changed. ASCQ %x. Asking for retry on Srb %p.\n", - DsmId, - addSenseCodeQualifier, - Srb)); - - // - // Indicate that a retry is necessary. - // - retry = TRUE; - handled = TRUE; - - break; - } - } - - break; - } - - - case SPC3_SCSI_ADSENSE_COMMANDS_CLEARED_BY_ANOTHER_INITIATOR: { - - if (addSenseCodeQualifier == 0x00) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): UNIT_ATTENTION (commands cleared by another initiator). Fail back to upper level. Srb %p.\n", - DsmId, - Srb)); - - // - // Commands cleared by another Initiator - // - handled = TRUE; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): UNIT_ATTENTION (commands cleared by another initiator). ASCQ %x. Asking for retry on Srb %p.\n", - DsmId, - addSenseCodeQualifier, - Srb)); - - // - // Indicate that a retry is necessary. - // - retry = TRUE; - handled = TRUE; - } - - - break; - } - - case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: { - - if (addSenseCodeQualifier == SCSI_SENSEQ_VOLUME_SET_MODIFIED || - addSenseCodeQualifier == SCSI_SENSEQ_REPORTED_LUNS_DATA_CHANGED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): VolumeSet/LunsData changed. Fail Srb %p.\n", - DsmId, - Srb)); - - // - // Fail back to upper layers. - // - handled = TRUE; - - break; - - } else { - - // - // Fall through to default case (ie. retry the request) - // - } - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): UNIT_ATTENTION. ASC %x, ASCQ %x. Asking for retry on Srb %p.\n", - DsmId, - addSenseCode, - addSenseCodeQualifier, - Srb)); - - // - // Indicate that a retry is necessary. - // - retry = TRUE; - handled = TRUE; - - break; - } - } - } else if (senseKey == SCSI_SENSE_NOT_READY) { - - if (addSenseCode == SCSI_ADSENSE_LUN_NOT_READY) { - - if (scsiStatus == SCSISTAT_CHECK_CONDITION) { - - switch (addSenseCodeQualifier) { - - // - // See if failure is due to device's current TPG state. - // - // If the failure is PORT_IN_STANDBY_STATE, we leave DSM_RETRY_DONT_DECREMENT unset if no active path exists, - // because otherwise MPIO will not be able to find a better path, and it will get into an infinite loop - // of trying and failing the command on a Standby path. See WCxeTfs:89150 - // - case SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION: - case SPC3_SCSI_SENSEQ_TARGET_PORT_IN_UNAVAILABLE_STATE: - - errorMask = DSM_RETRY_DONT_DECREMENT; - - case SPC3_SCSI_SENSEQ_TARGET_PORT_IN_STANDBY_STATE: - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): TPG-transition/TPG-SB/TPG-UA. ASCQ %x. Will send down async RTPG. Asking for retry on Srb %p.\n", - DsmId, - addSenseCodeQualifier, - Srb)); - - // - // Indicate that a retry is necessary but without decrementing the remaining - // retries count. However, we may need to send down an STPG/RTPG also. - // And we must set PTBU to a path that is in a different TPG. - // - sendTPG = TRUE; - tpgException = TRUE; - NT_ASSERT(!devInfoException); - retry = TRUE; - handled = TRUE; - - if ((addSenseCodeQualifier == SPC3_SCSI_SENSEQ_TARGET_PORT_IN_STANDBY_STATE) && - DsmIsReadWrite(opCode)) { - - PDSM_CONTEXT context = (PDSM_CONTEXT) deviceInfo->DsmContext; - KIRQL oldIrql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); - BOOLEAN activePathExists = ( NULL != DsmpGetAnyActivePath(deviceInfo->Group, FALSE, NULL, 0) ); - ExReleaseSpinLockExclusive(&(context->DsmContextLock), oldIrql); - - if (activePathExists) { - errorMask = DSM_RETRY_DONT_DECREMENT; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Not decrementing error counter, as an active path exists in group %p and opcode %x is r/w\n", - DsmId, - deviceInfo->Group, - opCode)); - } - } - - break; - - case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Manual intervention required. Asking for retry on Srb %p.\n", - DsmId, - Srb)); - - // - // This may be caused by NDU of controller firmware. It does not - // necessarily indicate that the device won't be ready via other path(s). - // Worth retrying instead of immediately failing back. - // - retry = TRUE; - handled = TRUE; - - break; - } - } - } - } - } - - } else if (Srb->SrbStatus == SRB_STATUS_BUS_RESET) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): BUS_RESET. Failing back Srb %p.\n", - DsmId, - Srb)); - - // - // Upper layers will retry in this case. If we retry here it will - // have a multiplicative effect which may result in a very long - // IO completion time if the device persistently times out. - // - retry = FALSE; - handled = TRUE; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Failing request. STATUS_IO_DEVICE_ERROR. SrbStatus (%x) ScsiStatus (%x).\n", - DsmId, - Srb->SrbStatus, - scsiStatus)); - } - - break; - } - - case STATUS_BUFFER_OVERFLOW: { - - if (DsmIsReadWrite(opCode)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): BUFFER_OVERFLOW: Retry.\n", - DsmId)); - - // - // Retry these, as this condition might indicate a torn write. - // - retry = TRUE; - handled = TRUE; - } - - break; - } - - case STATUS_DEVICE_BUSY: { - - // - // See if it's a check condition for TPG states in transition. - // - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && - scsiStatus == SCSISTAT_CHECK_CONDITION) { - - if (validSense) { - - if (senseKey == SCSI_SENSE_NOT_READY && - addSenseCode == SCSI_ADSENSE_LUN_NOT_READY && - addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): TPG transition. Will send down async RTPG. Asking for retry on Srb %p.\n", - DsmId, - Srb)); - - // - // Indicate that a retry is necessary but without decrementing the remaining - // retries count. However, we may need to send down an STPG/RTPG also. - // And we must set PTBU to a path that is in a different TPG. - // - sendTPG = TRUE; - tpgException = TRUE; - NT_ASSERT(!devInfoException); - retry = TRUE; - handled = TRUE; - errorMask = DSM_RETRY_DONT_DECREMENT; - } - - } - } - - break; - } - - case STATUS_DEVICE_NOT_READY: { - - if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && - scsiStatus == SCSISTAT_CHECK_CONDITION) { - - if (validSense) { - if (senseKey == SCSI_SENSE_NOT_READY && - addSenseCode == SCSI_ADSENSE_LUN_NOT_READY) { - - switch (addSenseCodeQualifier) { - - case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Manual intervention required. Asking for retry on Srb %p.\n", - DsmId, - Srb)); - - // - // This may be caused by NDU of controller firmware. It does not - // necessarily indicate that the device won't be ready via other path(s). - // Worth retrying instead of immediately failing back. - // - retry = TRUE; - handled = TRUE; - - break; - } - - case SCSI_SENSEQ_SPACE_ALLOC_IN_PROGRESS: { - // - // This indicates a logical block provisioning temporary resource exhaustion - // condition and therefore we must allow the class layer to handle it. - // - retry = FALSE; - handled = TRUE; - - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Unhandled AddQual %x.\n", - DsmId, - addSenseCodeQualifier)); - - break; - } - } - } - } - } - } - - - default: { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Unhandled status code %x.\n", - DsmId, - *Status)); - - break; - } - } - - if (!handled) { - - // - // The NTSTATUS didn't indicate a fail-over condition, but - // check various srb status for failover-class error. - // - switch (Srb->SrbStatus) { - case SRB_STATUS_SELECTION_TIMEOUT: - case SRB_STATUS_INVALID_LUN: - case SRB_STATUS_INVALID_TARGET_ID: - case SRB_STATUS_NO_DEVICE: - case SRB_STATUS_NO_HBA: - case SRB_STATUS_INVALID_PATH_ID: { - - // - // All of these are fatal. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): SrbStatus 0x%x. Will initiate fail over.\n", - DsmId, - Srb->SrbStatus)); - - failover = TRUE; - break; - } - - - default: { - - if ((scsiStatus == SCSISTAT_CHECK_CONDITION) && - (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { - - if (validSense) { - - switch (senseKey) { - - case SCSI_SENSE_NO_SENSE: { - - if (addSenseCode == SCSI_ADSENSE_NO_SENSE && - addSenseCodeQualifier == SCSI_SENSEQ_CAUSE_NOT_REPORTABLE) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): CheckCondition with no sense info. Will initiate fail over.\n", - DsmId)); - - // - // This could be a transient error generated - // in response to potentially a hardware fault. - // Worth trying another path. - // - failover = TRUE; - handled = TRUE; - } - - break; - } - - case SCSI_SENSE_ILLEGAL_REQUEST: { - - if (addSenseCode == SCSI_ADSENSE_INVALID_LUN) { - - if (addSenseCodeQualifier == 0x00) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Invalid LUN. Will initiate fail over.\n", - DsmId)); - - // - // LUN may still exist on other path(s). - // Worth a failover. - // - failover = TRUE; - handled = TRUE; - } - } - - break; - } - - case SCSI_SENSE_HARDWARE_ERROR: { - - if (addSenseCode == SPC3_SCSI_ADSENSE_LOGICAL_UNIT_COMMAND_FAILED) { - - if (addSenseCodeQualifier == SPC3_SCSI_SENSEQ_SET_TARGET_PORT_GROUPS_FAILED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): STPG failed. Will initiate fail over.\n", - DsmId)); - - // - // If an STPG failed, treat as FATAL and get another - // path set to A/O via another STPG. - // - failover = TRUE; - handled = TRUE; - } - } else if ((addSenseCode == SCSI_ADSENSE_LOGICAL_UNIT_ERROR && addSenseCodeQualifier == SCSI_SENSEQ_TIMEOUT_ON_LOGICAL_UNIT) || - (addSenseCode == SCSI_ADSENSE_DATA_TRANSFER_ERROR && addSenseCodeQualifier == SCSI_SENSEQ_INITIATOR_RESPONSE_TIMEOUT)) { - - // - // Could potentially indicate a dropped FC packet. Retry (along another - // path, based on the LB policy). - // - retry = TRUE; - handled = TRUE; - } - - break; - } - - default: { - - break; - } - } - } - } - - if (!handled) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Unhandled SRB Status 0x%x. Sense data %x|%x|%x.\n", - DsmId, - Srb->SrbStatus, - validSense ? senseKey : 0xFF, - validSense ? addSenseCode : 0xFF, - validSense ? addSenseCodeQualifier : 0xFF)); - } - - break; - } - } - } - - if (failover) { - ULONG SpecialHandlingFlag = 0; - - // - // If ALUA is supported, then it is possible that we may need to send - // down an STPG so build an IRP and fill in the SRB for STPG and send it down. - // - if (!DsmpIsSymmetricAccess(deviceInfo)) { - - DsmpSetLBForPathFailingALUA(DsmContext, deviceInfo, TRUE, SpecialHandlingFlag); - - } else { - - // - // If device doesn't support ALUA, we just need to update - // states without sending down any commands (STPG) - // - DsmpSetLBForPathFailing(DsmContext, deviceInfo, TRUE, SpecialHandlingFlag); - } - - errorMask = DSM_FATAL_ERROR; - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmInterpretError(DevInfo %p): Device changed to state %d\n", - deviceInfo, - deviceInfo->State)); - -#if DBG - { - ULONG inx; - PDSM_GROUP_ENTRY group = deviceInfo->Group; - PDSM_DEVICE_INFO tempDevInfo; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Device %p in group %p being marked as failed. NTStatus 0x%x.\n", - DsmId, - deviceInfo, - group, - *Status)); - - for (inx = 0; inx < group->NumberDevices; inx++) { - - tempDevInfo = group->DeviceList[inx]; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Device %p at %d. State %d.\n", - DsmId, - tempDevInfo, - inx, - tempDevInfo->State)); - } - } -#endif // DBG - } - - if (retry) { - - if (sendTPG) { - - // - // If ALUA is supported, send down STPG/RTPG as appropriate. - // - if (!DsmpIsSymmetricAccess(deviceInfo)) { - - DsmpSetPathForIoRetryALUA(DsmContext, deviceInfo, tpgException, devInfoException); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_RW, - "DsmInterpretError(DevInfo %p): SRB request %p will be retried. PTBU set to %p.\n", - deviceInfo, - Srb, - deviceInfo->Group->PathToBeUsed)); - } - } - } - - - *Retry = retry; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmInterpretError (DevInfo %p): Exiting function returning errorMask %x.\n", - DsmId, - errorMask)); - - return errorMask; -} - -BOOLEAN -DsmIsAddressTypeSupported( - _In_ IN PVOID DsmContext, - _In_ IN ULONG AddressType - ) -/*++ - -Routine Description: - - This routine is called when MPIO wants to know if the DSM supports a - particular storage address type. - - This routine must be provided for DSMs of DsmType6 or higher. - -Arguments: - - DsmContext - Context value passed to DsmInitialize() - AddressType - The storage address type being queried. - -Return Value: - - TRUE - If the DSM supports the given storage address type. - FALSE - If the DSM does not support the given storage address type. - ---*/ -{ - UNREFERENCED_PARAMETER(DsmContext); - - if (AddressType == STORAGE_ADDRESS_TYPE_BTL8) - { - return TRUE; - } - - return FALSE; -} - -NTSTATUS -DsmDeviceNotUsed( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId - ) -/*++ - -Routine Description: - - This routine indicates that the device represented by DsmId will not be - initialized completely by MPIO. - The DSM_ID list passed to other functions will no longer contain DsmId, - so internal structures should be updated accordingly. - - This routine must be provided for DSMs of DsmType6 or higher. - -Arguments: - - DsmContext - Context value given to the multipath driver during registration. - DsmId - Value referring to the uninitialized device. - -Return Value: - - NTSTATUS of the operation. - ---*/ -{ - PDSM_DEVICE_INFO deviceInfo = (PDSM_DEVICE_INFO)DsmId; - - DSM_ASSERT(deviceInfo->Group != NULL); - DSM_ASSERT(deviceInfo->Group->GroupSig == DSM_GROUP_SIG); - - // - // Undo anything we did to build up the device in DsmInquire(). - // - DsmRemoveDevice((PDSM_CONTEXT)DsmContext, DsmId, deviceInfo->FailGroup); - - return STATUS_SUCCESS; -} - -NTSTATUS -DsmUnload( - _In_ IN PVOID DsmContext - ) -/*++ - -Routine Description: - - This routine is called when the main module requires the DSM to be unloaded - (ie. prior to the main module unload). - -Arguments: - - DsmContext - Context value passed to DsmInitialize() - -Return Value: - - STATUS_SUCCESS; - ---*/ - -{ - PVOID tempAddress = DsmContext; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmUnload (DsmCtxt %p): Entering function.\n", - DsmContext)); - - DsmpFreeDSMResources((PDSM_CONTEXT) DsmContext); - - if (gMPIOControlObjectRefd) { - - ObDereferenceObject(gMPIOControlObject); - gMPIOControlObjectRefd = FALSE; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmUnload (DsmCtxt %p): Exiting function.\n", - tempAddress)); - - // - // Stop the tracing subsystem. - // - WPP_CLEANUP(gDsmDriverObject); - - return STATUS_SUCCESS; -} - diff --git a/tests/projects/wdk/wdm/msdsm/msdsm.h b/tests/projects/wdk/wdm/msdsm/msdsm.h deleted file mode 100644 index e1ddeb52d..000000000 --- a/tests/projects/wdk/wdm/msdsm/msdsm.h +++ /dev/null @@ -1,1403 +0,0 @@ -/*++ - -Copyright (C) 2004-2010 Microsoft Corporation - -Module Name: - - msdsm.h - -Abstract: - - Header for the Microsoft Device Specific Module (DSM). - -Environment: - - kernel mode only - -Notes: - ---*/ - -#ifndef _MSDSM_H_ -#define _MSDSM_H_ - -// -// Maximum number of paths per device supported by the DSM. -// This is a limit currently set by MPIO itself and needs to be updated if MPIO -// supports more paths-per-device in the future. -// -#define DSM_MAX_PATHS 32 - -// -// MPIO control object's well known symbolic name -// -#define DSM_MPIO_CONTROL_OBJECT_SYMLINK L"\\DosDevices\\MPIOControl" - -// -// Location of System class node in the registry -// -#define DSM_SYSTEM_CLASS_GUID_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E97D-E325-11CE-BFC1-08002BE10318}" - -// -// Values used for matching and figuring out the DriverVersion -// -#define DSM_INF_PATH L"InfPath" -#define DSM_MSDSM_INF_PATH L"msdsm.inf" -#define DSM_DRIVER_VERSION L"DriverVersion" -#define DSM_DRIVER_VERSION_FIELD_DELIMITER L'.' -#define DSM_BUFFER_MAXCOUNT 64 - -// -// MSDSM's display name. -// -#define DSM_FRIENDLY_NAME L"Microsoft DSM" - -// -// Name of the value for the supported devices in the registry, found in the -// DSM's Services' Parameters key -// -#define DSM_SUPPORTED_DEVICELIST_VALUE_NAME L"DsmSupportedDeviceList" - -// -// Value used to determine if per-IO statistics gathering needs to be turned OFF -// -#define DSM_DISABLE_STATISTICS L"DsmDisableStatistics" - -// -// Names of the values in the registry for whether to use the same path for -// sequential IOs when employing Least Blocks load balance policy, as well -// as its size. -// -#define DSM_USE_CACHE_FOR_LEAST_BLOCKS L"DsmUseCacheForLeastBlocks" -#define DSM_CACHE_SIZE_FOR_LEAST_BLOCKS L"DsmCacheSizeForLeastBlocks" - -// -// Name of the value in the registry for the maximum request retry time during ALUA -// state transitions. This value is found in the DSM's Services' Parameters key, and -// applies only to Persistent Reservation commands. -// -#define DSM_MAX_STATE_TRANSITION_TIME_VALUE_NAME L"DsmMaximumStateTransitionTime" - - -// -// Default max amount of time (in seconds) that a PR failing with retry-able UA will be retried -// -#define DSM_MAX_PR_UNIT_ATTENTION_RETRY_TIME 3 - -// -// Macro to translate seconds to ticks. Each system tick is 10^(-7) seconds. -// -#define DSM_SECONDS_TO_TICKS(_Seconds) ((_Seconds) * 10000000) - -// -// Size of the buffer allocated to retrieve device serial number. -// This is as defined by SPC-3 spec. The identifier with the biggest size is -// SCSI name type (0x8). -// -#define DSM_SERIAL_NUMBER_BUFFER_SIZE 255 - -// -// Number of LB Policies that are supported by this driver. -// -#define DSM_NUMBER_OF_LB_POLICIES 6 - -// -// Size of the buffer passed to read in Persistent Reserve keys. -// -#define DSM_READ_PERSISTENT_KEYS_BUFFER_SIZE 4096 - -// -// The default threshold for sequential IO for the Least Blocks load balance -// policy is 1MB. -// -#define DSM_LEAST_BLOCKS_DEFAULT_THRESHOLD 0x00100000 - -// -// Initialization data structure that needs to be filled in for MPIO -// -DSM_INIT_DATA gDsmInitData; - -// -// Macro used to round of a number to the nearest 8 byte aligned one. -// -#ifdef AlignOn8Bytes -#undef AlignOn8Bytes -#endif -#define AlignOn8Bytes(x) (((x) + 7) & ~7) - -// -// Macro for determining minimum of two numbers -// -#ifdef MIN -#undef MIN -#endif -#define MIN(a, b) ((ULONGLONG)(a) < (ULONGLONG)(b) ? (a) : (b)) - -// -// Macro used to convert a 4 byte array to a ULONG (where byte 0 MSB, byte 3 LSB) -// -#define GetUlongFrom4ByteArray(UCharArray, ULongValue) \ - ((UNALIGNED UCHAR *)&(ULongValue))[3] = ((UNALIGNED UCHAR *)(UCharArray))[0]; \ - ((UNALIGNED UCHAR *)&(ULongValue))[2] = ((UNALIGNED UCHAR *)(UCharArray))[1]; \ - ((UNALIGNED UCHAR *)&(ULongValue))[1] = ((UNALIGNED UCHAR *)(UCharArray))[2]; \ - ((UNALIGNED UCHAR *)&(ULongValue))[0] = ((UNALIGNED UCHAR *)(UCharArray))[3]; - -// -// Macro used to convert a ULONG into a 4 byte array (as big-endian) -// -#define Get4ByteArrayFromUlong(ULongValue, UCharArray) \ - ((UNALIGNED UCHAR *)(UCharArray))[3] = ((UNALIGNED UCHAR *)&(ULongValue))[0]; \ - ((UNALIGNED UCHAR *)(UCharArray))[2] = ((UNALIGNED UCHAR *)&(ULongValue))[1]; \ - ((UNALIGNED UCHAR *)(UCharArray))[1] = ((UNALIGNED UCHAR *)&(ULongValue))[2]; \ - ((UNALIGNED UCHAR *)(UCharArray))[0] = ((UNALIGNED UCHAR *)&(ULongValue))[3]; - -// -// Macro to check if passed in opcode is a read, write -// -#define DsmIsReadRequest(_Opcode) (_Opcode == SCSIOP_READ || _Opcode == SCSIOP_READ16) -#define DsmIsWriteRequest(_Opcode) (_Opcode == SCSIOP_WRITE || _Opcode == SCSIOP_WRITE16) -#define DsmIsReadWrite(_Opcode) (_Opcode == SCSIOP_READ || _Opcode == SCSIOP_READ16 || \ - _Opcode == SCSIOP_WRITE || _Opcode == SCSIOP_WRITE16) - -#define DsmIsReadCapacity( _Opcode ) (_Opcode == SCSIOP_READ_CAPACITY || _Opcode == SCSIOP_READ_CAPACITY16) - - -// -// Macro to find the number of bytes consumed by the array -// -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - - -// -// Signature used to identify various structures. -// Used solely for debugging purposes. -// -#define DSM_DEVICE_SIG 0xAAAAAAAA -#define DSM_GROUP_SIG 0x55555555 -#define DSM_FOG_SIG 0x88888888 -#define DSM_TARGET_PORT_GROUP_SIG 0x33333333 -#define DSM_TARGET_PORT_SIG 0xCCCCCCCC -#define DSM_CONTROLLER_SIG 0xEEEEEEEE - -#define WNULL (L'\0') -#define WNULL_SIZE (sizeof(WNULL)) - -#if DBG - -// -// NT_ASSERT wrapper. -// -#define DSM_ASSERT(exp) if (DoAssert) { \ - NT_ASSERT(exp); \ - } - -#else // DBG - -#define DSM_ASSERT(exp) - -#endif // DBG - -#define DSM_PARAMETER_PATH_W L"MSDSM\\Parameters" - -// -// Pool Tags used in memory allocation -// -#define DSM_TAG_GENERIC '00ZZ' -#define DSM_TAG_PASS_THRU '10ZZ' -#define DSM_TAG_GROUP_ENTRY '20ZZ' -#define DSM_TAG_FO_GROUP '30ZZ' -#define DSM_TAG_DSM_CONTEXT '40ZZ' -#define DSM_TAG_DEV_INFO '50ZZ' -#define DSM_TAG_SERIAL_NUM '60ZZ' -#define DSM_TAG_CTRL_INFO '70ZZ' -#define DSM_TAG_SUPPORTED_DEV '80ZZ' -#define DSM_TAG_REG_PATH '90ZZ' -#define DSM_TAG_FOG_DEV_ENTRY 'A0ZZ' -#define DSM_TAG_DEV_ID 'B0ZZ' -#define DSM_TAG_DEV_NAME 'C0ZZ' -#define DSM_TAG_LB_POLICY 'D0ZZ' -#define DSM_TAG_PR_KEYS 'E0ZZ' -#define DSM_TAG_RESERVED_DEVICE 'F0ZZ' -#define DSM_TAG_BIN_TO_ASCII '01ZZ' -#define DSM_TAG_TARGET_PORT_LIST_ENTRY '11ZZ' -#define DSM_TAG_TARGET_PORT_GROUP_ENTRY '21ZZ' -#define DSM_TAG_RELATIVE_TARGET_PORT_ID '31ZZ' -#define DSM_TAG_TARGET_PORT_GROUPS '41ZZ' -#define DSM_TAG_CONTROLLER_LIST_ENTRY '51ZZ' -#define DSM_TAG_CONTROLLER_INFO '61ZZ' -#define DSM_TAG_IO_STATUS_BLOCK '71ZZ' -#define DSM_TAG_DEVICE_ID_LIST '81ZZ' -#define DSM_TAG_TP_DEVICE_LIST_ENTRY '91ZZ' -#define DSM_TAG_RETRY_RESERVE 'A1ZZ' -#define DSM_TAG_WORKITEM 'B1ZZ' -#define DSM_TAG_SCSI_ADDRESS 'C1ZZ' -#define DSM_TAG_FAIL_DEVINFO_LIST_ENTRY 'D1ZZ' -#define DSM_TAG_TPG_COMPLETION_CONTEXT 'E1ZZ' -#define DSM_TAG_SCSI_REQUEST_BLOCK 'F1ZZ' -#define DSM_TAG_SCSI_SENSE_INFO '02ZZ' -#define DSM_TAG_SPT_DATA_BUFFER '12ZZ' -#define DSM_TAG_REG_KEY_RELATED '22ZZ' -#define DSM_TAG_DEV_HARDWARE_ID '32ZZ' -#define DSM_TAG_REG_VALUE_RELATED '42ZZ' -#define DSM_TAG_ZOMBIEGROUP_ENTRY '52ZZ' -#define DSM_TAG_PERSISTENT_RESERVATION '62ZZ' - -// -// Parameters subkey name under HKLM\System\CCS\Services\MSDSM -// -#define DSM_SERVICE_PARAMETERS L"Parameters" - -// -// Load Balance settings are persisted in the registry under this key -// -#define DSM_LOAD_BALANCE_SETTINGS L"DsmLoadBalanceSettings" - -// -// Load Balance settings on a VID/PID basis are persistented in the registry -// under this key -// -#define DSM_TARGETS_LOAD_BALANCE_SETTING L"DsmTargetsLoadBalanceSetting" - -// -// Values persisted per device: -// 1. Load Balance Policy -// 2. Preferred Path -// 3. Whether LB policy has been explicitly set -// -#define DSM_LOAD_BALANCE_POLICY L"DsmLoadBalancePolicy" -#define DSM_PREFERRED_PATH L"DsmPreferredPath" -#define DSM_POLICY_EXPLICITLY_SET L"DsmLoadBalancePolicyExplicitlySet" - -// -// Prefix for subkey created for each path -// -#define DSM_PATH L"DSMPath" - -// -// Values persisted per path: -// 1. Whether primary -// 2. Whether optimized -// 3. Path weight. -// -// Primary Optimized State -//==================================== -// True True Active-Optimized -// True False Active-Unoptimized -// False True StandBy -// False False Unavailable -// -#define DSM_PRIMARY_PATH L"DsmPrimaryPath" -#define DSM_OPTIMIZED_PATH L"DsmOptimizedPath" -#define DSM_PATH_WEIGHT L"DsmPathWeight" - -// -// Indicates that device doesn't support ALUA. -// -#define DSM_DEVINFO_ALUA_NOT_SUPPORTED 0 - -// -// Implies that device supports implicit ALUA transistions. -// -#define DSM_DEVINFO_ALUA_IMPLICIT 1 - -// -// Implies that device supports explicit ALUA state transitions. -// -#define DSM_DEVINFO_ALUA_EXPLICIT 2 - -// -// Type of device identifier (VPD 0x83) -// -typedef enum _DSM_DEVID_TYPE { - DSM_DEVID_SERIAL_NUMBER = 1, - DSM_DEVID_RELATIVE_TARGET_PORT, - DSM_DEVID_TARGET_PORT_GROUP -} DSM_DEVID_TYPE, *PDSM_DEVID_TYPE; - -#define _DSM_TERNARY_BOOLEAN UCHAR -typedef _DSM_TERNARY_BOOLEAN DSM_TERNARY_BOOLEAN, *PDSM_TERNARY_BOOLEAN; -#define DSM_TERNARY_UNKNOWN 0 -#define DSM_TERNARY_TRUE 1 -#define DSM_TERNARY_FALSE 2 - -// -// Macro to determine if _Id2 is more preferred than _Id1 to build a device's -// serial number. -// -#define DsmpIsPreferredDeviceId(_Id1, _Id2) (((_Id2) == StorageIdTypeScsiNameString) || \ - ((_Id2) == StorageIdTypeFCPHName && (_Id1) != StorageIdTypeScsiNameString) || \ - ((_Id2) == StorageIdTypeEUI64 && (_Id1) != StorageIdTypeScsiNameString && (_Id1) != StorageIdTypeFCPHName) || \ - ((_Id2) == StorageIdTypeVendorId && (_Id1) != StorageIdTypeScsiNameString && (_Id1) != StorageIdTypeFCPHName && (_Id1) != StorageIdTypeEUI64) || \ - ((_Id2) == StorageIdTypeVendorSpecific && (_Id1) != StorageIdTypeScsiNameString && (_Id1) != StorageIdTypeFCPHName && (_Id1) != StorageIdTypeEUI64 && (_Id1) != StorageIdTypeVendorId)) - -// -// Device State -// -typedef enum _DSM_DEVICE_STATE { - - // - // If ALUA is not supported, this state indicates that the device is active - // and a request can be sent to the device. - // If ALUA is supported, then this state indicates optimizied device-path - // pair for the device. - // - DSM_DEV_ACTIVE_OPTIMIZED = 0, - - // - // If ALUA is not supported, this state is not used. - // If ALUA is supported, then this state indicates active but unoptimized - // device-path pairing for the device. Can be used in in case no - // active/optimized path is available to service the IO. - // - DSM_DEV_ACTIVE_UNOPTIMIZED, - - // - // If ALUA is not supported, this state indicates that the device is in - // standby state. A request can be sent to the device in this state. - // If ALUA is supported, then this state indicates standby device-path - // pairing and only certain requests can be handled in this state. - // - DSM_DEV_STANDBY, - - // - // If ALUA is not supported, this state is not used. - // If ALUA is supported, then this state indicates that the device-path pairing - // is not active and incapable of handling any requests. - // - DSM_DEV_UNAVAILABLE, - - // - // If ALUA is not supported, this state is not used. - // If ALUA is supported, then this state indicates that the device-path pairing - // (actually its TPG) is in a transitioning state. - // - DSM_DEV_TRANSITIONING = 15, - - // - // Initial state when devInfo is created. - // - DSM_DEV_NOT_USED_STATE = 16, - - // - // Indicates that the state was undetermined (this is applicable only for - // a deviceInfo's DesiredState or if the device instance's path was not - // determined). - // - DSM_DEV_UNDETERMINED, - - // - // Indicates that a request sent down previously failed with a fatal error - // - DSM_DEV_FAILED, - - // - // Indicates that InvalidatePath has been called - // - DSM_DEV_INVALIDATED, - - // - // This indicates the device is about to be removed. No new request - // should be sent to the device. - // - DSM_DEV_REMOVE_PENDING, - - // - // This indicates the device has been removed. - // - DSM_DEV_REMOVED - -} DSM_DEVICE_STATE, *PDSM_DEVICE_STATE; - -// -// Device states supported -// -#define DSM_STATE_ACTIVE_OPTIMIZED_SUPPORTED 0 -#define DSM_STATE_STANDBY_SUPPORTED 1 -#define DSM_STATE_ACTIVE_UNOPTIMIZED_SUPPORTED 2 -#define DSM_STATE_UNAVAILABLE_SUPPORTED 4 - - -// -// Macro to determine if devInfo is in a failure state. -// -#define DsmpIsDeviceFailedState(_State) ((_State) > DSM_DEV_NOT_USED_STATE) - -// -// Macro to determine if devInfo was initialized. -// -#define DsmpIsDeviceInitialized(_DeviceInfo) ((_DeviceInfo)->Initialized) - -// -// Macro to determine if device is "usable" (ie. IsPathActive was successfully called). -// -#define DsmpIsDeviceUsable(_DeviceInfo) ((_DeviceInfo)->Usable) - -// -// Macro to determine if devInfo was used to send down registration. -// It the devInfo's group is not reserved, then the devInfo doesn't need to have -// had a register go down it. -// It the group is reserved, then the devInfo MUST have had a register go down it -// for it to be used. -// -#define DsmpIsDeviceUsablePR(_DeviceInfo) (!(_DeviceInfo)->Group->PRKeyValid || (_DeviceInfo)->PRKeyRegistered) - - -// -// Macro to determine if _State2 is a more preferred state than _State1. -// -#define DsmpIsBetterDeviceState(_State1, _State2) (((_State1) == DSM_DEV_STANDBY && (_State2) == DSM_DEV_ACTIVE_UNOPTIMIZED) || \ - ((_State1) == DSM_DEV_UNAVAILABLE && \ - ((_State2) == DSM_DEV_ACTIVE_UNOPTIMIZED || (_State2) == DSM_DEV_STANDBY)) || \ - ((_State1) == DSM_DEV_TRANSITIONING && \ - ((_State2) == DSM_DEV_ACTIVE_UNOPTIMIZED || (_State2) == DSM_DEV_STANDBY) || (_State2) == DSM_DEV_UNAVAILABLE)) - -// -// Macro to determine if passed in _State is active. -// -#define DsmpIsDeviceStateActive(_State) ((_State) == DSM_DEV_ACTIVE_OPTIMIZED || (_State) == DSM_DEV_ACTIVE_UNOPTIMIZED) - -// -// Macro to determine if symmetric access to the storage -// -#define DsmpIsSymmetricAccess(_DeviceInfo) ((_DeviceInfo)->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED || \ - ((_DeviceInfo)->ALUASupport == DSM_DEVINFO_ALUA_IMPLICIT && \ - (_DeviceInfo)->Group->Symmetric)) - -// -// Multi-path Group State -// -typedef enum _DSM_GROUP_STATE { - - // - // This indicates that the device is in working state. - // - DSM_GP_NORMAL = 1, - - // - // This indicates that there is a pending reservation failover - // - DSM_GP_PENDING, - - // - // This indicates that the device has lost all its paths - // - DSM_GP_FAILED - -} DSM_GROUP_STATE, *PDSM_GROUP_STATE; - -// -// Fail-Over Group State -// -typedef enum _DSM_FAILOVER_GROUP_STATE { - - // - // This indicates that the path is in working state. - // - DSM_FG_NORMAL = 1, - - // - // This indicates the path which had failed earlier - // is back to working state now. - // - DSM_FG_FAILBACK, - - // - // This indicates the path is about to be removed - // - DSM_FG_PENDING_REMOVE, - - // - // This indicates the path has failed. - // - DSM_FG_FAILED - -} DSM_FAILOVER_GROUP_STATE, *PDSM_FAILOVER_GROUP_STATE; - -#define DsmpIsPathFailedState(_State) ((_State) >= DSM_FG_PENDING_REMOVE) - -// -// DSM Context is the global driver context that gets passed to each of the DSM -// entry points. -// -// The DSM Context will maintain a list of all DeviceInfos (device-path pairing). -// It will maintain a list of Group entries. Each entry in the Group list will -// represent a LUN's different instances down different paths (i.e. DeviceInfos). -// Each entry in the Group will maintain a list of target port groups. -// Each entry in the target port group list will maintain a list of target -// ports that make up the target port group. Every deviceInfo that isn't -// in a failure state will be in the same state as the Asymmetric Access -// State of the target port group. -// There will be a list of Fail Over Group entries, where each entry represents -// the list of devices that fail over as a group (i.e. devices on the same path). -// There will also be a list of controller entries, representing the controllers -// on all storages connected to the system. -// -typedef struct _DSM_CONTEXT { - - // - // Used to synchronize access to the SupportedDevices list. - // - KSPIN_LOCK SupportedDevicesListLock; - - // - // List of supported devices - added into the INF. - // - UNICODE_STRING SupportedDevices; - - // - // Used to synchronize access to the elements in this structure. - // - EX_SPIN_LOCK DsmContextLock; - - // - // Flag cached that indicates if statistics don't need to be gathered - // - BOOLEAN DisableStatsGathering; - - UCHAR Reserved[3]; - - // - // Number of devices currently found. - // - ULONG NumberDevices; - - // - // List of devices. - // - LIST_ENTRY DeviceList; - - // - // Number of multi-path groups. - // - ULONG NumberGroups; - - // - // List of multi-path groups. - // - LIST_ENTRY GroupList; - - // - // Number of fail-over groups. - // - ULONG NumberFOGroups; - - // - // List of fail-over groups. - // - LIST_ENTRY FailGroupList; - - // - // Number of controllers. - // - ULONG NumberControllers; - - // - // List of controllers - // - LIST_ENTRY ControllerList; - - // - // Number of stale fail-over groups - // - ULONG NumberStaleFOGroups; - - // - // List of stale fail-over groups maintained for paths for which all devices - // have gotten removed but for which there is still outstanding IO-statistics - // - LIST_ENTRY StaleFailGroupList; - - // - // Context value passed to the DSM from MPIO. - // - PVOID MPIOContext; - - - // - // Look-aside list of completion routine context structures. - // - NPAGED_LOOKASIDE_LIST CompletionContextList; - -} DSM_CONTEXT, *PDSM_CONTEXT; - -// -// Statistics structure. Used by the device and path routines. -// -typedef struct _DSM_STATS { - - ULONG NumberReads; - ULONG NumberWrites; - ULONGLONG BytesRead; - ULONGLONG BytesWritten; - -} DSM_STATS, *PDSM_STATS; - - -// -// Information about each device that is supported by the DSM. -// -typedef struct _DSM_DEVICE_INFO { - - // - // To link to the next device info structure in the list - // - LIST_ENTRY ListEntry; - - // - // The device SIG. Used for debug. - // - ULONG DeviceSig; - - // - // Back-pointer to the DSM_CONTEXT. - // - PVOID DsmContext; - - // - // The underlying port driver PDO. - // - PDEVICE_OBJECT PortPdo; - - // - // The port FDO to which PortPdo is attached. - // - PDEVICE_OBJECT PortFdo; - - // - // The DeviceObject to which I/Os generated by the DSM should - // be sent. This is given to us by MPIO. - // - PDEVICE_OBJECT TargetObject; - - // - // The multi-path group to which this device belongs. - // - struct _DSM_GROUP_ENTRY *Group; - - // - // The fail-over group to which this device belongs. - // - struct _DSM_FAILOVER_GROUP *FailGroup; - - // - // The controller through which this device showed up. - // - struct _DSM_CONTROLLER_LIST_ENTRY *Controller; - - // - // The Target Port Group that this device belongs to. - // - struct _DSM_TARGET_PORT_GROUP_ENTRY *TargetPortGroup; - - // - // The Target Port that this device was exposed via. - // - struct _DSM_TARGET_PORT_LIST_ENTRY *TargetPort; - - // - // The current state of this device: ACTIVE_O, ACTIVE_U, STANDBY, UNAVAILABLE, etc. - // - DSM_DEVICE_STATE State; - - // - // Previous state of this device. Updated whenever this deviceInfo makes a - // state transition. - // - DSM_DEVICE_STATE PreviousState; - - // - // The desired state of this device: based on PrimaryPath and OptimizedPath - // specified in the registry. - // - DSM_DEVICE_STATE DesiredState; - - // - // The ALUA state of the TPG immediately after a ReportTPG is issued. - // - DSM_DEVICE_STATE ALUAState; - - // - // Holds state information temporarily while applying LB policy. Used in case - // changes need to be reverted in case of failure to apply the policy. - // - DSM_DEVICE_STATE TempPreviousStateForLB; - - // - // This is to save off the last known non-failed state. - // In case of an error down this deviceInfo, it is marked to be in Failed state. - // However, if no remove comes down for this device and a PathVerify down this - // deviceInfo succeeds, we need to put the deviceInfo back into a usable state. - // - DSM_DEVICE_STATE LastKnownGoodState; - - // - // This counter indicates that this deviceInfo is being used and a remove - // must thus wait until the counter falls to 0. - // - LONG BlockRemove; - - - // - // This indicates whether this device has handled a register/register_ignore_existing request, - // irrespective of the actual status of the operation. - // - BOOLEAN RegisterServiced; - - // - // This flag is set when a register/register_ignore_existing succeeds down this device-path pair. - // - BOOLEAN PRKeyRegistered; - - // - // Indicates whether the serial number was embedded in the device - // descriptor, or it was allocated. - // - BOOLEAN SerialNumberAllocated; - - // - // Flag to indicate that SetDeviceInfo has been called (and succeeded) on this device - // - BOOLEAN Initialized; - - // - // Flag to indicate that IsPathActive has been called (and succeeded) on this device. - // - BOOLEAN Usable; - - // - // Flag to indicate if IALUAE was disabled (via mode select) - // - BOOLEAN ImplicitDisabled; - - // - // Flag to indicate that RTPG has already been sent down in Inquire, so - // PathVerify can ignore sending down one more if it is called during - // device initialization. - // - BOOLEAN IgnorePathVerify; - - // - // Bit map indicating whether (and what kind) of ALUA support. - // - UCHAR ALUASupport; - - // - // Weight assigned to this path by management application. This is used - // when doing Load Balancing based on weighted paths. - // - ULONG PathWeight; - - // - // Number of requests outstanding on this device. - // - LONG NumberOfRequestsInProgress; - - // - // I/O, Fail-Over statistics. - // - DSM_STATS DeviceStats; - - // - // The device's serial number. - // - PSTR SerialNumber; - - // - // The scsi address of the port pdo. - // - PSCSI_ADDRESS ScsiAddress; - - - // - // Kernel structure that describes this device. Passed in to Inquire. - // - // NOTE: Descriptor should be the LAST field in this structure - // - STORAGE_DEVICE_DESCRIPTOR Descriptor; - -} DSM_DEVICE_INFO, *PDSM_DEVICE_INFO; - -typedef enum _DSM_DEFAULT_LB_POLICY_TYPE { - DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY = 0, // DSM assigned based on LUN access capability - DSM_DEFAULT_LB_POLICY_DSM_WIDE, // Admin has set a DSM-wide default policy - DSM_DEFAULT_LB_POLICY_VID_PID, // Admin has set a default policy for LUN's VID/PID - DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT // Admin has explicitly set the policy on the LUN -} DSM_DEFAULT_LB_POLICY_TYPE, *PDSM_DEFAULT_LB_POLICY_TYPE; - -typedef ULONG DSM_LOAD_BALANCE_TYPE, *PDSM_LOAD_BALANCE_TYPE; - - -// -// Information about multi-path groups: The same device found via multiple paths -// are put under one group. Each group will have it's own Load Balance policy -// settings. In other words, Load Balance policy settings are on per-device basis. -// -typedef struct _DSM_GROUP_ENTRY { - - // - // To link to the next entry in the multi-path group. - // - LIST_ENTRY ListEntry; - - // - // Group signature. Used for debug. - // - ULONG GroupSig; - - // - // Ordinal of creation. Never decremented. - // - ULONG GroupNumber; - - // - // State of the group. - // - DSM_GROUP_STATE State; - - // - // Number of devices in the multi-path group. - // - ULONG NumberDevices; - - // - // Array of devices belonging to this group. - // - PDSM_DEVICE_INFO DeviceList[DSM_MAX_PATHS]; - - // - // Max time to retry failed PR requests - // - ULONG MaxPRRetryTimeDuringStateTransition; - - // - // Number of target port groups that this device is accessible via. - // - ULONG NumberTargetPortGroups; - - // - // Array of the target port groups that this LUN belongs in. - // - struct _DSM_TARGET_PORT_GROUP_ENTRY *TargetPortGroupList[DSM_MAX_PATHS]; - - // - // Key used in Persistent Reserve\Release. This key is provided to the DSM - // by Cluster service. If cluster service has provided the key PRKeyValid - // is set to TRUE. PRKeyValid is set to FALSE otherwise. - // PRServiceAction, PRType and PRScope are the service action, type and - // scope associated with the PR registration. - // - UCHAR PersistentReservationRegisteredKey[8]; - UCHAR PRServiceAction; - UCHAR PRType; - UCHAR PRScope; - UCHAR PRKeyValid; - - - // - // Flag used to denote that LU access is symmetric down all paths - // - BOOLEAN Symmetric; - - // - // Flag to indicate whether or not to use same path for sequential IO - // when employing Least Blocks load balance policy. - // - BOOLEAN UseCacheForLeastBlocks; - - // - // Flag used to indicate if a throttle request succeeded. - // - ULONG Throttled; - - // - // Counter to track the number of RTPG in flight. - // - ULONG InFlightRTPG; - - // - // A bitmask of which devices are currently reserved. - // - ULONG ReservationList; - - // - // Which type of Load Balancing is being performed. - // - DSM_LOAD_BALANCE_TYPE LoadBalanceType; - - // - // Indicates how the Load Balancing policy was selected. - // - DSM_DEFAULT_LB_POLICY_TYPE LBPolicySelection; - - // - // The path to use when possible - if in F.O. Only, if failover had taken - // place and this path comes back online, failback to this path will take - // place. - // - ULONGLONG PreferredPath; - - // - // The path to choose when Round Robin Load Balance policy is in use - // - PVOID PathToBeUsed; - - // - // Size of cache set by Admin. Used in case of handling sequential - // IO in Least Blocks policy. - // - ULONGLONG CacheSizeForLeastBlocks; - - // - // The HardwareId (VID/PID) of the LUN - // - PWSTR HardwareId; - - // - // The registry key under which Load Balance Policy settings - // are stored in the registry for this Device Group. - // - PWSTR RegistryKeyName; - - // - // Number of failing deviceInfos - // - ULONG NumberFailingDevInfos; - - // - // To link the list of failed A/O devInfos and the corresponding non-A/O - // devInfos that are temporarily being used to service IO until STPG can - // properly update the device states. This is applicable only for ALUA - // devices. - // - LIST_ENTRY FailingDevInfoList; - - // - // General Purpose Event. - // - KEVENT Event; - -} DSM_GROUP_ENTRY, *PDSM_GROUP_ENTRY; - -// -// The collection of devices on one path. These fail-over as a unit. -// A path is considered an I_T nexus, i.e. Initiator port to Target (controller) port. -// -typedef struct _DSM_FAILOVER_GROUP { - - // - // To link to the next entry in the failover group - // - LIST_ENTRY ListEntry; - - // - // Signature. Used for debug. - // - ULONG FailOverSig; - - // - // State of the Path. - // - DSM_FAILOVER_GROUP_STATE State; - - // - // The pathId corresponding to this FOG. It may or may not be - // the same as what MPIO gave us as the default value. - // - PVOID PathId; - - // - // The default pathId (port FDO). - // - PDEVICE_OBJECT MPIOPath; - - // - // Last LBA - // - ULONGLONG LastLba; - - // - // Cumulative outstanding IO (in terms of size) - // - ULONGLONG OutstandingBytesOfIO; - - // - // Count of inflight IOs. This will be used in LQD load balance policy. - // - volatile LONG NumberOfRequestsInFlight; - - // - // Number of devices in this FOG. - // - ULONG Count; - - // - // List of devices that will over together. - // - LIST_ENTRY FOG_DeviceList; - - // - // List of zombie groups (in case a device is removed before the failover - // processing begins). - // - LIST_ENTRY ZombieGroupList; - -} DSM_FAILOVER_GROUP, *PDSM_FAILOVER_GROUP; - - -// -// Information about a target port group entry for a given LUN. -// Note: This is not a global list of all TPGs that are built. It is local to a Group entry. -// -typedef struct _DSM_TARGET_PORT_GROUP_ENTRY { - - // - // Signature. Used for debug. - // - ULONG TargetPortGroupSig; - - // - // The asymmetric access state for this target port group: - // ACTIVE_O, ACTIVE_U, STANDBY or UNAVAILABLE - // - DSM_DEVICE_STATE AsymmetricAccessState; - - // - // Flag to indicate if this is the preferred target port group. - // - BOOLEAN Preferred; - - // - // Supported access states - // - BOOLEAN ActiveOptimizedSupported; - BOOLEAN ActiveUnoptimizedSupported; - BOOLEAN StandBySupported; - BOOLEAN UnavailableSupported; - - // - // Indicates if the device reports asymmetric state as being under transition. - // - BOOLEAN TransitioningSupported; - - // - // Flag to indicate if this has been returned in any subsequent RTPG after - // it is initially built. (If this flag is not set after parsing the RTPG - // information, it indicates that this TPG entry is stale and should be - // deleted). - // - BOOLEAN Traversed; - - UCHAR Reserved; - - // - // The target group identifier - // - USHORT Identifier; - - // - // Status code - // - UCHAR StatusCode; - - // - // Vendor unique - // - UCHAR VendorUnique; - - // - // Backpointer to owning group - // - PDSM_GROUP_ENTRY Group; - - // - // Number of target ports that make up this group - // - ULONG NumberTargetPorts; - - // - // Linked list of target ports that make up this target port group. - // - LIST_ENTRY TargetPortList; - -} DSM_TARGET_PORT_GROUP_ENTRY, *PDSM_TARGET_PORT_GROUP_ENTRY; - - -// -// Information about each target port list entry for a given target port group. -// Note: this is not a global list of all TPs. It is local to a given TPG entry. -// -typedef struct _DSM_TARGET_PORT_LIST_ENTRY { - - // - // Link - // - LIST_ENTRY ListEntry; - - // - // Signature. Used for debug. - // - ULONG TargetPortSig; - - // - // Relative target port identifier - // - ULONG Identifier; - - // - // Backpointer to owning target port group - // - PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup; - - // - // Number of device instances exposed via this target port - // - ULONG Count; - - // - // List of device instances exposed via this target port - // - LIST_ENTRY TP_DeviceList; - -} DSM_TARGET_PORT_LIST_ENTRY, *PDSM_TARGET_PORT_LIST_ENTRY; - -// -// Information about each controller entry -// -typedef struct _DSM_CONTROLLER_LIST_ENTRY { - - // - // To link to the next contoller entry. - // - LIST_ENTRY ListEntry; - - // - // It's signature. Used for debug. - // - ULONG ControllerSig; - - // - // Device object (this controller's PDO). - // - PDEVICE_OBJECT DeviceObject; - - // - // Port FDO through which this controller object was exposed. - // - PDEVICE_OBJECT PortObject; - - // - // Identifier. - // - _Field_size_(IdLength) PUCHAR Identifier; - - // - // Identifier length. - // - ULONG IdLength; - - // - // Identifier code set. - // - STORAGE_IDENTIFIER_CODE_SET IdCodeSet; - - // - // Controller's SCSI address. - // - PSCSI_ADDRESS ScsiAddress; - - // - // Number of references to this entry. - // - UCHAR RefCount; - - // - // Flag to indicate whether this is a fake entry built for storage that do - // NOT have controllers - // - BOOLEAN IsFakeController; - - UCHAR Reserved[2]; - -} DSM_CONTROLLER_LIST_ENTRY, *PDSM_CONTROLLER_LIST_ENTRY; - -// -// Generic linked list of devices -// -typedef struct _DSM_DEVICELIST_ENTRY { - - // - // To link to the next device info structure in the list - // - LIST_ENTRY ListEntry; - - // - // Representation of device-path pair - // - PDSM_DEVICE_INFO DeviceInfo; - -} DSM_DEVICELIST_ENTRY, *PDSM_DEVICELIST_ENTRY; - -// -// Zombie Group List Entry -// -typedef struct _DSM_ZOMBIEGROUP_ENTRY { - - // - // To link to the next zombie group structure in the list - // - LIST_ENTRY ListEntry; - - // - // Pointer to actual group entry - // - PDSM_GROUP_ENTRY Group; - - // - // Flag to indicate that the failover thread has processed this entry. - // - BOOLEAN Processed; - -} DSM_ZOMBIEGROUP_ENTRY, *PDSM_ZOMBIEGROUP_ENTRY; - -// -// Linked list of devices that will failover as a group -// -typedef DSM_DEVICELIST_ENTRY DSM_FOG_DEVICELIST_ENTRY, *PDSM_FOG_DEVICELIST_ENTRY; - -// -// Linked list of the same device being exposed off of a particular target port -// (possibly because the controller is connected to multiple HBAs). -// -typedef DSM_DEVICELIST_ENTRY DSM_TARGET_PORT_DEVICELIST_ENTRY, *PDSM_TARGET_PORT_DEVICELIST_ENTRY; - -// -// Information about each failing devInfo and its corresponding devInfo -// being used temporarily to service requests until STPG can update new -// device states. -// -typedef struct _DSM_FAIL_PATH_PROCESSING_LIST_ENTRY { - - // - // To link to the next device info structure in the list - // - LIST_ENTRY ListEntry; - - // - // Representation of the failing device-path pair - // - PDSM_DEVICE_INFO FailingDeviceInfo; - - // - // Representation of the new candidate device-path pair that will take over - // processing of requests - // - PDSM_DEVICE_INFO TempDeviceInfo; - -} DSM_FAIL_PATH_PROCESSING_LIST_ENTRY, *PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY; - -// -// Completion context structure. -// -typedef struct _DSM_COMPLETION_CONTEXT { - - // - // The device that handled the request. - // - PDSM_DEVICE_INFO DeviceInfo; - - // - // The global context. - // - PDSM_CONTEXT DsmContext; - - // - // These are used to store control code, pointer to KEVENT, etc. - // - PVOID RequestUnique1; - - ULONG_PTR RequestUnique2; - -#if DBG - // - // Request time-stamp. - // - LARGE_INTEGER TickCount; -#endif - -} DSM_COMPLETION_CONTEXT, *PDSM_COMPLETION_CONTEXT; - -// -// Completion context structure for report/set target port groups. -// -typedef struct _DSM_TPG_COMPLETION_CONTEXT { - - PDSM_COMPLETION_CONTEXT CompletionContext; - - PSCSI_REQUEST_BLOCK Srb; - - PVOID SenseInfoBuffer; - - ULONG NumberRetries; - - UCHAR SenseInfoBufferLength; - -} DSM_TPG_COMPLETION_CONTEXT, *PDSM_TPG_COMPLETION_CONTEXT; - -// -// Version number used to determine whice version of MPIO_DSM_Path to use. -// -#define DSM_WMI_VERSION_1 1 -#define DSM_WMI_VERSION_2 2 - -// -// Version of MPIO_DSM_Path that is currently supported by this DSM. -// -#define DSM_WMI_VERSION DSM_WMI_VERSION_2 - -// -// This struct is used to save Load Balance Policy Settings in the registry -// -typedef struct _DSM_LOAD_BALANCE_POLICY_SETTINGS { - - WCHAR RegistryKeyName[256]; - ULONG LoadBalancePolicy; - ULONG PathCount; - MPIO_DSM_Path_V2 DsmPath[1]; - -} DSM_LOAD_BALANCE_POLICY_SETTINGS, *PDSM_LOAD_BALANCE_POLICY_SETTINGS; - -// -// This structure is used to pass in information used by the workitem -// to failover reservations down another path. -// -typedef struct _DSM_RETRY_RESERVE { - - PDSM_COMPLETION_CONTEXT CompletionContext; - - PIRP Irp; - - PKEVENT Event; - -} DSM_RETRY_RESERVE, *PDSM_RETRY_RESERVE; - -// -// This structure defines the workitem that will be used to handle reservation -// failover. -// -typedef struct _DSM_WORKITEM { - - // - // Work item that should be freed by the worker routine - // - PIO_WORKITEM WorkItem; - - // - // Context to be passed to worker routine - // - PVOID Context; - -} DSM_WORKITEM, *PDSM_WORKITEM; - -#endif // _MSDSM_H - - diff --git a/tests/projects/wdk/wdm/msdsm/msdsm.mof b/tests/projects/wdk/wdm/msdsm/msdsm.mof deleted file mode 100644 index 53ee61392..000000000 --- a/tests/projects/wdk/wdm/msdsm/msdsm.mof +++ /dev/null @@ -1,82 +0,0 @@ -// -// Copyright (C) 2004 Microsoft Corporation -// -// -// Microsoft DSM's internal classes -// - -// -// Perf class. -// -[WMI, - guid("{a34d03ec-6b0b-46a1-9178-82525f41133f}")] -class MSDSM_DEVICEPATH_PERF -{ - [WmiDataId(1), - Description("Path Identifier.") : amended - ] uint64 PathId; - - [WmiDataId(2), - Description("Number of Read Requests.") : amended - ] uint32 NumberReads; - - [WmiDataId(3), - Description("Number of Write Requests.") : amended - ] uint32 NumberWrites; - - [WmiDataId(4), - Description("Total Bytes Read.") : amended - ] uint64 BytesRead; - - [WmiDataId(5), - Description("Total Bytes Written.") : amended - ] uint64 BytesWritten; -}; - -[WMI, - Dynamic, - Provider("WmiProv"), - Description("Retrieve MSDSM Performance Information.") : amended, - Locale("MS\\0x409"), - guid("{875b8871-4889-4114-93f6-cd064c001cea}")] -class MSDSM_DEVICE_PERF -{ - [key, read] - string InstanceName; - [read] boolean Active; - - [WmiDataId(1), - read, - Description("Number of paths.") : amended - ] uint32 NumberPaths; - - [WmiDataId(2), - read, - Description("Array of Performance Information per path for the device.") : amended, - WmiSizeIs("NumberPaths") - ] MSDSM_DEVICEPATH_PERF PerfInfo[]; -}; - -// -// Methods -// Clear perf counters. -// -[Dynamic, - Provider("WMIProv"), - WMI, - Description("MSDSM WMI Methods") : amended, - guid("{04517f7e-92bb-4ebe-aed0-54339fa5f544}"), - locale("MS\\0x409") -] -class MSDSM_WMI_METHODS -{ - - [key, read] - string InstanceName; - [read] boolean Active; - - [WmiMethodId(1), - Implemented, - Description("Clear path performance counters for the device.") : amended - ] void MSDsmClearCounters(); -}; diff --git a/tests/projects/wdk/wdm/msdsm/msdsm.rc b/tests/projects/wdk/wdm/msdsm/msdsm.rc deleted file mode 100644 index 743640342..000000000 --- a/tests/projects/wdk/wdm/msdsm/msdsm.rc +++ /dev/null @@ -1,24 +0,0 @@ -//+------------------------------------------------------------------------- -// -// Microsoft Windows -// -// Copyright (C) Microsoft Corporation, 2004 -// -// File: msdsm.rc -// -//-------------------------------------------------------------------------- - -#include - -#include - -#define VER_FILETYPE VFT_DRV -#define VER_FILESUBTYPE VFT2_DRV_SYSTEM -#define VER_FILEDESCRIPTION_STR "Microsoft Device Specific Module" -#define VER_INTERNALNAME_STR "msdsm.sys" -#define VER_ORIGINALFILENAME_STR "msdsm.sys" - -#include "common.ver" - -MofResourceName MOFDATA msdsm.bmf -DsmMofResourceName MOFDATA msdsmdsm.bmf diff --git a/tests/projects/wdk/wdm/msdsm/msdsmdsm.mof b/tests/projects/wdk/wdm/msdsm/msdsmdsm.mof deleted file mode 100644 index f85eea270..000000000 --- a/tests/projects/wdk/wdm/msdsm/msdsmdsm.mof +++ /dev/null @@ -1,141 +0,0 @@ -// -// Copyright (C) 2004 Microsoft Corporation -// -// Microsoft DSM's DSM-specific classes -// - -// -// Class used for retrieving and setting MSDSM-wide default load balance policy. -// -[WMI, - Dynamic, - Provider("WmiProv"), - Description("MSDSM-wide default load balance policies.") : amended, - Locale("MS\\0x409"), - guid("{c81b5681-f3ca-4c98-9325-707d0d62ffc4}")] -class MSDSM_DEFAULT_LOAD_BALANCE_POLICY -{ - [key, read] - string InstanceName; - [read] boolean Active; - - [WmiDataId(1), - read, write, - Description("Load Balance Policy to be applied to devices controlled by MSDSM.") : amended - ] uint32 LoadBalancePolicy; - - [WmiDataId(2), - read, - Description("Reserved.") : amended - ] uint32 Reserved; - - // - // Preferred path. - // - [WmiDataId(3), - read, write, - Description("Preferred Path.") : amended - ] uint64 PreferredPath; -}; - -// -// Embedded class that describes a target and the default load balance policy -// of its LUNs. -// -[WMI, - guid("{ddb00a72-0fab-418b-a89e-97370ae293a4}")] -class MSDSM_TARGET_DEFAULT_POLICY_INFO -{ - // - // VID-PID string as an 8 + 16 character concatenated string. - // Spaces should be used to make the VID 8 chars and the PID 16 chars. - // - [WmiDataId(1), - MaxLen(31), - Description("Concatenated VendorID (8 characters) and ProductID (16 characters).") : amended - ] string HardwareId; - - // - // The default load balance policy to be applied to LUNs from the target - // whose hardware id matches the VID/PID above. - // NOTE: Setting this to 0 will act as removal of default setting for this - // target. - // - [WmiDataId(2)] uint32 LoadBalancePolicy; - - // - // Used for alignment reasons. - // - [WmiDataId(3)] uint32 Reserved; - - // - // Preferred path. - // - [WmiDataId(4)] uint64 PreferredPath; -}; - -// -// Class used for retrieving and setting target-level default load balance policy. -// -[WMI, - Dynamic, - Provider("WmiProv"), - Description("Target-level default load balance policies.") : amended, - Locale("MS\\0x409"), - guid("{5ccbcd91-1b56-4327-a2f3-0960335f8846}")] -class MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY -{ - [key, read] - string InstanceName; - [read] boolean Active; - - [WmiDataId(1), - read, write, - Description("Number of targets specified.") : amended - ] uint32 NumberDevices; - - [WmiDataId(2), - read, - Description("Reserved.") : amended - ] uint32 Reserved; - - [WmiDataId(3), - read, write, - MaxLen(31), - Description("Array of target hardware identifiers with policy and preferred path information.") : amended, - WmiSizeIs("NumberDevices") - ] MSDSM_TARGET_DEFAULT_POLICY_INFO TargetDefaultPolicyInfo[]; -}; - -// -// Supported devices list class. -// -[WMI, - Dynamic, - Provider("WmiProv"), - Description("Retrieve MSDSM's supported devices list.") : amended, - Locale("MS\\0x409"), - guid("{c362d67c-371e-44d8-8bba-044619e4f245}")] -class MSDSM_SUPPORTED_DEVICES_LIST -{ - [key, read] - string InstanceName; - [read] boolean Active; - - [WmiDataId(1), - read, - Description("Number of supported devices.") : amended - ] uint32 NumberDevices; - - [WmiDataId(2), - read, - Description("Reserved.") : amended - ] uint32 Reserved; - - [WmiDataId(3), - read, - MaxLen(31), - Description("Array of device hardware identifiers.") : amended, - WmiSizeIs("NumberDevices") - ] string DeviceId[]; -}; diff --git a/tests/projects/wdk/wdm/msdsm/precomp.h b/tests/projects/wdk/wdm/msdsm/precomp.h deleted file mode 100644 index bca8595db..000000000 --- a/tests/projects/wdk/wdm/msdsm/precomp.h +++ /dev/null @@ -1,34 +0,0 @@ - -/*++ - -Copyright (c) 2004 Microsoft Corporation - -Module Name: - - precomp.h - -Abstract: - - Precompiled header file for Microsoft Device Specific Module (DSM). - -Revision History: - ---*/ - -#pragma once - -#define DEBUG_MAIN_SOURCE 1 - -#include -#include - -#include "dsm.h" -#include "mpiodisk.h" -#include "msdsm.h" -#include "prototypes.h" -#include "trace.h" -#include "srbhelper.h" - -#include -#include - diff --git a/tests/projects/wdk/wdm/msdsm/precompsrc.c b/tests/projects/wdk/wdm/msdsm/precompsrc.c deleted file mode 100644 index 5944cf515..000000000 --- a/tests/projects/wdk/wdm/msdsm/precompsrc.c +++ /dev/null @@ -1 +0,0 @@ -#include "precomp.h" \ No newline at end of file diff --git a/tests/projects/wdk/wdm/msdsm/prototypes.h b/tests/projects/wdk/wdm/msdsm/prototypes.h deleted file mode 100644 index ebcf42029..000000000 --- a/tests/projects/wdk/wdm/msdsm/prototypes.h +++ /dev/null @@ -1,1436 +0,0 @@ - -/*++ - -Copyright (C) 2004 Microsoft Corporation - -Module Name: - - prototypes.h - -Abstract: - - Contains function prototypes for all the functions defined - by Microsoft Device Specific Module (DSM). - -Environment: - - kernel mode only - -Notes: - ---*/ - -#pragma warning (disable:4214) // bit field usage -#pragma warning (disable:4200) // zero-sized array - -#ifndef _PROTOTYPES_H_ -#define _PROTOTYPES_H_ - -#define DSM_VENDOR_ID_LEN 8 -#define DSM_PRODUCT_ID_LEN 16 -#define DSM_VENDPROD_ID_LEN 24 - -// -// In accordance with SPC-3 specs -// -#define SPC3_TARGET_PORT_GROUPS_HEADER_SIZE 4 - -typedef struct _SPC3_CDB_REPORT_TARGET_PORT_GROUPS { - UCHAR OperationCode; - UCHAR ServiceAction : 5; - UCHAR Reserved1 : 3; - UCHAR Reserved2[4]; - UCHAR AllocationLength[4]; - UCHAR Reserved3; - UCHAR Control; -} SPC3_CDB_REPORT_TARGET_PORT_GROUPS, *PSPC3_CDB_REPORT_TARGET_PORT_GROUPS; - -typedef struct _SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR { - UCHAR AsymmetricAccessState : 4; - UCHAR Reserved : 3; - UCHAR Preferred : 1; - UCHAR ActiveOptimizedSupported : 1; - UCHAR ActiveUnoptimizedSupported : 1; - UCHAR StandbySupported : 1; - UCHAR UnavailableSupported : 1; - UCHAR Reserved2 : 3; - UCHAR TransitioningSupported : 1; - USHORT TPG_Identifier; - UCHAR Reserved3; - UCHAR StatusCode; - UCHAR VendorUnique; - UCHAR NumberTargetPorts; - ULONG TargetPortIds[0]; -} SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR, *PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR; - -typedef struct _SPC3_CDB_SET_TARGET_PORT_GROUPS { - UCHAR OperationCode; - UCHAR ServiceAction : 5; - UCHAR Reserved1 : 3; - UCHAR Reserved2[4]; - UCHAR ParameterListLength[4]; - UCHAR Reserved3; - UCHAR Control; -} SPC3_CDB_SET_TARGET_PORT_GROUPS, *PSPC3_CDB_SET_TARGET_PORT_GROUPS; - -typedef struct _SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR { - UCHAR AsymmetricAccessState : 4; - UCHAR Reserved1 : 4; - UCHAR Reserved2; - USHORT TPG_Identifier; -} SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR, *PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR; - -typedef struct _SPC3_CONTROL_EXTENSION_MODE_PAGE { - UCHAR PageCode : 6; - UCHAR SubpageFormat : 1; - UCHAR ParametersSavable : 1; - UCHAR SubpageCode; - UCHAR PageLength[2]; - UCHAR ImplicitALUAEnable : 1; - UCHAR ScsiPrecendence : 1; - UCHAR TimestampChangeable : 1; - UCHAR Reserved1 : 5; - UCHAR InitialPriority : 4; - UCHAR Reserved2 : 4; - UCHAR Reserved3[26]; -} SPC3_CONTROL_EXTENSION_MODE_PAGE, *PSPC3_CONTROL_EXTENSION_MODE_PAGE; - -#define SPC3_SCSIOP_REPORT_TARGET_PORT_GROUPS 0xA3 -#define SPC3_SCSIOP_SET_TARGET_PORT_GROUPS 0xA4 -#define SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS 0xA -#define SPC3_RESERVATION_ACTION_REPORT_CAPABILITIES 0x2 - -#define SPC3_SCSI_ADSENSE_COMMANDS_CLEARED_BY_ANOTHER_INITIATOR 0x2F -#define SPC3_SCSI_ADSENSE_LOGICAL_UNIT_COMMAND_FAILED 0x67 - -#define SPC3_SCSI_SENSEQ_MODE_PARAMETERS_CHANGED 0x1 -#define SPC3_SCSI_SENSEQ_RESERVATIONS_PREEMPTED 0x3 -#define SPC3_SCSI_SENSEQ_RESERVATIONS_RELEASED 0x4 -#define SPC3_SCSI_SENSEQ_REGISTRATIONS_PREEMPTED 0x5 -#define SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_CHANGED 0x6 -#define SPC3_SCSI_SENSEQ_IMPLICIT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED 0x7 -#define SPC3_SCSI_SENSEQ_CAPACITY_DATA_HAS_CHANGED 0x9 -#define SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION 0xA -#define SPC3_SCSI_SENSEQ_TARGET_PORT_IN_STANDBY_STATE 0xB -#define SPC3_SCSI_SENSEQ_TARGET_PORT_IN_UNAVAILABLE_STATE 0xC - -#define SPC3_SCSI_SENSEQ_SET_TARGET_PORT_GROUPS_FAILED 0xA - -#define SPC3_SET_TARGET_PORT_GROUPS_TIMEOUT 10 -#define SPC3_REPORT_TARGET_PORT_GROUPS_TIMEOUT 10 - - -// -// Function prototypes for functions intrface.c -// - -DRIVER_INITIALIZE DriverEntry; -DRIVER_UNLOAD DsmDriverUnload; - -NTSTATUS -DsmInquire ( - _In_ IN PVOID DsmContext, - _In_ IN PDEVICE_OBJECT TargetDevice, - _In_ IN PDEVICE_OBJECT PortObject, - _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, - _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList, - _Out_ OUT PVOID *DsmIdentifier - ); - -BOOLEAN -DsmCompareDevices( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId1, - _In_ IN PVOID DsmId2 - ); - -NTSTATUS -DsmGetControllerInfo( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN ULONG Flags, - _Inout_ IN OUT PCONTROLLER_INFO *ControllerInfo - ); - -NTSTATUS -DsmSetDeviceInfo( - _In_ IN PVOID DsmContext, - _In_ IN PDEVICE_OBJECT TargetObject, - _In_ IN PVOID DsmId, - _Inout_ IN OUT PVOID *PathId - ); - -BOOLEAN -DsmIsPathActive( - _In_ IN PVOID DsmContext, - _In_ IN PVOID PathId, - _In_ IN PVOID DsmId - ); - -NTSTATUS -DsmPathVerify( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PVOID PathId - ); - -NTSTATUS -DsmInvalidatePath( - _In_ IN PVOID DsmContext, - _In_ IN ULONG ErrorMask, - _In_ IN PVOID PathId, - _Inout_ IN OUT PVOID *NewPathId - ); - -NTSTATUS -DsmMoveDevice( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PVOID MPIOPath, - _In_ IN PVOID SuggestedPath, - _In_ IN ULONG Flags - ); - -NTSTATUS -DsmRemovePending( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId - ); - -NTSTATUS -DsmRemoveDevice( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PVOID PathId - ); - -NTSTATUS -DsmRemovePath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PVOID PathId - ); - -NTSTATUS -DsmSrbDeviceControl( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ); - -PVOID -DsmLBGetPath( - _In_ IN PVOID DsmContext, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PDSM_IDS DsmList, - _In_ IN PVOID CurrentPath, - _Out_ OUT NTSTATUS *Status - ); - -ULONG -DsmInterpretError( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _Inout_ IN OUT NTSTATUS *Status, - _Out_ OUT PBOOLEAN Retry, - _Out_ OUT PLONG RetryInterval, - ... - ); - -NTSTATUS -DsmUnload( - _In_ IN PVOID DsmContext - ); - -VOID -DsmSetCompletion( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _Inout_ IN OUT PDSM_COMPLETION_INFO DsmCompletion - ); - -_Success_(return == DSM_PATH_SET) -ULONG -DsmCategorizeRequest( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PVOID CurrentPath, - _Outptr_result_maybenull_ OUT PVOID *PathId, - _Out_ OUT NTSTATUS *Status - ); - -NTSTATUS -DsmBroadcastRequest( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ); - -BOOLEAN -DsmIsAddressTypeSupported( - _In_ IN PVOID DsmContext, - _In_ IN ULONG AddressType - ); - -NTSTATUS -DsmDeviceNotUsed( - _In_ IN PVOID DsmContext, - _In_ IN PVOID DsmId - ); - - -// -// Function prototypes for functions in dsmmain.c -// - -VOID -DsmpFreeDSMResources( - _In_ IN PDSM_CONTEXT DsmContext - ); - -PDSM_GROUP_ENTRY -DsmpFindDevice( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN BOOLEAN AcquireDSMLockExclusive - ); - -PDSM_GROUP_ENTRY -DsmpBuildGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - -NTSTATUS -DsmpParseTargetPortGroupsInformation( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, - _In_ IN ULONG TargetPortGroupsInfoLength - ); - -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpFindTargetPortGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, - _In_ IN ULONG TPGs_BufferLength - ); - -_Success_(return!=0) -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpUpdateTargetPortGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, - _In_ IN ULONG TPGs_BufferLength, - _Out_ OUT PULONG DescriptorSize - ); - -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpBuildTargetPortGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, - _In_ IN ULONG TPGs_BufferLength, - _Out_ OUT PULONG DescriptorSize - ); - -PDSM_TARGET_PORT_LIST_ENTRY -DsmpFindTargetPortListEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN ULONG RelativeTargetPortId - ); - -PDSM_TARGET_PORT_LIST_ENTRY -DsmpBuildTargetPortListEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN ULONG RelativeTargetPortId - ); - -PDSM_TARGET_PORT_GROUP_ENTRY -DsmpFindTargetPortGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PUSHORT TargetPortGroupId - ); - -PDSM_TARGET_PORT_LIST_ENTRY -DsmpFindTargetPort( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN PULONG TargetPortGroupId - ); - -NTSTATUS -DsmpAddDeviceEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - -PDSM_CONTROLLER_LIST_ENTRY -DsmpFindControllerEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDEVICE_OBJECT PortObject, - _In_ IN PSCSI_ADDRESS ScsiAddress, - _In_reads_(ControllerSerialNumberLength) IN PSTR ControllerSerialNumber, - _In_ IN SIZE_T ControllerSerialNumberLength, - _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, - _In_ IN BOOLEAN AcquireLock - ); - -_Ret_maybenull_ -_Must_inspect_result_ -_When_(return != NULL, __drv_allocatesMem(Mem)) -PDSM_CONTROLLER_LIST_ENTRY -DsmpBuildControllerEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_opt_ IN PDEVICE_OBJECT DeviceObject, - _In_ IN PDEVICE_OBJECT PortObject, - _In_ IN PSCSI_ADDRESS ScsiAddress, - _In_ IN PSTR ControllerSerialNumber, - _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, - _In_ IN BOOLEAN AcquireLock - ); - -VOID -DsmpFreeControllerEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ __drv_freesMem(Mem) IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry - ); - -BOOLEAN -DsmpIsDeviceBelongsToController( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry - ); - -PDSM_DEVICE_INFO -DsmpFindDevInfoFromGroupAndFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_FAILOVER_GROUP FOGroup - ); - -PDSM_FAILOVER_GROUP -DsmpFindFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PVOID PathId - ); - -PDSM_FAILOVER_GROUP -DsmpBuildFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PVOID *PathId - ); - -NTSTATUS -DsmpUpdateFOGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_FAILOVER_GROUP FailGroup, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - -VOID -DsmpRemoveDeviceFailGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_FAILOVER_GROUP FailGroup, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN BOOLEAN AcquireDSMLockExclusive - ); - -ULONG -DsmpRemoveDeviceEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - -VOID -DsmpRemoveDeviceFromTargetPortList( - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - -PDSM_FAILOVER_GROUP -DsmpSetNewPath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDevice - ); - -PDSM_FAILOVER_GROUP -DsmpSetNewPathUsingGroup( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY Group - ); - -VOID -DsmpRemoveZombieGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY ZombieGroup - ); - -NTSTATUS -DsmpUpdateTargetPortGroupDevicesStates( - _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, - _In_ IN DSM_DEVICE_STATE NewState - ); - -VOID -DsmpIncrementCounters( - _In_ PDSM_FAILOVER_GROUP FailGroup, - _In_ PSCSI_REQUEST_BLOCK Srb - ); - -BOOLEAN -DsmpDecrementCounters( - _In_ PDSM_FAILOVER_GROUP FailGroup, - _In_ PSCSI_REQUEST_BLOCK Srb - ); - -PDSM_FAILOVER_GROUP -DsmpGetPath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmList, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN ULONG SpecialHandlingFlag - ); - -PVOID -DsmpGetPathIdFromPassThroughPath( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmList, - _In_ IN PIRP Irp, - _Inout_ IN OUT NTSTATUS *Status - ); - -VOID -DsmpRemoveGroupEntry( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_GROUP_ENTRY GroupEntry, - _In_ IN BOOLEAN AcquireDSMLockExclusive - ); - -BOOLEAN -DsmpMpioPassThroughPathCommand( - _In_ IN PIRP Irp - ); - -BOOLEAN -DsmpReservationCommand( - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb - ); - -VOID -DsmpRequestComplete( - _In_ IN PVOID DsmId, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PVOID DsmContext - ); - -NTSTATUS -DsmpRegisterPersistentReservationKeys( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN BOOLEAN Register - ); - - -BOOLEAN -DsmpShouldRetryPassThroughRequest( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ); - -BOOLEAN -DsmpShouldRetryPersistentReserveCommand( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ); - -BOOLEAN -DsmpShouldRetryTPGRequest( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ); - -BOOLEAN -DsmpIsDeviceRemoved( - _In_ IN PVOID SenseData, - _In_ IN UCHAR SenseDataSize - ); - -PDSM_DEVICE_INFO -DsmpGetActivePathToBeUsed( - _In_ PDSM_GROUP_ENTRY Group, - _In_ BOOLEAN Symmetric, - _In_ IN ULONG SpecialHandlingFlag - ); - -PDSM_DEVICE_INFO -DsmpGetAnyActivePath( - _In_ PDSM_GROUP_ENTRY Group, - _In_ BOOLEAN Exception, - _In_opt_ PDSM_DEVICE_INFO DeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ); - -PDSM_DEVICE_INFO -DsmpFindStandbyPathToActivate( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN ULONG SpecialHandlingFlag - ); - -PDSM_DEVICE_INFO -DsmpFindStandbyPathToActivateALUA( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PBOOLEAN SendTPG, - _In_ IN ULONG SpecialHandlingFlag - ); - -PDSM_DEVICE_INFO -DsmpFindStandbyPathInAlternateTpgALUA( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForDsmPolicyAdjustment( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ); - -NTSTATUS -DsmpSetLBForVidPidPolicyAdjustment( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PWSTR TargetHardwareId, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ); - -NTSTATUS -DsmpSetNewDefaultLBPolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_opt_ IN PDSM_DEVICE_INFO NewDeviceInfo, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForPathArrival( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForPathArrivalALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForPathRemoval( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, - _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForPathRemovalALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, - _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForPathFailing( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, - _In_ IN BOOLEAN MarkDevInfoFailed, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetLBForPathFailingALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, - _In_ IN BOOLEAN MarkDevInfoFailed, - _In_ IN ULONG SpecialHandlingFlag - ); - -NTSTATUS -DsmpSetPathForIoRetryALUA( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, - _In_ IN BOOLEAN TPGException, - _In_ IN BOOLEAN DeviceInfoException - ); - -PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY -DsmpFindFailPathDevInfoEntry( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO FailingDevInfo - ); - -PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY -DsmpBuildFailPathDevInfoEntry( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_DEVICE_INFO FailingDevInfo, - _In_ IN PDSM_DEVICE_INFO AlternateDevInfo - ); - -IO_COMPLETION_ROUTINE DsmpPhase1ProcessPathFailingALUA; - -NTSTATUS -DsmpRemoveFailPathDevInfoEntry( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY FailPathDevInfoEntry - ); - -IO_COMPLETION_ROUTINE DsmpPhase2ProcessPathFailingALUA; - -NTSTATUS -DsmpPersistentReserveOut( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ); - -__inline -BOOLEAN -DsmpIsPersistentReservationKeyZeroKey( - _In_ ULONG KeyLength, - _In_reads_bytes_(KeyLength) PUCHAR Key - ) -{ - BOOLEAN zeroKey = FALSE; - - NT_ASSERT(KeyLength == 8); - - if ((KeyLength) == 8 && - (Key[0] == 0 && Key[1] == 0 && Key[2] == 0 && Key[3] == 0 && - Key[4] == 0 && Key[5] == 0 && Key[6] == 0 && Key[7] == 0)) { - - zeroKey = TRUE; - } - - return zeroKey; -} - - -NTSTATUS -DsmpPersistentReserveIn( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN PSCSI_REQUEST_BLOCK Srb, - _In_ IN PKEVENT Event - ); - -IO_COMPLETION_ROUTINE DsmpPersistentReserveCompletion; - - -// -// Function prototypes for functions in utils.c -// - -_Success_(return != NULL) -__drv_allocatesMem(Mem) -_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) -_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) -_When_(((PoolType&0x2))!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))==0, - _Post_maybenull_ _Must_inspect_result_) -_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))!=0, - _Post_notnull_) -_When_((PoolType&NonPagedPoolMustSucceed)!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -_Post_writable_byte_size_(NumberOfBytes) -PVOID -DsmpAllocatePool( - _In_ _Strict_type_match_ IN POOL_TYPE PoolType, - _In_ IN SIZE_T NumberOfBytes, - _In_ IN ULONG Tag - ); - -_Success_(return != NULL) -_Post_maybenull_ -_Must_inspect_result_ -__drv_allocatesMem(Mem) -_Post_writable_byte_size_(*BytesAllocated) -_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) -_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) -_When_((PoolType&NonPagedPoolMustSucceed)!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -PVOID -DsmpAllocateAlignedPool( - _In_ IN POOL_TYPE PoolType, - _In_ IN SIZE_T NumberOfBytes, - _In_ IN ULONG AlignmentMask, - _In_ IN ULONG Tag, - _Out_ OUT SIZE_T *BytesAllocated - ); - -_IRQL_requires_max_(DISPATCH_LEVEL) -VOID -DsmpFreePool( - _In_opt_ __drv_freesMem(Mem) IN PVOID Block - ); - -NTSTATUS -DsmpGetStatsGatheringChoice( - _In_ IN PDSM_CONTEXT Context, - _Out_ OUT PULONG StatsGatherChoice - ); - -NTSTATUS -DsmpSetStatsGatheringChoice( - _In_ IN PDSM_CONTEXT Context, - _In_ IN ULONG StatsGatherChoice - ); - - -NTSTATUS -DsmpGetDeviceList( - _In_ IN PDSM_CONTEXT Context - ); - -_Success_(return==0) -NTSTATUS -DsmpGetStandardInquiryData( - _In_ IN PDEVICE_OBJECT DeviceObject, - _Out_ OUT PINQUIRYDATA InquiryData - ); - -BOOLEAN -DsmpCheckScsiCompliance( - _In_ IN PDEVICE_OBJECT DeviceObject, - _In_ IN PINQUIRYDATA InquiryData, - _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, - _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList - ); - -BOOLEAN -DsmpDeviceSupported( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PCSTR VendorId, - _In_ IN PCSTR ProductId - ); - -BOOLEAN -DsmpFindSupportedDevice( - _In_ IN PUNICODE_STRING DeviceName, - _In_ IN PUNICODE_STRING SupportedDevices - ); - -_Success_(return!=0) -PVOID -DsmpParseDeviceID ( - _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceID, - _In_ IN DSM_DEVID_TYPE DeviceIdType, - _In_opt_ IN PULONG IdNumber, - _Out_opt_ PSTORAGE_IDENTIFIER_CODE_SET CodeSet, - _In_ IN BOOLEAN Legacy - ); - -PUCHAR -DsmpBinaryToAscii( - _In_reads_(Length) IN PUCHAR HexBuffer, - _In_ IN ULONG Length, - _Inout_ IN OUT PULONG UpdateLength, - _In_ IN BOOLEAN Legacy - ); - -PSTR -DsmpGetSerialNumber( - _In_ IN PDEVICE_OBJECT DeviceObject - ); - - -NTSTATUS -DsmpDisableImplicitStateTransition( - _In_ IN PDEVICE_OBJECT DeviceObject, - _Out_ OUT PBOOLEAN DisableImplicit - ); - -PWSTR -DsmpBuildHardwareId( - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - -PWSTR -DsmpBuildDeviceNameLegacyPage0x80( - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ); - - -PWSTR -DsmpBuildDeviceName( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_reads_(SerialNumberLength) IN PSTR SerialNumber, - _In_ IN SIZE_T SerialNumberLength - ); - -NTSTATUS -DsmpApplyDeviceNameCorrection( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_reads_(DeviceNameLegacyLen) PWSTR DeviceNameLegacy, - _In_ IN SIZE_T DeviceNameLegacyLen, - _In_reads_(DeviceNameLen) PWSTR DeviceName, - _In_ IN SIZE_T DeviceNameLen - ); - -NTSTATUS -DsmpQueryDeviceLBPolicyFromRegistry( - _In_ PDSM_DEVICE_INFO DeviceInfo, - _In_ PWSTR RegistryKeyName, - _Inout_ PDSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Inout_ PULONGLONG PreferredPath, - _Inout_ PUCHAR ExplicitlySet - ); - -NTSTATUS -DsmpQueryTargetLBPolicyFromRegistry( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Out_ OUT PULONGLONG PreferredPath - ); - -NTSTATUS -DsmpQueryDsmLBPolicyFromRegistry( - _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Out_ OUT PULONGLONG PreferredPath - ); - -NTSTATUS -DsmpSetDsmLBPolicyInRegistry( - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ); - -NTSTATUS -DsmpSetVidPidLBPolicyInRegistry( - _In_ IN PWSTR TargetHardwareId, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ); - -NTSTATUS -DsmpOpenLoadBalanceSettingsKey( - _In_ IN ACCESS_MASK AccessMask, - _Out_ OUT PHANDLE LoadBalanceSettingsKey - ); - -NTSTATUS -DsmpOpenTargetsLoadBalanceSettingKey( - _In_ IN ACCESS_MASK AccessMask, - _Out_ OUT PHANDLE TargetsLoadBalanceSettingKey - ); - -NTSTATUS -DsmpOpenDsmServicesParametersKey( - _In_ IN ACCESS_MASK AccessMask, - _Out_ OUT PHANDLE ParametersSettingsKey - ); - -IO_COMPLETION_ROUTINE DsmpReportTargetPortGroupsSyncCompletion; - -_Success_(return==0) -NTSTATUS -DsmpReportTargetPortGroups( - _In_ PDEVICE_OBJECT DeviceObject, - _Outptr_result_buffer_maybenull_(*TargetPortGroupsInfoLength) PUCHAR *TargetPortGroupsInfo, - _Out_ PULONG TargetPortGroupsInfoLength - ); - -NTSTATUS -DsmpReportTargetPortGroupsAsync( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, - _Inout_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, - _In_ IN ULONG TargetPortGroupsInfoLength, - _Inout_ __drv_aliasesMem IN OUT PUCHAR TargetPortGroupsInfo - ); - -NTSTATUS -DsmpQueryLBPolicyForDevice( - _In_ IN PWSTR RegistryKeyName, - _In_ IN ULONGLONG PathId, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Out_ OUT PULONG PrimaryPath, - _Out_ OUT PULONG OptimizedPath, - _Out_ OUT PULONG PathWeight - ); - -VOID -DsmpGetDSMPathKeyName( - _In_ ULONGLONG DSMPathId, - _Out_writes_(DsmPathKeyNameSize) PWCHAR DsmPathKeyName, - _In_ ULONG DsmPathKeyNameSize - ); - -UCHAR -DsmpGetAsciiForBinary( - _In_ UCHAR BinaryChar - ); - -NTSTATUS -DsmpGetDeviceIdList ( - _In_ IN PDEVICE_OBJECT DeviceObject, - _Out_ OUT PSTORAGE_DESCRIPTOR_HEADER *Descriptor - ); - -NTSTATUS -DsmpSetTargetPortGroups( - _In_ IN PDEVICE_OBJECT DeviceObject, - _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, - _In_ IN ULONG TargetPortGroupsInfoLength - ); - -NTSTATUS -DsmpSetTargetPortGroupsAsync( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, - _In_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, - _In_ IN ULONG TargetPortGroupsInfoLength, - _In_ __drv_aliasesMem IN PUCHAR TargetPortGroupsInfo - ); - -PDSM_LOAD_BALANCE_POLICY_SETTINGS -DsmpCopyLoadBalancePolicies( - _In_ IN PDSM_GROUP_ENTRY GroupEntry, - _In_ IN ULONG DsmWmiVersion, - _In_ IN PVOID SupportedLBPolicies - ); - -NTSTATUS -DsmpPersistLBSettings( - _In_ IN PDSM_LOAD_BALANCE_POLICY_SETTINGS LoadBalanceSettings - ); - -NTSTATUS -DsmpSetDeviceALUAState( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN DSM_DEVICE_STATE DevState - ); - -NTSTATUS -DsmpGetDeviceALUAState( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_opt_ IN PDSM_DEVICE_STATE DevState - ); - -NTSTATUS -DsmpAdjustDeviceStatesALUA( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_opt_ IN PDSM_DEVICE_INFO PreferredActiveDeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ); - -PDSM_WORKITEM -DsmpAllocateWorkItem( - _In_ IN PDEVICE_OBJECT DeviceObject, - _In_ IN PVOID Context - ); - -VOID -DsmpFreeWorkItem( - _In_ IN PDSM_WORKITEM DsmWorkItem - ); - -VOID -DsmpFreeZombieGroupList( - _In_ IN PDSM_FAILOVER_GROUP FailGroup - ); - -NTSTATUS -DsmpRegCopyTree( - _In_ IN HANDLE SourceKey, - _In_ IN HANDLE DestKey - ); - -NTSTATUS -DsmpRegDeleteTree( - _In_ IN HANDLE KeyRoot - ); - -#if defined (_WIN64) -VOID -DsmpPassThroughPathTranslate32To64( - _In_ IN PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32, - _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64 - ); - -VOID -DsmpPassThroughPathTranslate64To32( - _In_ IN PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64, - _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32 - ); -#endif - -NTSTATUS -DsmpGetMaxPRRetryTime( - _In_ IN PDSM_CONTEXT Context, - _Out_ OUT PULONG RetryTime - ); - -NTSTATUS -DsmpQueryCacheInformationFromRegistry( - _In_ IN PDSM_CONTEXT DsmContext, - _Out_ OUT PBOOLEAN UseCacheForLeastBlocks, - _Out_ OUT PULONGLONG CacheSizeForLeastBlocks - ); - -BOOLEAN -DsmpConvertSharedSpinLockToExclusive( - _Inout_ _Requires_lock_held_(*_Curr_) PEX_SPIN_LOCK SpinLock - ); - - -// -// Function prototypes for functions in wmi.c -// - -VOID -DsmpDsmWmiInitialize( - _In_ IN PDSM_WMILIB_CONTEXT WmiGlobalInfo, - _In_ IN PUNICODE_STRING RegistryPath - ); - -NTSTATUS -DsmGlobalQueryData( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG InstanceCount, - _Inout_ IN OUT PULONG InstanceLengthArray, - _In_ IN ULONG BufferAvail, - _Out_writes_to_(BufferAvail, *DataLength) OUT PUCHAR Buffer, - _Out_ OUT PULONG DataLength, - ... - ); - -NTSTATUS -DsmGlobalSetData( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG BufferAvail, - _In_reads_bytes_(BufferAvail) IN PUCHAR Buffer, - ... - ); - -VOID -DsmpWmiInitialize( - _In_ IN PDSM_WMILIB_CONTEXT WmiInfo, - _In_ IN PUNICODE_STRING RegistryPath - ); - -NTSTATUS -DsmQueryData( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG InstanceCount, - _Inout_ IN OUT PULONG InstanceLengthArray, - _In_ IN ULONG BufferAvail, - _When_(GuidIndex == 0 || GuidIndex == 7, _Pre_notnull_ _Const_) - _When_(!(GuidIndex == 0 || GuidIndex == 7), _Out_writes_to_(BufferAvail, *DataLength)) - OUT PUCHAR Buffer, - _Out_ OUT PULONG DataLength, - ... - ); - -NTSTATUS -DsmpQueryLoadBalancePolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG DsmWmiVersion, - _In_ IN ULONG InBufferSize, - _In_ IN PULONG OutBufferSize, - _Out_writes_bytes_(*OutBufferSize) OUT PVOID Buffer - ); - -NTSTATUS -DsmpQuerySupportedLBPolicies( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG BufferAvail, - _In_ IN ULONG DsmWmiVersion, - _Out_ OUT PULONG OutBufferSize, - _Out_writes_to_(BufferAvail, *OutBufferSize) OUT PUCHAR Buffer - ); - -NTSTATUS -DsmExecuteMethod( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG MethodId, - _In_ IN ULONG InBufferSize, - _In_ IN PULONG OutBufferSize, - _Inout_ IN OUT PUCHAR Buffer, - ... - ); - -NTSTATUS -DsmpClearLoadBalancePolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds - ); - -NTSTATUS -DsmpSetLoadBalancePolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG DsmWmiVersion, - _In_ IN ULONG InBufferSize, - _In_ IN PULONG OutBufferSize, - _In_ IN PVOID Buffer - ); - -NTSTATUS -DsmpValidateSetLBPolicyInput( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG DsmWmiVersion, - _In_ IN PVOID SetLoadBalancePolicyIN, - _In_ IN ULONG InBufferSize - ); - -VOID -DsmpSaveDeviceState( - _In_ IN PVOID SupportedLBPolicies, - _In_ IN ULONG DsmWmiVersion - ); - -VOID -DsmpRestorePreviousDeviceState( - _In_ IN PVOID SupportedLBPolicies, - _In_ IN ULONG DsmWmiVersion - ); - -VOID -DsmpUpdateDesiredStateAndWeight( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN ULONG DsmWmiVersion, - _In_ IN PVOID SupportedLBPolicies - ); - -NTSTATUS -DsmpQueryDevicePerf( - _In_ PDSM_CONTEXT DsmContext, - _In_ PDSM_IDS DsmIds, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ); - -NTSTATUS -DsmpClearPerfCounters( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds - ); - -NTSTATUS -DsmpQuerySupportedDevicesList( - _In_ PDSM_CONTEXT DsmContext, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ); - -NTSTATUS -DsmpQueryTargetsDefaultPolicy( - _In_ PDSM_CONTEXT DsmContext, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ); - -NTSTATUS -DsmpQueryDsmDefaultPolicy( - _In_ PDSM_CONTEXT DsmContext, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ); - - -// -// Function prototypes for functions in debug.c -// - -VOID -DsmpDebugPrint( - _In_ ULONG DebugPrintLevel, - _In_ PCCHAR DebugMessage, - ... - ); - -// -// SRB Helpers not found in srbhelper.h -// -_Success_(return != 0) -__drv_allocatesMem(mem) -_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) -_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) -_When_(((PoolType&0x2))!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))==0, - _Post_maybenull_ _Must_inspect_result_) -_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))!=0, - _Post_notnull_ ) -__inline PSTORAGE_REQUEST_BLOCK_HEADER -SrbAllocateCopy( - _Inout_ PVOID Srb, - _In_ _Strict_type_match_ POOL_TYPE PoolType, - _In_ ULONG Tag - ) -/* - -Description: - This function returns an allocated copy of the given SRB. The memory is - allocated using DsmpAllocatePool(). - - ***It is up to the caller to free the memory returned by this function.*** - -Arguments: - Srb - A pointer to either a STORAGE_REQUEST_BLOCK or a SCSI_REQUEST_BLOCK. - PoolType - The pool type to use. See documentation for ExAllocatePoolWithTag(). - Tag - The allocation tag to use. See documentation for ExAllocatePoolWithTag(). - -Returns: - NULL, if the copy could not be allocated; or - A pointer to either a STORAGE_REQUEST_BLOCK or a SCSI_REQUEST_BLOCK that is - direct copy of the given SRB. - -*/ -{ - PSTORAGE_REQUEST_BLOCK srb = (PSTORAGE_REQUEST_BLOCK)Srb; - PSTORAGE_REQUEST_BLOCK_HEADER srbCopy = NULL; - ULONG allocationSize = 0; - - if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) - { - allocationSize = srb->SrbLength; - NT_ASSERT(allocationSize >= (sizeof(STORAGE_REQUEST_BLOCK) + sizeof(STOR_ADDR_BTL8))); - } - else - { - allocationSize = SCSI_REQUEST_BLOCK_SIZE; - NT_ASSERT(allocationSize >= sizeof(SCSI_REQUEST_BLOCK)); - } - - #pragma warning(suppress: 28160 28118) // False-positive; PoolType is simply passed through - srbCopy = (PSTORAGE_REQUEST_BLOCK_HEADER)DsmpAllocatePool(PoolType, allocationSize, Tag); - if (srbCopy != NULL) - { - RtlCopyMemory(srbCopy, Srb, allocationSize); - } - - return srbCopy; -} - -__inline -BOOLEAN DsmpIsMPIOPassThroughEx( - ULONG ControlCode - ) -// -// Returns TRUE if the given passthrough IOCTL's control code indicates it is -// an "extended" passthrough. Returns FALSE otherwise. -// -{ - if (ControlCode == IOCTL_MPIO_PASS_THROUGH_PATH_EX || - ControlCode == IOCTL_MPIO_PASS_THROUGH_PATH_DIRECT_EX) { - return TRUE; - } else { - return FALSE; - } -} - -__inline -UCHAR DsmpNtStatusToSrbStatus( - _In_ NTSTATUS Status - ) -/*++ - -Routine Description: - - Translate an NT status value into a SCSI Srb status code. - -Arguments: - - Status - Supplies the NT status code to translate. - -Return Value: - - SRB status code. - ---*/ -{ - switch (Status) { - - case STATUS_DEVICE_BUSY: - return SRB_STATUS_BUSY; - - case STATUS_INVALID_DEVICE_REQUEST: - return SRB_STATUS_BAD_FUNCTION; - - case STATUS_INSUFFICIENT_RESOURCES: - return SRB_STATUS_INTERNAL_ERROR; - - case STATUS_INVALID_PARAMETER: - return SRB_STATUS_INVALID_REQUEST; - - default: - if (NT_SUCCESS (Status)) { - return SRB_STATUS_SUCCESS; - } else { - return SRB_STATUS_ERROR; - } - } -} - - -#endif // _PROTOTYPES_H_ - diff --git a/tests/projects/wdk/wdm/msdsm/trace.h b/tests/projects/wdk/wdm/msdsm/trace.h deleted file mode 100644 index b9449cc8f..000000000 --- a/tests/projects/wdk/wdm/msdsm/trace.h +++ /dev/null @@ -1,35 +0,0 @@ - -/*++ - -Copyright (C) 2004 Microsoft Corporation - -Module Name: - - trace.h - -Abstract: - - Header file included by the Microsoft Device Specific Module (DSM). - - This file contains Windows tracing related defines. - -Environment: - - kernel mode only - -Notes: - ---*/ - -// -// Set component ID for DbgPrintEx calls -// -#define DEBUG_COMP_ID DPFLTR_MSDSM_ID - -// -// Include header file and setup GUID for tracing -// -#include -#define WPP_GUID_MSDSM (DEDADFF5, F99F, 4600, B8C9, 2D4D9B806B5B) -#define WPP_CONTROL_GUIDS WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_MSDSM) - diff --git a/tests/projects/wdk/wdm/msdsm/utils.c b/tests/projects/wdk/wdm/msdsm/utils.c deleted file mode 100644 index 91d8f44ce..000000000 --- a/tests/projects/wdk/wdm/msdsm/utils.c +++ /dev/null @@ -1,7946 +0,0 @@ - -/*++ - -Copyright (C) 2004-2010 Microsoft Corporation - -Module Name: - - utils.c - -Abstract: - - This driver is the Microsoft Device Specific Module (DSM). - It exports behaviours that mpio.sys will use to determine how to - multipath SPC-3 compliant devices. - - This file contains utility routines. - -Environment: - - kernel mode only - -Notes: - ---*/ - -#include "precomp.h" - -#ifdef DEBUG_USE_WPP -#include "utils.tmh" -#endif - -#pragma warning (disable:4305) - -extern BOOLEAN DoAssert; - -#ifdef ALLOC_PRAGMA - #pragma alloc_text(PAGE, DsmpBuildDeviceNameLegacyPage0x80) - #pragma alloc_text(PAGE, DsmpBuildDeviceName) - #pragma alloc_text(PAGE, DsmpApplyDeviceNameCorrection) - #pragma alloc_text(PAGE, DsmpOpenLoadBalanceSettingsKey) - #pragma alloc_text(PAGE, DsmpQueryLBPolicyForDevice) - #pragma alloc_text(PAGE, DsmpOpenTargetsLoadBalanceSettingKey) - #pragma alloc_text(PAGE, DsmpOpenDsmServicesParametersKey) -#endif - -_Success_(return != NULL) -__drv_allocatesMem(Mem) -_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) -_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) -_When_(((PoolType&0x2))!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))==0, - _Post_maybenull_ _Must_inspect_result_) -_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))!=0, - _Post_notnull_ ) -_When_((PoolType&NonPagedPoolMustSucceed)!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -_Post_writable_byte_size_(NumberOfBytes) -PVOID -DsmpAllocatePool( - _In_ _Strict_type_match_ IN POOL_TYPE PoolType, - _In_ IN SIZE_T NumberOfBytes, - _In_ IN ULONG Tag - ) -/*+++ - -Routine Description : - - Allocates memory from the specified pool using the given tag. - If the allocation is successful, the entire buffer will be zeroed. - -Arguements: - - PoolType - Pool to allocate from (NonPaged, Paged, etc) - NumberOfBytes - Size of the buffer to allocate - Tag - Tag (DSM_TAG_XXX) to be used for this allocation. - These tags are defined in msdsm.h - -Return Value: - - Pointer to the buffer if allocation is successful - NULL otherwise - ---*/ -{ - PVOID Block = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpAllocatePool (Tag %u): Entering function.\n", - Tag)); - - #pragma warning(suppress: 28118) // False-positive; PoolType is simply passed through - Block = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); - if (Block) { - RtlZeroMemory(Block, NumberOfBytes); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpAllocatePool (Tag %u): Exiting function with allocated block %p.\n", - Tag, - Block)); - - return Block; -} - - -_Success_(return != NULL) -_Post_maybenull_ -_Must_inspect_result_ -__drv_allocatesMem(Mem) -_Post_writable_byte_size_(*BytesAllocated) -_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) -_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) -_When_((PoolType&NonPagedPoolMustSucceed)!=0, - __drv_reportError("Must succeed pool allocations are forbidden. " - "Allocation failures cause a system crash")) -PVOID -#pragma warning(suppress:28195) // Allocation is not guaranteed, caller needs to check return value -DsmpAllocateAlignedPool( - _In_ IN POOL_TYPE PoolType, - _In_ IN SIZE_T NumberOfBytes, - _In_ IN ULONG AlignmentMask, - _In_ IN ULONG Tag, - _Out_ OUT SIZE_T *BytesAllocated - ) -/*+++ - -Routine Description : - - Allocates memory from the specified pool using the given tag and alignment requirement. - If the allocation is successful, the entire buffer will be zeroed. - -Arguements: - - PoolType - Pool to allocate from (NonPaged, Paged, etc) - NumberOfBytes - Size of the buffer to allocate - AlignmentMask - Alignment requirement specified by the device - Tag - Tag (DSM_TAG_XXX) to be used for this allocation. - These tags are defined in msdsm.h - BytesAllocated - Returns the number of bytes allocated, if the routine was successful - -Return Value: - - Pointer to the buffer if allocation is successful - NULL otherwise - ---*/ -{ - PVOID Block = NULL; - UINT_PTR align64 = (UINT_PTR)AlignmentMask; - ULONG totalSize = (ULONG)NumberOfBytes; - NTSTATUS status = STATUS_SUCCESS; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpAllocateAlignedPool (Tag %u): Entering function.\n", - Tag)); - - if (BytesAllocated == NULL) { - - status = STATUS_INVALID_PARAMETER; - goto __Exit; - } - - *BytesAllocated = 0; - - if (AlignmentMask) { - - status = RtlULongAdd((ULONG)NumberOfBytes, AlignmentMask, &totalSize); - } - - if (NT_SUCCESS(status)) { - - #pragma warning(suppress: 6014 28118) // Block isn't leaked, this function is marked as an allocator; PoolType is simply passed through - Block = ExAllocatePoolWithTag(PoolType, totalSize, Tag); - - if (Block != NULL) { - - if (AlignmentMask) { - - Block = (PVOID)(((UINT_PTR)Block + align64) & ~align64); - } - } else { - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - -__Exit: - - if (NT_SUCCESS(status)) { - - RtlZeroMemory(Block, totalSize); - *BytesAllocated = totalSize; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpAllocateAlignedPool (Tag %u): Exiting function with allocated block %p.\n", - Tag, - Block)); - - return Block; -} - - -_IRQL_requires_max_(DISPATCH_LEVEL) -VOID -DsmpFreePool( - _In_opt_ __drv_freesMem(Mem) IN PVOID Block - ) -/*+++ - -Routine Description : - - Frees the block passed in. - -Arguements: - - Block - pointer to the memory to free. - -Return Value: - - Nothing - ---*/ -{ - PVOID tempAddress = Block; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFreePool (Block %p): Entering function.\n", - Block)); - - if (Block) { - - ExFreePool(Block); - Block = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFreePool (Block %p): Exiting function.\n", - tempAddress)); - - return; -} - - -NTSTATUS -DsmpGetStatsGatheringChoice( - _In_ IN PDSM_CONTEXT Context, - _Out_ OUT PULONG StatsGatherChoice - ) -/*++ - -Routine Description: - - This routine is used to determine if the Admin wants statitics to be collected - on every IO. It queries the the services key for the value under - "msdsm\Parameters\DsmDisableStatistics" - -Arguments: - - Context - The DSM Context value. - StatsGatherChoice - Returns the choice of whether or not to gather statistics - -Return Value: - - Status of the RtlQueryRegistryValues call. - ---*/ -{ - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - WCHAR registryKeyName[56] = {0}; - NTSTATUS status = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetStatsGatherChoice (DsmCtxt %p): Entering function.\n", - Context)); - - if (!StatsGatherChoice) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_INIT, - "DsmpGetStatsGatherChoice (DsmCtxt %p): Invalid parameter - StatsGatherChoice is NULL.\n", - Context)); - - goto __Exit_DsmpGetStatsGatherChoice; - } - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - // - // Build the key value name that we want as the base of the query. - // - RtlStringCbPrintfW(registryKeyName, - sizeof(registryKeyName), - DSM_PARAMETER_PATH_W); - - // - // The query table has two entries. One for the supporteddeviceList and - // the second which is the 'NULL' terminator. - // - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_DISABLE_STATISTICS; - queryTable[0].EntryContext = StatsGatherChoice; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - registryKeyName, - queryTable, - registryKeyName, - NULL); - -__Exit_DsmpGetStatsGatherChoice: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetStatsGatherChoice (DsmCtxt %p): Exiting function with status %x.\n", - Context, - status)); - - return status; -} - - -NTSTATUS -DsmpSetStatsGatheringChoice( - _In_ IN PDSM_CONTEXT Context, - _In_ IN ULONG StatsGatherChoice - ) -/*++ - -Routine Description: - - This routine is used to set the value that indicates whether statistics will - be gathered on every IO. It updates the services key for the value under - "msdsm\Parameters\DsmDisableStatistics" - -Arguments: - - Context - The DSM Context value. - StatsGatherChoice - Value indicating whether to gather statistics (TRUE) or not (FALSE) - -Return Value: - - Status of the RtlWriteRegistryValue call. - ---*/ -{ - WCHAR registryKeyName[56] = {0}; - NTSTATUS status = STATUS_SUCCESS; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetStatsGatherChoice (DsmCtxt %p): Entering function.\n", - Context)); - - // - // Build the key value name that we want as the base of the query. - // - RtlStringCbPrintfW(registryKeyName, - sizeof(registryKeyName), - DSM_PARAMETER_PATH_W); - - - status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, - registryKeyName, - DSM_DISABLE_STATISTICS, - REG_DWORD, - &StatsGatherChoice, - sizeof(ULONG)); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetStatsGatherChoice (DsmCtxt %p): Exiting function with status %x.\n", - Context, - status)); - - return status; -} - - - -NTSTATUS -DsmpGetDeviceList( - _In_ IN PDSM_CONTEXT Context - ) -/*++ - -Routine Description: - - This routine is used to build the supported device list by querying the services - key for the values under "msdsm\Parameters\DsmSupportedDeviceList" - -Arguments: - - Context - The DSM Context value. It contains storage for the multi_sz string that may - be built. - -Return Value: - - Status of the RtlQueryRegistryValues call. - ---*/ -{ - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - WCHAR registryKeyName[56] = {0}; - UNICODE_STRING inquiryStrings; - WCHAR defaultIDs[] = { L"\0" }; - NTSTATUS status; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetDeviceList (DsmCtxt %p): Entering function.\n", - Context)); - - RtlZeroMemory(queryTable, sizeof(queryTable)); - RtlInitUnicodeString(&inquiryStrings, NULL); - - // - // Build the key value name that we want as the base of the query. - // - RtlStringCbPrintfW(registryKeyName, - sizeof(registryKeyName), - DSM_PARAMETER_PATH_W); - - // - // The query table has two entries. One for the supporteddeviceList and - // the second which is the 'NULL' terminator. - // - // Indicate that there is NO call-back routine, and to give back the MULTI_SZ as - // one blob, as opposed to individual unicode strings. - // - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_TYPECHECK; - - // - // The value to query. - // - queryTable[0].Name = DSM_SUPPORTED_DEVICELIST_VALUE_NAME; - - // - // Where to put the strings. Note that we need to use an empty unicode_string - // for the query or else RtlQueryRegistryValues will only fill in enough - // entries as specified by the size of the unicode string's buffer, which - // is why we can't use Context->SupportedDevices directly in the call. - // - queryTable[0].EntryContext = &inquiryStrings; - queryTable[0].DefaultType = (REG_MULTI_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_MULTI_SZ; - queryTable[0].DefaultData = defaultIDs; - queryTable[0].DefaultLength = sizeof(defaultIDs); - - status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - registryKeyName, - queryTable, - registryKeyName, - NULL); - - // - // If we successfully queried for the supported device list, we need to delete - // our cached list and update it with this new one. - // - if (NT_SUCCESS(status)) { - - KIRQL oldIrql; - PWCHAR tempBuffer = NULL; - - tempBuffer = DsmpAllocatePool(NonPagedPoolNx, inquiryStrings.MaximumLength, DSM_TAG_REG_VALUE_RELATED); - - // - // This is a "best effort" operation. If we are unable to allocate a - // buffer for the strings, we just continue using our old cached list. - // We do NOT fall back to using inquiryStrings's buffer as we want to - // be able to work with the supported devices list at raised IRQL. - // - if (tempBuffer) { - - RtlCopyMemory(tempBuffer, inquiryStrings.Buffer, inquiryStrings.Length); - - KeAcquireSpinLock(&Context->SupportedDevicesListLock, &oldIrql); - DsmpFreePool(Context->SupportedDevices.Buffer); - Context->SupportedDevices.Buffer = tempBuffer; - Context->SupportedDevices.Length = inquiryStrings.Length; - Context->SupportedDevices.MaximumLength = inquiryStrings.MaximumLength; - KeReleaseSpinLock(&Context->SupportedDevicesListLock, oldIrql); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetDeviceList (DsmCtxt %p): Failed to allocate supported device list's buffer.\n", - Context)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - - ExFreePool(inquiryStrings.Buffer); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetDeviceList (DsmCtxt %p): Exiting function with status %x.\n", - Context, - status)); - - return status; -} - - -_Success_(return==0) -NTSTATUS -DsmpGetStandardInquiryData( - _In_ IN PDEVICE_OBJECT DeviceObject, - _Out_ OUT PINQUIRYDATA InquiryData - ) -/*++ - -Routine Description: - - Helper routine to send an inquiry with EVPD cleared to get the standard inquiry data. - -Arguments: - - DeviceObject - The port PDO to which the command should be sent. - InquiryData - Pointer to inquiry data that will be returned to caller. - -Return Value: - - STATUS_SUCCESS or failure NTSTATUS code. - ---*/ -{ - PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; - PCDB cdb; - IO_STATUS_BLOCK ioStatus; - ULONG length; - NTSTATUS status = STATUS_SUCCESS; - PINQUIRYDATA inquiryData; - PSENSE_DATA senseData; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetStandardInquiryData (DevObj %p): Entering function.\n", - DeviceObject)); - - if (InquiryData == NULL) { - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpGetStandardInquiryData; - } - - // - // Build a standard inquiry command. - // - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - passThrough = DsmpAllocatePool(NonPagedPoolNx, - length, - DSM_TAG_PASS_THRU); - if (!passThrough) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetStandardInquiryData (DevObj %p): Failed to allocate mem for passthrough.\n", - DeviceObject)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpGetStandardInquiryData; - } - -__Retry_Request: - - // - // Build the cdb for SCSI-3 standard inquiry. - // - cdb = (PCDB)passThrough->ScsiPassThrough.Cdb; - cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY; - cdb->CDB6INQUIRY3.EnableVitalProductData = 0; - cdb->CDB6INQUIRY3.AllocationLength = sizeof(INQUIRYDATA); - - passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); - passThrough->ScsiPassThrough.CdbLength = 6; - passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; - passThrough->ScsiPassThrough.DataIn = 1; - passThrough->ScsiPassThrough.DataTransferLength = sizeof(INQUIRYDATA); - passThrough->ScsiPassThrough.TimeOutValue = 20; - passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); - passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); - - DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, - DeviceObject, - passThrough, - passThrough, - length, - length, - FALSE, - &ioStatus); - - status = ioStatus.Status; - senseData = (PSENSE_DATA)(passThrough->SenseInfoBuffer); - - if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(status))) { - - // - // Get the returned data. - // - inquiryData = (PINQUIRYDATA)(passThrough->DataBuffer); - - RtlCopyMemory(InquiryData, inquiryData, sizeof(INQUIRYDATA)); - - } else if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_CHECK_CONDITION) && - (NT_SUCCESS(ioStatus.Status)) && - (DsmpShouldRetryPassThroughRequest(senseData, passThrough->ScsiPassThrough.SenseInfoLength))) { - - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - // - // Retry the request - // - RtlZeroMemory(passThrough, length); - goto __Retry_Request; - - } else { - - // Failed to get inquiry data - // Here it is possible that status is success, but scsi status is not. - // If so, set status to unsuccessful. - if (NT_SUCCESS(status)){ - status = STATUS_UNSUCCESSFUL; - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetStandardInquiryData (DevObj %p): NTStatus 0x%x, ScsiStatus 0x%x.\n", - DeviceObject, - status, - passThrough->ScsiPassThrough.ScsiStatus)); - } - -__Exit_DsmpGetStandardInquiryData: - - // - // Free the passthrough + data buffer. - // - if (passThrough) { - DsmpFreePool(passThrough); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetStandardInquiryData (DevObj %p): Exiting function with status %x.\n", - DeviceObject, - status)); - - return status; -} - - -BOOLEAN -DsmpCheckScsiCompliance( - _In_ IN PDEVICE_OBJECT TargetObject, - _In_ IN PINQUIRYDATA InquiryData, - _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, - _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList - ) -/*++ - -Routine Description: - - Helper routine to determine if the device is SPC-3 compliant. - -Arguments: - - DeviceObject - The port PDO that we're determining compliance for. - InquiryData - Pointer to its inquiry data. - Descriptor - Pointer to its VPD page 0x80 data - DeviceIdList - Pointer to its VPD page 0x83 data - -Return Value: - - TRUE if compliant, else FALSE. - ---*/ -{ - BOOLEAN supported = FALSE /* TRUE */; - UCHAR deviceType; - UCHAR qualifier; - - UNREFERENCED_PARAMETER(DeviceIdList); - UNREFERENCED_PARAMETER(Descriptor); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpCheckScsiCompliance (DevObj %p): Entering function.\n", - TargetObject)); - - deviceType = InquiryData->DeviceType & 0x1F; - qualifier = (InquiryData->DeviceTypeQualifier >> 0x5) & 0x7; - - if ((deviceType | qualifier) == 0x7F) { - - supported = FALSE; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpCheckScsiCompliance (DevObj %p): Exiting function with Supported = %u.\n", - TargetObject, - supported)); - - return supported; -} - - -BOOLEAN -DsmpDeviceSupported( - _In_ IN PDSM_CONTEXT Context, - _In_ IN PCSTR VendorId, - _In_ IN PCSTR ProductId - ) -/*++ - -Routine Description: - - This routine determines whether the device is supported by traversing the SupportedDevice - list and comparing to the VendorId/ProductId values passed in. - -Arguments: - - Context - Context value given to the multipath driver during registration. - VendorId - Pointer to the inquiry data VendorId. - ProductId - Pointer to the inquiry data ProductId. - -Return Value: - - TRUE - If VendorId/ProductId is found. - ---*/ -{ - UNICODE_STRING deviceName; - UNICODE_STRING productName; - ANSI_STRING ansiVendor; - ANSI_STRING ansiProduct; - NTSTATUS status; - BOOLEAN supported = FALSE; - KIRQL oldIrql; - UNICODE_STRING tempStrings; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpDeviceSupported (DsmCtxt %p): Entering function.\n", - Context)); - - KeAcquireSpinLock(&Context->SupportedDevicesListLock, &oldIrql); - - RtlInitUnicodeString(&tempStrings, NULL); - tempStrings.Buffer = DsmpAllocatePool(NonPagedPoolNx, Context->SupportedDevices.MaximumLength, DSM_TAG_REG_VALUE_RELATED); - - if (tempStrings.Buffer) { - - RtlCopyMemory(tempStrings.Buffer, Context->SupportedDevices.Buffer, Context->SupportedDevices.Length); - tempStrings.Length = Context->SupportedDevices.Length; - tempStrings.MaximumLength = Context->SupportedDevices.MaximumLength; - - } else { - - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpDeviceSupported (DsmCtxt %p): Failed to allocate temporary list (error %x).\n", - Context, - status)); - - KeReleaseSpinLock(&Context->SupportedDevicesListLock, oldIrql); - - goto __Exit_DsmpDeviceSupported; - } - - KeReleaseSpinLock(&Context->SupportedDevicesListLock, oldIrql); - - // - // The SupportedDevice list was built in DriverEntry from the services key. - // - if (tempStrings.MaximumLength == 0) { - - // - // List is empty. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDeviceSupported (DsmCtxt %p): No supported Device in the list.\n", - Context)); - - goto __Exit_DsmpDeviceSupported; - } - - RtlInitUnicodeString(&productName, NULL); - - // - // Convert the inquiry fields into ansi strings. - // - RtlInitAnsiString(&ansiVendor, VendorId); - RtlInitAnsiString(&ansiProduct, ProductId); - - // - // Allocate the deviceName buffer. Needs to be 8+16 plus NULL. - // (productId length + vendorId length + NULL). - // - deviceName.MaximumLength = 25 * sizeof(WCHAR); - deviceName.Buffer = DsmpAllocatePool(PagedPool, deviceName.MaximumLength, DSM_TAG_SUPPORTED_DEV); - - if (deviceName.Buffer) { - - // - // Convert the vendorId to unicode. - // - status = RtlAnsiStringToUnicodeString(&deviceName, &ansiVendor, FALSE); - if (NT_SUCCESS(status)) { - - // - // Convert the productId to unicode. - // - status = RtlAnsiStringToUnicodeString(&productName, &ansiProduct, TRUE); - - if (NT_SUCCESS(status)) { - - // - // 'cat' them. - // - status = RtlAppendUnicodeStringToString(&deviceName, &productName); - - if (NT_SUCCESS(status)) { - - // - // Run the list of supported devices that was captured from the registry - // and see if this one is in the list. - // - supported = DsmpFindSupportedDevice(&deviceName, - &tempStrings); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDeviceSupported (DsmCtxt %p): Failed to append product name. Status %x.\n", - Context, - status)); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDeviceSupported (DsmCtxt %p): Failed to convert ansi vendor string to unicode. Status %x\n", - Context, - status)); - } - - DsmpFreePool(deviceName.Buffer); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDeviceSupported (DsmCtxt %p): Failed to allocate device name buffer.\n", - Context)); - } - -__Exit_DsmpDeviceSupported: - - if (tempStrings.Buffer) { - DsmpFreePool(tempStrings.Buffer); - } - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpDeviceSupported (DsmCtxt %p): Exiting function with supported = %u.\n", - Context, - supported)); - - return supported; -} - - -BOOLEAN -DsmpFindSupportedDevice( - _In_ IN PUNICODE_STRING DeviceName, - _In_ IN PUNICODE_STRING SupportedDevices - ) -/*++ - -Routine Description: - - This routine compares the two unicode strings for a match. - -Arguments: - - DeviceName - String built from the current device's inquiry data. - SupportedDevices - MULTI_SZ of devices that are supported. - -Return Value: - - TRUE - If VendorId/ProductId is found. - ---*/ -{ - PWSTR devices = SupportedDevices->Buffer; - ULONG bufferLengthLeft = SupportedDevices->MaximumLength / sizeof(WCHAR); - UNICODE_STRING unicodeString; - USHORT originalLength = DeviceName->Length; - LONG compare; - BOOLEAN supported = FALSE; - WCHAR tempString[32]; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFindSupportedDevice (DevName %ws): Entering function.\n", - DeviceName->Buffer)); - - // - // 'devices' is the current buffer in the MULTI_SZ built from - // the registry. - // - while (devices[0]) { - - RtlZeroMemory(tempString, sizeof(tempString)); - - if (!NT_SUCCESS(RtlStringCchCopyNW(tempString, sizeof(tempString) / sizeof(tempString[0]), devices, bufferLengthLeft))) { - - tempString[(sizeof(tempString) / sizeof(tempString)) - 1] = L'\0'; - } - - // - // Make the current entry into a unicode string. - // - RtlInitUnicodeString(&unicodeString, tempString); - - // - // Compare this one with the current device. - // However, for storages that make up the product id on-the-fly, MPIO - // allows for matching based just on substring (product-id-prefix so to - // speak). - // - if (unicodeString.Length < DeviceName->Length) { - DeviceName->Length = unicodeString.Length; - } - - compare = RtlCompareUnicodeStrings(unicodeString.Buffer, - unicodeString.Length / sizeof(WCHAR), - DeviceName->Buffer, - DeviceName->Length / sizeof(WCHAR), - TRUE); - - DeviceName->Length = originalLength; - - if (compare == 0) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpFindSupportedDevice (DevName %ws): Device support found in the registry.\n", - DeviceName->Buffer)); - - supported = TRUE; - break; - } - - // - // Advance to next entry in the MULTI_SZ. - // - devices += (unicodeString.MaximumLength / sizeof(WCHAR)); - - bufferLengthLeft -= (unicodeString.MaximumLength / sizeof(WCHAR)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpFindSupportedDevice (DevName %ws): Exiting function with Supported = %u.\n", - DeviceName->Buffer, - supported)); - - return supported; -} - -_Success_(return!=0) -PVOID -DsmpParseDeviceID( - _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceID, - _In_ IN DSM_DEVID_TYPE DeviceIdType, - _In_opt_ IN PULONG IdNumber, - _Out_opt_ OUT PSTORAGE_IDENTIFIER_CODE_SET CodeSet, - _In_ IN BOOLEAN Legacy - ) -/*++ - -Routine Description: - - This routine builds a serial number string based on the information - in the VPD page 0x83 data if serial number is requested, else it - returns the appropriate identifier requested. - - Caller must free the buffer. - -Arguments: - - DeviceIdList - VPD Page 0x83 information. - DeviceIdType - Type of identifier that the DeviceID is being parsed for - IdNumber - If there are multiple identifiers of type DeviceIdType, this parameter - determines which among them to actually return. - IMPORTANT: This number is one-based (not zero-based). - CodeSet - Of relevance only if the DeviceIdType is DSM_DEVID_SERIAL_NUMBER. This - returns the code set that was used when building the serial number. - Legacy - Of relevance only if the DeviceIdType is DSM_DEVID_SERIAL_NUMBER. If the - code set of the identifier is StorageIdCodeSetBinary, this determines - whether to use the legacy method of binary to ascii conversion. - -Return Value: - - Requested Device identifier. - ---*/ -{ - PSTORAGE_IDENTIFIER identifier; - STORAGE_IDENTIFIER_CODE_SET codeSet = StorageIdCodeSetReserved; // Preload with a bogus value. - STORAGE_IDENTIFIER_TYPE type = 0xF; - STORAGE_ASSOCIATION_TYPE association = 0xF; - ULONG numberIds; - ULONG i; - ULONG identifierSize = 0; - PUCHAR bytes = NULL; - PVOID buffer = NULL; - BOOLEAN done = FALSE; - ULONG idNumber = MAXULONG; - ULONG matches = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpParseDeviceID (DevIdDesc %p): Entering function - IdType %x.\n", - DeviceID, - DeviceIdType)); - - if (IdNumber) { - idNumber = *IdNumber; - } - - // - // Get the number of encapsulated identifiers. - // - numberIds = DeviceID->NumberOfIdentifiers; - - if (idNumber != MAXULONG && idNumber > numberIds) { - goto __Exit_DsmpParseDeviceID; - } - - // - // Get a pointer to the first one. - // - identifier = (PSTORAGE_IDENTIFIER)(DeviceID->Identifiers); - - for (i = 0; i < numberIds && !done; i++) { - - switch (DeviceIdType) { - - case DSM_DEVID_SERIAL_NUMBER: { - - // - // The way this works is that we will go through all the identifiers - // Order of preference will be LUN-associated over Target-associated. - // Further, upon same association, preference will be based on type as - // follows: 0x8, 0x3, 0x2, 0x1, 0x0. - // So an existing identifier will be discarded if a better one is found. - // If two identifiers have the same type, we will prefer the one will - // the larger length. - // - - // - // 1. Ensure that the association is for either the LUN or target. (If neither, ignore id). - // 2. If association is with target, don't it consider if current candidate has assocation with LUN. - // 3. If considering this identifier, order of preference is 8 > 3 > 2 > 1 > 0. - // 4. If this id type is same as current candidate, consider it only if it is of greater length. - // - if (((identifier->Association == StorageIdAssocDevice) || - (identifier->Association == 0x2 && association != StorageIdAssocDevice)) && - ((type == identifier->Type && identifierSize < identifier->IdentifierSize) || - (type != identifier->Type && DsmpIsPreferredDeviceId(type, identifier->Type)))) { - - // - // Get a pointer to the id itself. - // - bytes = identifier->Identifier; - - // - // The id's size. - // - identifierSize = identifier->IdentifierSize; - - // - // Get the type, code set, and association. - // - type = identifier->Type; - codeSet = identifier->CodeSet; - association = identifier->Association; - - matches++; - } - - break; - } - - case DSM_DEVID_RELATIVE_TARGET_PORT: { - - // - // Ensure that the association is for the target port. - // - if (identifier->Association != StorageIdAssocPort) { - - if ((i + 1) < numberIds) { - identifier = (PSTORAGE_IDENTIFIER)((PUCHAR)identifier + identifier->NextOffset); - } - - continue; - } - - if (identifier->Type == StorageIdTypePortRelative) { - - // - // Get a pointer to the id itself. - // - bytes = identifier->Identifier; - - // - // The id's size. - // - identifierSize = identifier->IdentifierSize; - - type = identifier->Type; - codeSet = identifier->CodeSet; - association = identifier->Association; - - matches++; - } - - break; - } - - case DSM_DEVID_TARGET_PORT_GROUP: { - - // - // Ensure that the association is for the target port. - // - if (identifier->Association != StorageIdAssocPort) { - - if ((i + 1) < numberIds) { - identifier = (PSTORAGE_IDENTIFIER)((PUCHAR)identifier + identifier->NextOffset); - } - - continue; - } - - if (identifier->Type == 0x5) { - - // - // Get a pointer to the id itself. - // - bytes = identifier->Identifier; - - // - // Move this by two bytes because first two bytes are reservered - // - bytes += sizeof(USHORT); - - // - // The id's size. Reduce the size by 2 bytes (to account - // for the reservered bytes) - // - identifierSize = identifier->IdentifierSize - sizeof(USHORT); - - type = identifier->Type; - codeSet = identifier->CodeSet; - association = identifier->Association; - - matches++; - } - - break; - } - - default: break; - } - - - if (idNumber != MAXULONG && idNumber == matches) { - done = TRUE; - } - - // - // Advance to the next identifier in the buffer. - // - if ((i + 1) < numberIds) { - identifier = (PSTORAGE_IDENTIFIER)((PUCHAR)identifier + identifier->NextOffset); - } - } - - if (idNumber != MAXULONG && idNumber > matches) { - goto __Exit_DsmpParseDeviceID; - } - - if (DeviceIdType == DSM_DEVID_SERIAL_NUMBER) { - - if (type != StorageIdTypeScsiNameString && - type != StorageIdTypeFCPHName && - type != StorageIdTypeEUI64 && - type != StorageIdTypeVendorId && - type != StorageIdTypeVendorSpecific) { - - DSM_ASSERT(FALSE); - bytes = NULL; - identifierSize = 0; - type = association = 0xF; - codeSet = StorageIdCodeSetReserved; - } - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpParseDeviceID (DevIdDesc %p): IdentifierSize = %u, Type = %u, Association = %u, CodeSet = %u.\n", - DeviceID, - identifierSize, - type, - association, - codeSet)); - - if (!bytes) { - goto __Exit_DsmpParseDeviceID; - } - - if (codeSet == StorageIdCodeSetBinary) { - - // - // Need to convert to ascii. - // - buffer = DsmpBinaryToAscii(bytes, - identifierSize, - &identifierSize, - Legacy); - - } else { - - if (identifierSize) { - // - // Allocate a buffer that is the size of the data, plus one for NULL. - // - buffer = DsmpAllocatePool(NonPagedPoolNx, identifierSize + 1, DSM_TAG_DEV_ID); - DSM_ASSERT(buffer); - - if (buffer) { - - // - // Copy over the id. - // - RtlCopyMemory(buffer, bytes, identifierSize); - } - } - } - - if (CodeSet) { - *CodeSet = codeSet; - } - - } else { - - if (identifierSize) { - - DSM_ASSERT((DeviceIdType == DSM_DEVID_RELATIVE_TARGET_PORT && identifierSize == sizeof(ULONG)) || - (DeviceIdType == DSM_DEVID_TARGET_PORT_GROUP && identifierSize == sizeof(USHORT))); - - _Analysis_assume_((DeviceIdType == DSM_DEVID_RELATIVE_TARGET_PORT && identifierSize == sizeof(ULONG)) || - (DeviceIdType == DSM_DEVID_TARGET_PORT_GROUP && identifierSize == sizeof(USHORT))); - - buffer = DsmpAllocatePool(NonPagedPoolNx, identifierSize, DSM_TAG_DEV_ID); - - if (buffer) { - - if (DeviceIdType == DSM_DEVID_RELATIVE_TARGET_PORT) { - - GetUlongFrom4ByteArray(bytes, *((PULONG)buffer)); - - } else if (DeviceIdType == DSM_DEVID_TARGET_PORT_GROUP) { - - *((PUSHORT)buffer) = (bytes[0] << 8) | (bytes[1]); - } - } - } - } - -__Exit_DsmpParseDeviceID: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpParseDeviceID (DevIdDesc %p): Exiting function with buffer %p.\n", - DeviceID, - buffer)); - - return buffer; -} - - -PUCHAR -DsmpBinaryToAscii( - _In_reads_(Length) IN PUCHAR HexBuffer, - _In_ IN ULONG Length, - _Inout_ IN OUT PULONG UpdateLength, - _In_ IN BOOLEAN Legacy - ) -/*++ - -Routine Description: - - This routine will convert HexBuffer into an ascii NULL-terminated string. - - Note: This routine will allocate memory for storing the ascii string. It is - the responsibility of the caller to free this buffer. - -Arguments: - - HexBuffer - Pointer to the binary data. - Length - Length, in bytes, of HexBuffer. - UpdateLength - Storage to place the actual length of the returned string. - Legacy - Use the legacy method for the conversion. - -Return Value: - - Serial Number string, or NULL if an error occurred. - ---*/ -{ - static UCHAR IntegerTable[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - ULONG i; - ULONG j; - ULONG actualLength; - PUCHAR buffer = NULL; - UCHAR highWord; - UCHAR lowWord; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBinaryToAscii (HexBuff %p): Entering function.\n", - HexBuffer)); - - if (Length == 0) { - *UpdateLength = 0; - goto __Exit_DsmpBinaryToAscii; - } - - if (Legacy) { - // - // Do a pre-test on the buffer to determine the length actually needed. - // - for (i = 0, actualLength = 0; i < Length; i++) { - - if (HexBuffer[i] < 0x10) { - actualLength++; - } else { - actualLength += 2; - } - } - - // - // Add room for a terminating NULL. - // - actualLength++; - } else { - // - // We need one character for each nibble, plus one for the terminating NULL. - // - actualLength = (Length * 2) + 1; - } - - // - // Allocate the buffer. - // - buffer = DsmpAllocatePool(NonPagedPoolNx, - actualLength, - DSM_TAG_BIN_TO_ASCII); - if (!buffer) { - *UpdateLength = 0; - goto __Exit_DsmpBinaryToAscii; - } - - for (i = 0, j = 0; i < Length && j < actualLength; i++) { - - if (Legacy && (HexBuffer[i] < 0x10)) { - - // - // If legacy is mentioned and it's 0x0F or less, - // just convert the entire byte. - // - buffer[j++] = IntegerTable[HexBuffer[i]]; - } else { - - // - // Split out each nibble from the binary byte. - // - highWord = HexBuffer[i] >> 4; - lowWord = HexBuffer[i] & 0x0F; - - // - // Using the lookup table, convert and stuff into - // the ascii buffer. - // - buffer[j++] = IntegerTable[highWord]; - buffer[j++] = IntegerTable[lowWord]; - } - } - - // - // Update the caller's length field. - // - *UpdateLength = actualLength; - -__Exit_DsmpBinaryToAscii: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBinaryToAscii (HexBuff %p): Exiting function with buffer %s.\n", - HexBuffer, - (const char*) buffer)); - - return buffer; -} - - -PSTR -DsmpGetSerialNumber( - _In_ IN PDEVICE_OBJECT DeviceObject - ) -/*++ - -Routine Description: - - Helper routine to send an inquiry with EVPD set to get the serial number page. - Used if the serial number is not embedded in the device descriptor (this device probably - doesn't support VPD page 0x00). - - Note: This routine will allocate memory for storing the serial number. It is - the responsibility of the caller to free this buffer. - -Arguments: - - DeviceObject - The port PDO to which the command should be sent. - -Return Value: - - The serial number (null-terminated string) or NULL if the call fails. - ---*/ -{ - PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; - PVPD_SERIAL_NUMBER_PAGE serialPage; - PCDB cdb; - PSTR serialNumber = NULL; - IO_STATUS_BLOCK ioStatus; - ULONG length; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetSerialNumber (DevObj %p): Entering function.\n", - DeviceObject)); - - // - // Build an inquiry command with EVPD and pagecode of 0x80 (serial number). - // - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - passThrough = DsmpAllocatePool(NonPagedPoolNx, - length, - DSM_TAG_PASS_THRU); - if (!passThrough) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetSerialNumber (DevObj %p): Failed to allocate mem for passthrough.\n", - DeviceObject)); - - goto __Exit_DsmpGetSerialNumber; - } - - // - // Build the cdb. - // - cdb = (PCDB)passThrough->ScsiPassThrough.Cdb; - cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY; - cdb->CDB6INQUIRY.Reserved1 = 1; - cdb->CDB6INQUIRY.PageCode = VPD_SERIAL_NUMBER; - cdb->CDB6INQUIRY.AllocationLength = DSM_SERIAL_NUMBER_BUFFER_SIZE; - - passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); - passThrough->ScsiPassThrough.CdbLength = 6; - passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; - passThrough->ScsiPassThrough.DataIn = 1; - passThrough->ScsiPassThrough.DataTransferLength = DSM_SERIAL_NUMBER_BUFFER_SIZE; - passThrough->ScsiPassThrough.TimeOutValue = 20; - passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); - passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); - - DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, - DeviceObject, - passThrough, - passThrough, - length, - length, - FALSE, - &ioStatus); - if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && - (NT_SUCCESS(ioStatus.Status))) { - - ULONG inx; - - // - // Get the returned data. - // - serialPage = (PVPD_SERIAL_NUMBER_PAGE)(passThrough->DataBuffer); - - // - // Allocate a buffer to hold just the serial number plus a null terminator - // - serialNumber = DsmpAllocatePool(NonPagedPoolNx, - serialPage->PageLength + 1, - DSM_TAG_SERIAL_NUM); - if (serialNumber) { - - // - // Copy it over. - // - RtlCopyMemory(serialNumber, serialPage->SerialNumber, serialPage->PageLength); - - // - // Some devices return binary data for the serial number. - // Convert to a more ascii-ish format so that other routines don't have a problem. - // - for (inx = 0; inx < serialPage->PageLength; inx++) { - if (serialNumber[inx] == '\0') { - serialNumber[inx] = ' '; - } - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetSerialNumber (DevObj %p): Failed to allocate mem for serialnumber.\n", - DeviceObject)); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetSerialNumber (DevObj %p): NTStatus 0%x, ScsiStatus 0x%x.\n", - DeviceObject, - ioStatus.Status, - passThrough->ScsiPassThrough.ScsiStatus)); - } - -__Exit_DsmpGetSerialNumber: - - // - // Free the passthrough + data buffer. - // - if (passThrough) { - - DsmpFreePool(passThrough); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetSerialNumber (DevObj %p): Exiting function with serial number %s.\n", - DeviceObject, - (const char*)serialNumber)); - - // - // Return the sn. - // - return serialNumber; -} - - -NTSTATUS -DsmpDisableImplicitStateTransition( - _In_ IN PDEVICE_OBJECT TargetDevice, - _Out_ OUT PBOOLEAN DisableImplicit - ) -/*++ - -Routine Description: - - Send down request to disable implicit ALUA state transition. - The function first sends down a mode sense to get the control extension mode - sense data. It then clears the IALUAE bit and sends down a mode select. - -Arguements: - - TargetDevice - Device object that will be target of this command. - DisableImplicit - Flag returned to the caller to indicate whether or not - implicit transitions are disabled. - -Return Value : - - STATUS_SUCCESS if the command succeeds. - Appropriate NTSTATUS code on failure - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; - PCDB cdb; - IO_STATUS_BLOCK ioStatus; - ULONG length; - PSPC3_CONTROL_EXTENSION_MODE_PAGE controlExtensionPage = NULL; - PSENSE_DATA senseData = NULL; - BOOLEAN implicitDisabled = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): Entering function.\n", - TargetDevice)); - - // - // First build the mode sense command to get the control extension parameters. - // - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - passThrough = DsmpAllocatePool(NonPagedPoolNx, - length, - DSM_TAG_PASS_THRU); - if (!passThrough) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): Failed to allocate mem for passthrough.\n", - TargetDevice)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpDisableImplicitStateTransition; - } - -__Retry_ModeSense: - - passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); - passThrough->ScsiPassThrough.CdbLength = 6; - passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; - passThrough->ScsiPassThrough.DataIn = 1; - passThrough->ScsiPassThrough.DataTransferLength = sizeof(SPC3_CONTROL_EXTENSION_MODE_PAGE); - passThrough->ScsiPassThrough.TimeOutValue = 20; - passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); - passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); - - // - // Build the cdb for mode sense. - // - cdb = (PCDB)passThrough->ScsiPassThrough.Cdb; - cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; - cdb->MODE_SENSE.Dbd = 1; - cdb->MODE_SENSE.PageCode = 0xA; - cdb->MODE_SENSE.SubPageCode = 0x01; - cdb->MODE_SENSE.AllocationLength = sizeof(SPC3_CONTROL_EXTENSION_MODE_PAGE); - - DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, - TargetDevice, - passThrough, - passThrough, - length, - length, - FALSE, - &ioStatus); - - status = ioStatus.Status; - senseData = (PSENSE_DATA)(passThrough->SenseInfoBuffer); - - if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(status))) { - - controlExtensionPage = (PSPC3_CONTROL_EXTENSION_MODE_PAGE)(passThrough->DataBuffer); - - if (controlExtensionPage->ImplicitALUAEnable) { - - controlExtensionPage->ImplicitALUAEnable = 0; - -__Retry_ModeSelect: - - RtlZeroMemory(passThrough->SenseInfoBuffer, passThrough->ScsiPassThrough.SenseInfoLength); - - passThrough->ScsiPassThrough.DataIn = 0; - - // - // Build the cdb for mode select. - // - RtlZeroMemory(cdb, 6); - cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; - cdb->MODE_SELECT.SPBit = 0; - cdb->MODE_SELECT.PFBit = 1; - cdb->MODE_SELECT.ParameterListLength = sizeof(SPC3_CONTROL_EXTENSION_MODE_PAGE); - - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, - TargetDevice, - passThrough, - passThrough, - length, - length, - FALSE, - &ioStatus); - - status = ioStatus.Status; - senseData = (PSENSE_DATA)(passThrough->SenseInfoBuffer); - - if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(status))) { - - implicitDisabled = TRUE; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): Implicit transitions turned off successfully.\n", - TargetDevice)); - - } else if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_CHECK_CONDITION) && - (NT_SUCCESS(status)) && - (DsmpShouldRetryPassThroughRequest(senseData, passThrough->ScsiPassThrough.SenseInfoLength))) { - - // - // Retry the request - // - goto __Retry_ModeSelect; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): ModeSelect failed - NTStatus 0x%x, ScsiStatus 0x%x.\n", - TargetDevice, - status, - passThrough->ScsiPassThrough.ScsiStatus)); - } - } else { - - implicitDisabled = TRUE; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): Implicit transitions already turned OFF.\n", - TargetDevice)); - } - } else if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_CHECK_CONDITION) && - (NT_SUCCESS(status)) && - (DsmpShouldRetryPassThroughRequest(senseData, passThrough->ScsiPassThrough.SenseInfoLength))) { - - length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); - - // - // Retry the request - // - RtlZeroMemory(passThrough, length); - goto __Retry_ModeSense; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): ModeSense failed - NTStatus 0x%x, ScsiStatus 0x%x.\n", - TargetDevice, - status, - passThrough->ScsiPassThrough.ScsiStatus)); - } - -__Exit_DsmpDisableImplicitStateTransition: - - // - // Free the passthrough + data buffer. - // - if (passThrough) { - DsmpFreePool(passThrough); - } - - // - // Return whether IALUAE is set to 0. - // - if (DisableImplicit) { - - *DisableImplicit = implicitDisabled; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpDisableImplicitStateTransition (DevObj %p): Exiting function with status %x.\n", - TargetDevice, - status)); - - return status; -} - - -PWSTR -DsmpBuildHardwareId( - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - Construct a string concatinating VendorId with ProductId. - -Arguements: - - DeviceInfo - Device Extension - -Return Value : - - NULL terminated hardware id if it was built successfully. - NULL in case of failure. - ---*/ -{ - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; - PWSTR hardwareId = NULL; - SIZE_T vendorIDLength = 0; - SIZE_T productIDLength = 0; - PCSZ vendorIdOffset; - PCSZ productIdOffset; - SIZE_T sizeNeeded; - NTSTATUS status = STATUS_SUCCESS; - ANSI_STRING ansiString; - UNICODE_STRING unicodeString; - ULONG offset; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): Entering function.\n", - DeviceInfo)); - - deviceDescriptor = &(DeviceInfo->Descriptor); - - // - // Save the vendorid and productid offset in Device Descriptor - // - offset = deviceDescriptor->ProductIdOffset; - if ((offset != 0) && (offset != MAXULONG)) { - - productIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - offset = deviceDescriptor->VendorIdOffset; - if ((offset != 0) && (offset != MAXULONG)) { - - vendorIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - if (!vendorIDLength || !productIDLength) { - - status = STATUS_UNSUCCESSFUL; - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): Invalid vendor and/or product id.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildHardwareId; - } - - sizeNeeded = vendorIDLength + productIDLength; - hardwareId = DsmpAllocatePool(NonPagedPoolNx, sizeNeeded, DSM_TAG_DEV_HARDWARE_ID); - if (!hardwareId) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): Failed to allocate memory for device name.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpBuildHardwareId; - } - - // - // Build the NULL terminated hardwareId whose format is : - // - // VendorIdProductId - // - vendorIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + deviceDescriptor->VendorIdOffset); - RtlInitAnsiString(&ansiString, vendorIdOffset); - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT)vendorIDLength; - unicodeString.Buffer = hardwareId; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): Failed to convert vendor id to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildHardwareId; - } - - productIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + deviceDescriptor->ProductIdOffset); - RtlInitAnsiString(&ansiString, productIdOffset); - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT)productIDLength; - unicodeString.Buffer = hardwareId + strlen(((PCHAR)deviceDescriptor) + offset); - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): Failed to convert product id to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildHardwareId; - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): HardwareId is %ws.\n", - DeviceInfo, - hardwareId)); - -__Exit_DsmpBuildHardwareId: - - if (hardwareId && !NT_SUCCESS(status)) { - DsmpFreePool(hardwareId); - hardwareId = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildHardwareId (DevInfo %p): Exiting function with deviceName %ws.\n", - DeviceInfo, - hardwareId)); - - return hardwareId; -} - - -PWSTR -DsmpBuildDeviceNameLegacyPage0x80( - _In_ IN PDSM_DEVICE_INFO DeviceInfo - ) -/*++ - -Routine Description: - - Construct a string from VendorId, ProductId, and SerialNumber (page 0x80 - info) of the device. - -Arguements: - - DeviceInfo - Device Extension - -Return Value : - - STATUS_SUCCESS if the device name was built successfully. - - Appropriate NTSTATUS code on failure - ---*/ -{ - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; - PWCHAR deviceName = NULL; - PWCHAR tmpPtr; - PWCHAR vendorID = NULL; - PWCHAR productID = NULL; - PWCHAR serialID = NULL; - ANSI_STRING ansiString; - UNICODE_STRING unicodeString; - UNICODE_STRING unicodeDeviceName; - SIZE_T vendorIDLength = 0; - SIZE_T productIDLength = 0; - SIZE_T serialIDLength = 0; - ULONG offset; - SIZE_T sizeNeeded; - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Entering function.\n", - DeviceInfo)); - - deviceDescriptor = &(DeviceInfo->Descriptor); - - // - // Save the vendorid, productid, and serialnumber offset - // in Device Descriptor - // - offset = deviceDescriptor->VendorIdOffset; - if ((offset != 0) && (offset != MAXULONG)) { - - vendorIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - offset = deviceDescriptor->ProductIdOffset; - if ((offset != 0) && (offset != MAXULONG)) { - - productIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - offset = deviceDescriptor->SerialNumberOffset; - if ((offset != 0) && (offset != MAXULONG)) { - - serialIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - // - // Allocate buffers to use to convert the IDs from ANSI to Unicode and - // eventually build the device name. - // - if (vendorIDLength > 0) { - vendorID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, vendorIDLength, DSM_TAG_DEV_NAME); - if (!vendorID) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for vendor ID.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (productIDLength > 0) { - productID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, productIDLength, DSM_TAG_DEV_NAME); - if (!productID) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for product ID.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (serialIDLength > 0) { - serialID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, serialIDLength, DSM_TAG_DEV_NAME); - if (!serialID) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for serial ID.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - sizeNeeded = vendorIDLength + productIDLength + serialIDLength; - if (sizeNeeded > 0) { - - // - // Account for the terminating NULL if serial id is empty. - // - - sizeNeeded += (serialIDLength ? 0 : WNULL_SIZE); - - deviceName = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, sizeNeeded, DSM_TAG_DEV_NAME); - if (!deviceName) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for device name.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } else { - - status = STATUS_UNSUCCESSFUL; - } - - if (!NT_SUCCESS(status)) { - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - - // - // Build the NULL terminated device name whose format is : - // - // VendorId_ProductId_SerialNumber - // - - unicodeDeviceName.Length = 0; - unicodeDeviceName.MaximumLength = (USHORT)sizeNeeded; - unicodeDeviceName.Buffer = deviceName; - - if (vendorIDLength) { - - PCSZ vendorIdOffset; - - vendorIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + - deviceDescriptor->VendorIdOffset); - - RtlInitAnsiString(&ansiString, vendorIdOffset); - - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT) vendorIDLength; - unicodeString.Buffer = vendorID; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to convert vendor id to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - - // - // If there are spaces in the id, set NULL at the first space. - // - tmpPtr = wcschr(vendorID, L' '); - if (tmpPtr != NULL) { - *tmpPtr = WNULL; - } - - status = RtlUnicodeStringCatString(&unicodeDeviceName, vendorID); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to concatenate vendor ID to device name.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - - RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); - } - - if (productIDLength) { - - PCSZ productIdOffset; - - productIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + - deviceDescriptor->ProductIdOffset); - - RtlInitAnsiString(&ansiString, productIdOffset); - - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT) productIDLength; - unicodeString.Buffer = productID; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to convert product id to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - - // - // If there are spaces in the id, set NULL at the first space. - // - tmpPtr = wcschr(productID, L' '); - if (tmpPtr != NULL) { - *tmpPtr = WNULL; - } - - status = RtlUnicodeStringCatString(&unicodeDeviceName, productID); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to concatenate product ID to device name.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - - RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); - } - - // - // Serial number - // - if (serialIDLength) { - - PCSZ serialNumberOffset; - - serialNumberOffset = (PCSZ)((PUCHAR)deviceDescriptor + - deviceDescriptor->SerialNumberOffset); - - RtlInitAnsiString(&ansiString, serialNumberOffset); - - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT) serialIDLength; - unicodeString.Buffer = serialID; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to convert serial number to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - - // - // If there are spaces in the id, set NULL at the first space. - // - tmpPtr = wcschr(serialID, L' '); - if (tmpPtr != NULL) { - *tmpPtr = WNULL; - } - - status = RtlUnicodeStringCatString(&unicodeDeviceName, serialID); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to concatenate serial number to device name.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; - } - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Device Name is %ws.\n", - DeviceInfo, - deviceName)); - -__Exit_DsmpBuildDeviceNameLegacyPage0x80: - - if (vendorID) { - DsmpFreePool(vendorID); - } - - if (productID) { - DsmpFreePool(productID); - } - - if (serialID) { - DsmpFreePool(serialID); - } - - if (deviceName && !NT_SUCCESS(status)) { - DsmpFreePool(deviceName); - deviceName = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Exiting function with deviceName %ws.\n", - DeviceInfo, - deviceName)); - - return deviceName; -} - - - -PWSTR -DsmpBuildDeviceName( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_reads_(SerialNumberLength) IN PSTR SerialNumber, - _In_ IN SIZE_T SerialNumberLength - ) -/*++ - -Routine Description: - - Construct a string from VendorId, ProductId, and SerialNumber (page 0x83 - identifiers) of the device. - -Arguements: - - DeviceInfo - Device Extension - SerialNumber - Device serial number built from appropriate page 0x83 identifier - SerialNumberLength - Length (in chars) of the passed in serial number buffer - -Return Value : - - Device name if it was built successfully. - NULL in case of failure. - ---*/ -{ - PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; - PWCHAR deviceName = NULL; - PWCHAR tmpPtr; - PWCHAR vendorID = NULL; - PWCHAR productID = NULL; - PWCHAR serialID = NULL; - ANSI_STRING ansiString; - UNICODE_STRING unicodeString; - UNICODE_STRING unicodeDeviceName; - SIZE_T vendorIDLength = 0; - SIZE_T productIDLength = 0; - SIZE_T serialIDLength = 0; - ULONG offset; - SIZE_T sizeNeeded; - NTSTATUS status = STATUS_SUCCESS; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Entering function.\n", - DeviceInfo)); - - deviceDescriptor = &(DeviceInfo->Descriptor); - - // - // Save the vendorid, productid, and serialnumber offset - // in Device Descriptor - // - offset = deviceDescriptor->VendorIdOffset; - if ((offset != 0) && (offset != MAXULONG)) { - - vendorIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - offset = deviceDescriptor->ProductIdOffset; - if ((offset != 0) && (offset != -1)) { - - productIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; - } - - if (SerialNumber) { - - serialIDLength = (SerialNumberLength * sizeof(WCHAR)) + WNULL_SIZE; - } - - // - // Allocate buffers to use to convert the IDs from ANSI to Unicode and - // eventually build the device name. - // - if (vendorIDLength > 0) { - vendorID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, vendorIDLength, DSM_TAG_DEV_NAME); - if (!vendorID) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for vendor ID.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (productIDLength > 0) { - productID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, productIDLength, DSM_TAG_DEV_NAME); - if (!productID) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for product ID.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (serialIDLength > 0) { - serialID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, serialIDLength, DSM_TAG_DEV_NAME); - if (!serialID) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for serial ID.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - sizeNeeded = vendorIDLength + productIDLength + serialIDLength; - if (sizeNeeded > 0) { - - // - // Account for the terminating NULL if serial id is empty. - // - - sizeNeeded += (serialIDLength ? 0 : WNULL_SIZE); - - deviceName = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, sizeNeeded, DSM_TAG_DEV_NAME); - if (!deviceName) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for device name.\n", - DeviceInfo)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } else { - - status = STATUS_UNSUCCESSFUL; - } - - if (!NT_SUCCESS(status)) { - goto __Exit_DsmpBuildDeviceName; - } - - // - // Build the NULL terminated device name whose format is : - // - // VendorId_ProductId_SerialNumber - // - - unicodeDeviceName.Length = 0; - unicodeDeviceName.MaximumLength = (USHORT)sizeNeeded; - unicodeDeviceName.Buffer = deviceName; - - if (vendorIDLength) { - - PCSZ vendorIdOffset; - - vendorIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + - deviceDescriptor->VendorIdOffset); - - RtlInitAnsiString(&ansiString, vendorIdOffset); - - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT) vendorIDLength; - unicodeString.Buffer = vendorID; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to convert vendor id to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceName; - } - - // - // If there are spaces in the id, set NULL at the first space. - // - tmpPtr = wcschr(vendorID, L' '); - if (tmpPtr != NULL) { - *tmpPtr = WNULL; - } - - status = RtlUnicodeStringCatString(&unicodeDeviceName, vendorID); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to concatenate vendor ID to device name.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceName; - } - - RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); - } - - if (productIDLength) { - - PCSZ productIdOffset; - - productIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + - deviceDescriptor->ProductIdOffset); - - RtlInitAnsiString(&ansiString, productIdOffset); - - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT) productIDLength; - unicodeString.Buffer = productID; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to convert product id to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceName; - } - - // - // If there are spaces in the id, set NULL at the first space. - // - tmpPtr = wcschr(productID, L' '); - if (tmpPtr != NULL) { - *tmpPtr = WNULL; - } - - status = RtlUnicodeStringCatString(&unicodeDeviceName, productID); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to concatenate product ID to device name.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceName; - } - - RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); - } - - // - // Serial number - // - if (serialIDLength) { - - PSTR serialNumberOffset; - - serialNumberOffset = SerialNumber; - - RtlInitAnsiString(&ansiString, serialNumberOffset); - - unicodeString.Length = 0; - unicodeString.MaximumLength = (USHORT) serialIDLength; - unicodeString.Buffer = serialID; - - status = RtlAnsiStringToUnicodeString(&unicodeString, - &ansiString, - FALSE); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to convert serial number to unicode string.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceName; - } - - // - // If there are spaces in the id, set NULL at the first space. - // - tmpPtr = wcschr(serialID, L' '); - if (tmpPtr != NULL) { - *tmpPtr = WNULL; - } - - status = RtlUnicodeStringCatString(&unicodeDeviceName, serialID); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Failed to concatenate serial number to device name.\n", - DeviceInfo)); - - goto __Exit_DsmpBuildDeviceName; - } - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Device Name is %ws.\n", - DeviceInfo, - deviceName)); - -__Exit_DsmpBuildDeviceName: - - if (vendorID) { - DsmpFreePool(vendorID); - } - - if (productID) { - DsmpFreePool(productID); - } - - if (serialID) { - DsmpFreePool(serialID); - } - - if (deviceName && !NT_SUCCESS(status)) { - DsmpFreePool(deviceName); - deviceName = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpBuildDeviceName (DevInfo %p): Exiting function with deviceName %ws.\n", - DeviceInfo, - deviceName)); - - return deviceName; -} - - -NTSTATUS -DsmpApplyDeviceNameCorrection( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_reads_(DeviceNameLegacyLen) PWSTR DeviceNameLegacy, - _In_ IN SIZE_T DeviceNameLegacyLen, - _In_reads_(DeviceNameLen) PWSTR DeviceName, - _In_ IN SIZE_T DeviceNameLen - ) -/*++ - -Routine Description: - - If the registry has a key name built with a legacy device name, this - function updates the key name with the current device name. - -Arguements: - - DeviceInfo - Device instance - DeviceNameLegacy - Device name built using legacy methods. - DeviceNameLegacyLen - Number of chars (including NULL) of the DeviceNameLegacy buffer. - DeviceName - Device name built using current methods. - DeviceNameLen - Number of chars (including NULL) of the DeviceName buffer. - -Return Value : - - STATUS_SUCCESS if the device's key was updated successfully. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE lbSettingsKey = NULL; - HANDLE deviceKeyLegacy = NULL; - HANDLE deviceKey = NULL; - OBJECT_ATTRIBUTES objectAttributes; - NTSTATUS status; - UNICODE_STRING deviceNameLegacy; - UNICODE_STRING deviceName; - - PAGED_CODE(); - - UNREFERENCED_PARAMETER(DeviceNameLen); - UNREFERENCED_PARAMETER(DeviceNameLegacyLen); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Entering function.\n", - DeviceInfo)); - - // - // First open LoadBalanceSettings key under the service key. - // - status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to open LB Settings key. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpApplyDeviceNameCorrection; - } - - RtlInitUnicodeString(&deviceNameLegacy, DeviceNameLegacy); - - InitializeObjectAttributes(&objectAttributes, - &deviceNameLegacy, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - lbSettingsKey, - (PSECURITY_DESCRIPTOR) NULL); - - // - // Open the old device key under DsmLoadBalanceSettings key. - // The name of this key is the one built using legacy methods - either a - // serial number from VPD page 0x80 or an aliased serial number from VPD - // page 0x83. - // - status = ZwOpenKey(&deviceKeyLegacy, - KEY_ALL_ACCESS, - &objectAttributes); - - if (NT_SUCCESS(status)) { - - ULONG disposition; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Key with old device name exists.\n", - DeviceInfo)); - - RtlInitUnicodeString(&deviceName, DeviceName); - - InitializeObjectAttributes(&objectAttributes, - &deviceName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - lbSettingsKey, - (PSECURITY_DESCRIPTOR) NULL); - - // - // Since the old name key exists, create one with the new name. - // - status = ZwCreateKey(&deviceKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - &disposition); - - if (NT_SUCCESS(status)) { - - // - // The new key shouldn't exist if the old one does. - // If it does, it indicates a error occured the previous time - // this was tried, so just copy over the old subtree anyways now. - // - DSM_ASSERT(disposition == REG_CREATED_NEW_KEY); - - // - // Copy over the entire subtree of the old key over to the new key. - // - status = DsmpRegCopyTree(deviceKeyLegacy, deviceKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to copy over the old device key's subtree. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpApplyDeviceNameCorrection; - } - - // - // Delete the old key name. - // - status = DsmpRegDeleteTree(deviceKeyLegacy); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to delete the old device key's subtree. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpApplyDeviceNameCorrection; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to create the new device key. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpApplyDeviceNameCorrection; - } - - } else if (status == STATUS_INVALID_HANDLE || - status == STATUS_OBJECT_NAME_NOT_FOUND) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Key with old device name does not exist.\n", - DeviceInfo)); - - status = STATUS_SUCCESS; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to query key with old device name. Status %x\n", - DeviceInfo, - status)); - } - -__Exit_DsmpApplyDeviceNameCorrection: - - if (deviceKey) { - ZwClose(deviceKey); - } - - if (deviceKeyLegacy) { - ZwClose(deviceKeyLegacy); - } - - if (lbSettingsKey) { - ZwClose(lbSettingsKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpApplyDeviceNameCorrection (DevInfo %p): Exiting function with status %x\n", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryDeviceLBPolicyFromRegistry( - _In_ PDSM_DEVICE_INFO DeviceInfo, - _In_ PWSTR RegistryKeyName, - _Inout_ PDSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Inout_ PULONGLONG PreferredPath, - _Inout_ PUCHAR ExplicitlySet - ) -/*++ - -Routine Description: - - Query the saved load balance policy and preferred path for this device from - the registry. - Also returns whether this setting was explicitly set via WMI call to SetLBPolicy, - (as opposed to the settings being made based on defaults determined through the - storage's ALUA capabilities). - -Arguements: - - DeviceInfo - The instance of the LUN through a paricular path - RegistryKeyName - DeviceName representing this LUN - LoadBalanceType - Type of LB policy. - PreferredPath - The preferred path for the device. - ExplicitlySet - Flag reflecting if LB policy was explicitly set. - -Return Value : - - STATUS_SUCCESS if we were able to successfully query the registry for the info. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE lbSettingsKey = NULL; - HANDLE deviceKey = NULL; - UNICODE_STRING subKeyName; - OBJECT_ATTRIBUTES objectAttributes; - NTSTATUS status; - UNICODE_STRING keyValueName; - ULONG length; - struct _explicitSet { - KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; - UCHAR Data; - } explicitSet; - struct _preferredPath { - KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; - ULONGLONG Data; - } preferredPath; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Entering function.\n", - DeviceInfo)); - - // - // Query the Load Balance settings for the given device from the registry. - // First open LoadBalanceSettings key under the service key. - // - status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to open LB Settings key. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpQueryDeviceLBPolicyFromRegistry; - } - - RtlInitUnicodeString(&subKeyName, RegistryKeyName); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - lbSettingsKey, - (PSECURITY_DESCRIPTOR) NULL); - - // - // Create or Open the device key under DsmLoadBalanceSettings key. - // The name of this key is the one built in DsmpBuildDeviceName - // - status = ZwCreateKey(&deviceKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (NT_SUCCESS(status)) { - - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | - RTL_QUERY_REGISTRY_REQUIRED | - RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; - queryTable[0].EntryContext = LoadBalanceType; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - deviceKey, - queryTable, - deviceKey, - NULL); - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): LB Policy is %d.\n", - DeviceInfo, - *LoadBalanceType)); - - } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - - // - // The device key must have been newly created. - // Set the default load balance policy for this device - // - - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_LOAD_BALANCE_POLICY, - REG_DWORD, - LoadBalanceType, - sizeof(ULONG)); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to write LB policy. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpQueryDeviceLBPolicyFromRegistry; - } - } - - if (NT_SUCCESS(status)) { - - RtlInitUnicodeString(&keyValueName, DSM_POLICY_EXPLICITLY_SET); - status = ZwQueryValueKey(deviceKey, - &keyValueName, - KeyValuePartialInformation, - &explicitSet, - sizeof(explicitSet), - &length); - - if (NT_SUCCESS(status)) { - - NT_ASSERT(explicitSet.KeyValueInfo.DataLength == sizeof(UCHAR)); - - *ExplicitlySet = *((UCHAR UNALIGNED *)&(explicitSet.KeyValueInfo.Data)); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): ExplicitlySet is %!bool!.\n", - DeviceInfo, - *ExplicitlySet)); - - } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - - *ExplicitlySet = FALSE; - - // - // The device key must have been newly created. - // Set ExplicitlySet to 0 to indicate that the default was used. - // - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_POLICY_EXPLICITLY_SET, - REG_BINARY, - ExplicitlySet, - sizeof(UCHAR)); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to write ExplicitlySet. Status %x.\n", - DeviceInfo, - status)); - } - } - - if (NT_SUCCESS(status)) { - - RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); - status = ZwQueryValueKey(deviceKey, - &keyValueName, - KeyValuePartialInformation, - &preferredPath, - sizeof(preferredPath), - &length); - - if (NT_SUCCESS(status)) { - - NT_ASSERT(preferredPath.KeyValueInfo.DataLength == sizeof(ULONGLONG)); - - *PreferredPath = *((ULONGLONG UNALIGNED *)&(preferredPath.KeyValueInfo.Data)); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): PreferredPath is %I64x.\n", - DeviceInfo, - *PreferredPath)); - - } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - - *PreferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - - // - // The device key must have been newly created. - // Set a bogus preferred path as default. - // - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_PREFERRED_PATH, - REG_BINARY, - PreferredPath, - sizeof(ULONGLONG)); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to write PreferredPath. Status %x.\n", - DeviceInfo, - status)); - } - } - } - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to create LB policy registry key. Status %x.\n", - DeviceInfo, - status)); - - deviceKey = NULL; - } - -__Exit_DsmpQueryDeviceLBPolicyFromRegistry: - - if (deviceKey) { - ZwClose(deviceKey); - } - - if (lbSettingsKey) { - ZwClose(lbSettingsKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Exiting function with status %x.\n", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryTargetLBPolicyFromRegistry( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Out_ OUT PULONGLONG PreferredPath - ) -/*++ - -Routine Description: - - Query the load balance policy for the VID/PID of the passed in device from - the registry if it has been set. - -Arguements: - - DeviceInfo - Device's whose VID/PID we need to compare against. - LoadBalanceType - Type of LB policy. - PreferredPath - The preferred path for the device. - -Return Value : - - STATUS_SUCCESS if we were able to successfully query the registry for the info. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE targetsLBSettingKey = NULL; - HANDLE targetKey = NULL; - UNICODE_STRING subKeyName; - OBJECT_ATTRIBUTES objectAttributes; - NTSTATUS status = STATUS_INVALID_PARAMETER; - UNICODE_STRING keyValueName; - ULONG length; - struct _preferredPath { - KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; - ULONGLONG Data; - } preferredPath; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Entering function.\n", - DeviceInfo)); - - if (!LoadBalanceType || !PreferredPath) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Invalid parameter.\n", - DeviceInfo)); - - goto __Exit_DsmpQueryTargetLBPolicyFromRegistry; - } - - if (!DeviceInfo->Group->HardwareId) { - - status = STATUS_UNSUCCESSFUL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Couldn't build hardware id for passed in device.\n", - DeviceInfo)); - - goto __Exit_DsmpQueryTargetLBPolicyFromRegistry; - } - - // - // Query the Load Balance settings for the given target from the registry. - // First open TargetsLoadBalanceSetting key under the service key. - // - status = DsmpOpenTargetsLoadBalanceSettingKey(KEY_ALL_ACCESS, &targetsLBSettingKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to open Targets LB Setting key. Status %x.\n", - DeviceInfo, - status)); - - goto __Exit_DsmpQueryTargetLBPolicyFromRegistry; - } - - RtlInitUnicodeString(&subKeyName, DeviceInfo->Group->HardwareId); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - targetsLBSettingKey, - (PSECURITY_DESCRIPTOR) NULL); - - // - // Open the VID/PID key under DsmTargetsLoadBalanceSetting key. - // - status = ZwOpenKey(&targetKey, KEY_ALL_ACCESS, &objectAttributes); - - if (NT_SUCCESS(status)) { - - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | - RTL_QUERY_REGISTRY_REQUIRED | - RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; - queryTable[0].EntryContext = LoadBalanceType; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - targetKey, - queryTable, - targetKey, - NULL); - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): LB Policy is %d.\n", - DeviceInfo, - *LoadBalanceType)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to query LB Policy - error %x.\n", - DeviceInfo, - status)); - } - - if (NT_SUCCESS(status)) { - - RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); - status = ZwQueryValueKey(targetKey, - &keyValueName, - KeyValuePartialInformation, - &preferredPath, - sizeof(preferredPath), - &length); - - if (NT_SUCCESS(status)) { - - NT_ASSERT(preferredPath.KeyValueInfo.DataLength == sizeof(ULONGLONG)); - - *PreferredPath = *((ULONGLONG UNALIGNED *)&(preferredPath.KeyValueInfo.Data)); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): PreferredPath is %I64x.\n", - DeviceInfo, - *PreferredPath)); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to query PreferredPath. Status %x.\n", - DeviceInfo, - status)); - } - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to open LB policy registry key. Status %x.\n", - DeviceInfo, - status)); - - targetKey = NULL; - } - -__Exit_DsmpQueryTargetLBPolicyFromRegistry: - - if (targetKey) { - ZwClose(targetKey); - } - - if (targetsLBSettingKey) { - ZwClose(targetsLBSettingKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Exiting function with status %x.\n", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryDsmLBPolicyFromRegistry( - _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Out_ OUT PULONGLONG PreferredPath - ) -/*++ - -Routine Description: - - Query the overall load balance policy for MSDSM controlled devices from - the registry if it has been set. - -Arguements: - - LoadBalanceType - Type of LB policy. - PreferredPath - The preferred path for the device. - -Return Value : - - STATUS_SUCCESS if we were able to successfully query the registry for the info. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE parametersKey = NULL; - NTSTATUS status = STATUS_INVALID_PARAMETER; - UNICODE_STRING keyValueName; - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - ULONG length; - struct _preferredPath { - KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; - ULONGLONG Data; - } preferredPath; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: Entering function.\n")); - - if (!LoadBalanceType || !PreferredPath) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: Invalid parameter.\n")); - - goto __Exit_DsmpQueryDsmLBPolicyFromRegistry; - } - - // - // Query the overall default Load Balance settings for MSDSM from the registry. - // First open the Parameters key under the service key. - // - status = DsmpOpenDsmServicesParametersKey(KEY_ALL_ACCESS, ¶metersKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: Failed to open Parameters key. Status %x.\n", - status)); - - goto __Exit_DsmpQueryDsmLBPolicyFromRegistry; - } - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | - RTL_QUERY_REGISTRY_REQUIRED | - RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; - queryTable[0].EntryContext = LoadBalanceType; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - parametersKey, - queryTable, - parametersKey, - NULL); - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: LB Policy is %d.\n", - *LoadBalanceType)); - - } else { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: Failed to query LB policy. Status %x.\n", - status)); - - goto __Exit_DsmpQueryDsmLBPolicyFromRegistry; - } - - if (NT_SUCCESS(status)) { - - RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); - status = ZwQueryValueKey(parametersKey, - &keyValueName, - KeyValuePartialInformation, - &preferredPath, - sizeof(preferredPath), - &length); - - if (NT_SUCCESS(status)) { - - NT_ASSERT(preferredPath.KeyValueInfo.DataLength == sizeof(ULONGLONG)); - - *PreferredPath = *((ULONGLONG UNALIGNED *)&(preferredPath.KeyValueInfo.Data)); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: PreferredPath is %I64x.\n", - *PreferredPath)); - - } else { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: Failed to query PreferredPath. Status %x.\n", - status)); - } - } - -__Exit_DsmpQueryDsmLBPolicyFromRegistry: - - if (parametersKey) { - ZwClose(parametersKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryDsmLBPolicyFromRegistry: Exiting function with status %x.\n", - status)); - - return status; -} - - -NTSTATUS -DsmpSetDsmLBPolicyInRegistry( - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ) -/*++ - -Routine Description: - - Set the overall load balance policy for MSDSM controlled devices in - the registry. - Note: If the policy specified is 0, remove the currently set values - for policy and preferred path. - -Arguements: - - LoadBalanceType - Type of LB policy. - PreferredPath - The preferred path for devices controlled by DSM. - -Return Value : - - STATUS_SUCCESS if we were able to successfully set the info in the registry. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE parametersKey = NULL; - NTSTATUS status; - UNICODE_STRING lbPolicyValueName; - UNICODE_STRING preferredPathValueName; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetDsmLBPolicyInRegistry: Entering function.\n")); - - // - // First open the Parameters key under the service key. - // - status = DsmpOpenDsmServicesParametersKey(KEY_ALL_ACCESS, ¶metersKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetDsmLBPolicyInRegistry: Failed to open Parameters key. Status %x.\n", - status)); - - goto __Exit_DsmpSetDsmLBPolicyInRegistry; - } - - RtlInitUnicodeString(&lbPolicyValueName, DSM_LOAD_BALANCE_POLICY); - RtlInitUnicodeString(&preferredPathValueName, DSM_PREFERRED_PATH); - - // - // If the LB policy is specified as 0, we need to delete the values. - // - if (LoadBalanceType < DSM_LB_FAILOVER) { - - status = ZwDeleteValueKey(parametersKey, &preferredPathValueName); - - if (NT_SUCCESS(status) || status == STATUS_OBJECT_NAME_NOT_FOUND) { - - status = ZwDeleteValueKey(parametersKey, &lbPolicyValueName); - } - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetDsmLBPolicyInRegistry: Failed to delete either preferredPath or lbPolicy. Status %x.\n", - status)); - } - } else { - - status = ZwSetValueKey(parametersKey, - &lbPolicyValueName, - 0, - REG_DWORD, - &LoadBalanceType, - sizeof(ULONG)); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetDsmLBPolicyInRegistry: Failed to set LB policy in registry. Status %x.\n", - status)); - - goto __Exit_DsmpSetDsmLBPolicyInRegistry; - } - - status = ZwSetValueKey(parametersKey, - &preferredPathValueName, - 0, - REG_BINARY, - &PreferredPath, - sizeof(ULONGLONG)); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetDsmLBPolicyInRegistry: Failed to set preferred path in registry. Status %x.\n", - status)); - } - } - -__Exit_DsmpSetDsmLBPolicyInRegistry: - - if (parametersKey) { - ZwClose(parametersKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetDsmLBPolicyInRegistry: Exiting function with status %x.\n", - status)); - - return status; -} - - -NTSTATUS -DsmpSetVidPidLBPolicyInRegistry( - _In_ IN PWSTR TargetHardwareId, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _In_ IN ULONGLONG PreferredPath - ) -/*++ - -Routine Description: - - Set the default load balance policy for MSDSM controlled devices for - a particular target VID/PID in the registry. - Note: If the policy specified is 0, remove the subkey that matches - the passed in TargetHardwareId. - -Arguements: - - TargetHardwareId - The VID/PID for which a default LB policy is being set. - LoadBalanceType - Type of LB policy. - PreferredPath - The preferred path for devices controlled by DSM. - -Return Value : - - STATUS_SUCCESS if we were able to successfully set the info in the registry. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE targetsLBSettingKey = NULL; - HANDLE targetSubKey = NULL; - NTSTATUS status; - UNICODE_STRING vidPidKeyName; - UNICODE_STRING lbPolicyValueName; - UNICODE_STRING preferredPathValueName; - OBJECT_ATTRIBUTES objectAttributes; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Entering function.\n", - TargetHardwareId)); - - // - // First open the DsmTargetsLoadBalanceSetting key under the service's parameters key. - // - status = DsmpOpenTargetsLoadBalanceSettingKey(KEY_ALL_ACCESS, &targetsLBSettingKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to open Targets Policy settings key. Status %x.\n", - TargetHardwareId, - status)); - - goto __Exit_DsmpSetVidPidLBPolicyInRegistry; - } - - RtlInitUnicodeString(&vidPidKeyName, TargetHardwareId); - InitializeObjectAttributes(&objectAttributes, - &vidPidKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - targetsLBSettingKey, - (PSECURITY_DESCRIPTOR) NULL); - - // - // If the LB policy is specified as 0, we need to delete the values. - // - if (LoadBalanceType < DSM_LB_FAILOVER) { - - // - // Open the VID/PID key under DsmTargetsLoadBalanceSetting key. - // - status = ZwOpenKey(&targetSubKey, KEY_ALL_ACCESS, &objectAttributes); - - if (NT_SUCCESS(status)) { - - status = ZwDeleteKey(targetSubKey); - } - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to either open or delete. Status %x.\n", - TargetHardwareId, - status)); - } - } else { - - RtlInitUnicodeString(&lbPolicyValueName, DSM_LOAD_BALANCE_POLICY); - RtlInitUnicodeString(&preferredPathValueName, DSM_PREFERRED_PATH); - - status = ZwCreateKey(&targetSubKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to open/create key in registry. Status %x.\n", - TargetHardwareId, - status)); - - goto __Exit_DsmpSetVidPidLBPolicyInRegistry; - } - - status = ZwSetValueKey(targetSubKey, - &lbPolicyValueName, - 0, - REG_DWORD, - &LoadBalanceType, - sizeof(ULONG)); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to set LB policy in registry. Status %x.\n", - TargetHardwareId, - status)); - - goto __Exit_DsmpSetVidPidLBPolicyInRegistry; - } - - status = ZwSetValueKey(targetSubKey, - &preferredPathValueName, - 0, - REG_BINARY, - &PreferredPath, - sizeof(ULONGLONG)); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to set preferred path in registry. Status %x.\n", - TargetHardwareId, - status)); - } - } - -__Exit_DsmpSetVidPidLBPolicyInRegistry: - - if (targetSubKey) { - ZwClose(targetSubKey); - } - - if (targetsLBSettingKey) { - ZwClose(targetsLBSettingKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpSetVidPidLBPolicyInRegistry (%ws): Exiting function with status %x.\n", - TargetHardwareId, - status)); - - return status; -} - - -NTSTATUS -DsmpOpenLoadBalanceSettingsKey( - _In_ IN ACCESS_MASK AccessMask, - _Out_ OUT PHANDLE LoadBalanceSettingsKey - ) -/*++ - -Routine Description: - - Open the device key in the registry. - - NOTE: It is the responsibility of the caller to close the returned handle. - -Arguements: - - AccessMask - Requested access with which to open key - LoadBalanceSettingsKey - handle of the key that is returned to the caller - -Return Value : - - STATUS_SUCCESS if we were able to successfully open the registry key. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE serviceKey = NULL; - HANDLE parametersKey = NULL; - PUNICODE_STRING registryPath = &(gDsmInitData.DsmWmiInfo.RegistryPath); - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING parametersKeyName; - UNICODE_STRING subKeyName; - NTSTATUS status = STATUS_UNSUCCESSFUL; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Entering function.\n", - registryPath)); - - *LoadBalanceSettingsKey = NULL; - - // - // First check if registry path is available for msdsm. - // - if (!registryPath->Buffer) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Registry Path not set.\n", - registryPath)); - - goto __Exit_DsmpOpenLoadBalanceSettingsKey; - } - - // - // Open the service key first - // - InitializeObjectAttributes(&objectAttributes, - registryPath, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - NULL, - NULL); - - status = ZwOpenKey(&serviceKey, - AccessMask, - &objectAttributes); - if (NT_SUCCESS(status)) { - - // - // Open Parameters key under the Service key - // - RtlInitUnicodeString(¶metersKeyName, DSM_SERVICE_PARAMETERS); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - ¶metersKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - serviceKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(¶metersKey, - AccessMask, - &objectAttributes); - - if (NT_SUCCESS(status)) { - - // - // Open LoadBalanceSettings key under the Parameters key - // - RtlInitUnicodeString(&subKeyName, DSM_LOAD_BALANCE_SETTINGS); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - parametersKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwCreateKey(LoadBalanceSettingsKey, - AccessMask, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Failed to open/create LBSettings key. Status %x.\n", - registryPath, - status)); - - *LoadBalanceSettingsKey = NULL; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Failed to open parameters key. Status %x.\n", - registryPath, - status)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Failed to open service key %ws. Status %x.\n", - registryPath, - registryPath->Buffer, - status)); - } - -__Exit_DsmpOpenLoadBalanceSettingsKey: - - if (parametersKey) { - ZwClose(parametersKey); - } - - if (serviceKey) { - ZwClose(serviceKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Exiting function with status %x.\n", - registryPath, - status)); - - return status; -} - - -NTSTATUS -DsmpOpenTargetsLoadBalanceSettingKey( - _In_ IN ACCESS_MASK AccessMask, - _Out_ OUT PHANDLE TargetsLoadBalanceSettingKey - ) -/*++ - -Routine Description: - - Open the target key in the registry. - - NOTE: It is the responsibility of the caller to close the returned handle. - -Arguements: - - AccessMask - Requested access with which to open key - LoadBalanceSettingsKey - handle of the key that is returned to the caller - -Return Value : - - STATUS_SUCCESS if we were able to successfully open the registry key. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE serviceKey = NULL; - HANDLE parametersKey = NULL; - PUNICODE_STRING registryPath = &(gDsmInitData.DsmWmiInfo.RegistryPath); - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING parametersKeyName; - UNICODE_STRING subKeyName; - NTSTATUS status = STATUS_UNSUCCESSFUL; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Entering function.\n", - registryPath)); - - if (!TargetsLoadBalanceSettingKey) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Invalid parameter.\n", - registryPath)); - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpOpenTargetsLoadBalanceSettingKey; - } - - *TargetsLoadBalanceSettingKey = NULL; - - // - // First check if registry path is available for msdsm. - // - if (!registryPath->Buffer) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Registry Path not set.\n", - registryPath)); - - goto __Exit_DsmpOpenTargetsLoadBalanceSettingKey; - } - - // - // Open the service key first - // - InitializeObjectAttributes(&objectAttributes, - registryPath, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - NULL, - NULL); - - status = ZwOpenKey(&serviceKey, - AccessMask, - &objectAttributes); - if (NT_SUCCESS(status)) { - - // - // Open Parameters key under the Service key - // - RtlInitUnicodeString(¶metersKeyName, DSM_SERVICE_PARAMETERS); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - ¶metersKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - serviceKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(¶metersKey, - AccessMask, - &objectAttributes); - - if (NT_SUCCESS(status)) { - - // - // Open LoadBalanceSettings key under the Parameters key - // - RtlInitUnicodeString(&subKeyName, DSM_TARGETS_LOAD_BALANCE_SETTING); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - parametersKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwCreateKey(TargetsLoadBalanceSettingKey, - AccessMask, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Failed to open/create TargetsLBSetting key. Status %x.\n", - registryPath, - status)); - - *TargetsLoadBalanceSettingKey = NULL; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Failed to open parameters key. Status %x.\n", - registryPath, - status)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Failed to open service key %ws. Status %x.\n", - registryPath, - registryPath->Buffer, - status)); - } - -__Exit_DsmpOpenTargetsLoadBalanceSettingKey: - - if (parametersKey) { - ZwClose(parametersKey); - } - - if (serviceKey) { - ZwClose(serviceKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Exiting function with status %x.\n", - registryPath, - status)); - - return status; -} - - -NTSTATUS -DsmpOpenDsmServicesParametersKey( - _In_ IN ACCESS_MASK AccessMask, - _Out_ OUT PHANDLE ParametersKey - ) -/*++ - -Routine Description: - - Open the DSM's Parameters key in the registry. - - NOTE: It is the responsibility of the caller to close the returned handle. - -Arguements: - - AccessMask - Requested access with which to open key - ParametersKey - handle of the key that is returned to the caller - -Return Value : - - STATUS_SUCCESS if we were able to successfully open the registry key. - - Appropriate NTSTATUS code on failure - ---*/ -{ - HANDLE serviceKey = NULL; - PUNICODE_STRING registryPath = &(gDsmInitData.DsmWmiInfo.RegistryPath); - OBJECT_ATTRIBUTES objectAttributes; - UNICODE_STRING parametersKeyName; - NTSTATUS status = STATUS_UNSUCCESSFUL; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpOpenDsmServicesParametersKey (RegPath %p): Entering function.\n", - registryPath)); - - if (!ParametersKey) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenDsmServicesParametersKey (RegPath %p): Invalid parameter.\n", - registryPath)); - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpOpenDsmServicesParametersKey; - } - - *ParametersKey = NULL; - - // - // First check if registry path is available for msdsm. - // - if (!registryPath->Buffer) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenDsmServicesParametersKey (RegPath %p): Registry Path not set.\n", - registryPath)); - - goto __Exit_DsmpOpenDsmServicesParametersKey; - } - - // - // Open the service key first - // - InitializeObjectAttributes(&objectAttributes, - registryPath, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - NULL, - NULL); - - status = ZwOpenKey(&serviceKey, - AccessMask, - &objectAttributes); - if (NT_SUCCESS(status)) { - - // - // Open Parameters key under the Service key - // - RtlInitUnicodeString(¶metersKeyName, DSM_SERVICE_PARAMETERS); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - ¶metersKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - serviceKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(ParametersKey, - AccessMask, - &objectAttributes); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenDsmServicesParametersKey (RegPath %p): Failed to open parameters key. Status %x.\n", - registryPath, - status)); - - *ParametersKey = NULL; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpOpenDsmServicesParametersKey (RegPath %p): Failed to open service key %ws. Status %x.\n", - registryPath, - registryPath->Buffer, - status)); - } - -__Exit_DsmpOpenDsmServicesParametersKey: - - if (serviceKey) { - ZwClose(serviceKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpOpenDsmServicesParametersKey (RegPath %p): Exiting function with status %x.\n", - registryPath, - status)); - - return status; -} - -NTSTATUS -DsmpReportTargetPortGroupsSyncCompletion( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context - ) -{ - UNREFERENCED_PARAMETER(DeviceObject); - UNREFERENCED_PARAMETER(Context); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroupsSyncCompletion: IRP %p, Context %p\n", - Irp, Context)); - - KeSetEvent(Irp->UserEvent, 0, FALSE); - - return STATUS_MORE_PROCESSING_REQUIRED; -} - -_Success_(return==0) -NTSTATUS -DsmpReportTargetPortGroups( - _In_ PDEVICE_OBJECT DeviceObject, - _Outptr_result_buffer_maybenull_(*TargetPortGroupsInfoLength) PUCHAR *TargetPortGroupsInfo, - _Out_ PULONG TargetPortGroupsInfoLength - ) -/*++ - -Routine Description: - - Helper routine to send down ReportTargetPortGroups request synchronously. - Used if device supports ALUA. - - Note: This routine will allocate memory for the TPG info. It is the - responsibility of the caller to free this buffer, but only if the function - returns STATUS_SUCCESS. - -Arguments: - - DeviceObject - The port PDO to which the command should be sent. - TargetPortGroupsInfo - buffer containing the returned data. - TargetPortGroupsInfoLength - size of the returned buffer. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - PSPC3_CDB_REPORT_TARGET_PORT_GROUPS cdb; - NTSTATUS status = STATUS_SUCCESS; - PIRP irp = NULL; - PMDL mdl = NULL; - PSCSI_REQUEST_BLOCK srb = NULL; - PSENSE_DATA_EX senseInfoBuffer = NULL; - UCHAR senseInfoBufferLength = 0; - KEVENT completionEvent; - ULONG targetPortGroupsInfoLength = 0; - PUCHAR targetPortGroupsInfo = NULL; - PIO_STACK_LOCATION irpStack = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Entering function.\n", - DeviceObject)); - - if (TargetPortGroupsInfoLength == NULL || - TargetPortGroupsInfo == NULL) { - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpReportTargetPortGroups; - } - - *TargetPortGroupsInfoLength = 0; - *TargetPortGroupsInfo = NULL; - - senseInfoBuffer = (PSENSE_DATA_EX)DsmpAllocatePool(NonPagedPoolNx, - SENSE_BUFFER_SIZE_EX, - DSM_TAG_SCSI_SENSE_INFO); - if (senseInfoBuffer != NULL) { - - senseInfoBufferLength = SENSE_BUFFER_SIZE_EX; - - srb = (PSCSI_REQUEST_BLOCK)DsmpAllocatePool(NonPagedPoolNx, - sizeof(SCSI_REQUEST_BLOCK), - DSM_TAG_SCSI_REQUEST_BLOCK); - if (srb != NULL) { - - SrbSetSenseInfoBufferLength(srb, senseInfoBufferLength); - SrbSetSenseInfoBuffer(srb, senseInfoBuffer); - - // - // Take care of worst case scenario, which is: - // 1. 4-byte header (for allocation length) - // 2. 32 8-byte descriptors (for TPGs) - // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) - // - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + - DSM_MAX_PATHS * sizeof(ULONG))); - - targetPortGroupsInfo = (PUCHAR)DsmpAllocatePool(NonPagedPoolNx, - targetPortGroupsInfoLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate TPG info.\n", - DeviceObject)); - goto __Exit_DsmpReportTargetPortGroups; - } - - } else { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate SRB.\n", - DeviceObject)); - goto __Exit_DsmpReportTargetPortGroups; - } - - } else { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate Sense Info Buffer.\n", - DeviceObject)); - goto __Exit_DsmpReportTargetPortGroups; - } - - irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE); - if (irp == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate IRP.\n", - DeviceObject)); - goto __Exit_DsmpReportTargetPortGroups; - } - - mdl = IoAllocateMdl(targetPortGroupsInfo, - targetPortGroupsInfoLength, - FALSE, - FALSE, - irp); - - if (mdl == NULL) { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate MDL.\n", - DeviceObject)); - goto __Exit_DsmpReportTargetPortGroups; - } - - MmBuildMdlForNonPagedPool(mdl); - -__Retry_DsmpReportTargetPortGroups: - - irp->MdlAddress = mdl; - - // - // Set up SRB for execute scsi request. Save SRB address in next stack - // for the port driver. - // - irpStack = IoGetNextIrpStackLocation(irp); - irpStack->MajorFunction = IRP_MJ_SCSI; - irpStack->MinorFunction = IRP_MN_SCSI_CLASS; - irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srb; - irpStack->DeviceObject = DeviceObject; - - // - // Set the completion event and the completion routine. - // - KeInitializeEvent(&completionEvent, NotificationEvent, FALSE); - irp->UserEvent = &completionEvent; - IoSetCompletionRoutine(irp, - DsmpReportTargetPortGroupsSyncCompletion, - srb, - TRUE, - TRUE, - TRUE); - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->Length = sizeof(SCSI_REQUEST_BLOCK); - - SrbSetCdbLength(srb, sizeof(SPC3_CDB_REPORT_TARGET_PORT_GROUPS)); - cdb = (PSPC3_CDB_REPORT_TARGET_PORT_GROUPS)SrbGetCdb(srb); - cdb->OperationCode = SPC3_SCSIOP_REPORT_TARGET_PORT_GROUPS; - cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; - REVERSE_BYTES(&(cdb->AllocationLength), &targetPortGroupsInfoLength); - - SrbSetTimeOutValue(srb, SPC3_REPORT_TARGET_PORT_GROUPS_TIMEOUT); - SrbSetDataTransferLength(srb, targetPortGroupsInfoLength); - SrbSetDataBuffer(srb, targetPortGroupsInfo); - srb->SrbStatus = 0; - SrbSetScsiStatus(srb, 0); - SrbSetNextSrb(srb, NULL); - SrbSetSrbFlags(srb, SRB_FLAGS_DONT_START_NEXT_PACKET | SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER | - SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE); - SrbSetQueueAction(srb, SRB_HEAD_OF_QUEUE_TAG_REQUEST); - SrbSetOriginalRequest(srb, irp); - - ObReferenceObject(DeviceObject); - - // - // Finally, send the IRP down and wait for its completion. - // - status = IoCallDriver(DeviceObject, irp); - - if (status == STATUS_PENDING) { - KeWaitForSingleObject(&completionEvent, - Executive, - KernelMode, - FALSE, - NULL); - status = irp->IoStatus.Status; - } - - ObDereferenceObject(DeviceObject); - - if ((status == STATUS_BUFFER_OVERFLOW) || - (NT_SUCCESS(status) && (SrbGetScsiStatus(srb) == SCSISTAT_GOOD))) { - - // - // The first 4 bytes of the returned data are the Returned Data Length - // field of the RTPG header. - // - ULONG returnedDataLength = 0; - REVERSE_BYTES(&returnedDataLength, targetPortGroupsInfo); - - status = STATUS_SUCCESS; - if (returnedDataLength > SrbGetDataTransferLength(srb)) { - - status = STATUS_BUFFER_OVERFLOW; - } - } - - if (NT_SUCCESS(status) && SrbGetScsiStatus(srb) == SCSISTAT_GOOD) { - - // - // RTPG was successful so return the TPG info to the caller. - // - - // - // The first 4 bytes of the returned data are the Returned Data Length - // field of the RTPG header. We need to return this value plus the header size. - // - ULONG returnedDataLength = 0; - REVERSE_BYTES(&returnedDataLength, targetPortGroupsInfo); - *TargetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + returnedDataLength; - - *TargetPortGroupsInfo = targetPortGroupsInfo; - - } else if (SrbGetScsiStatus(srb) == SCSISTAT_CHECK_CONDITION) { - - if (DsmpShouldRetryTPGRequest(senseInfoBuffer, senseInfoBufferLength)) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Retrying request.\n", - DeviceObject)); - - IoReuseIrp(irp, STATUS_SUCCESS); - - RtlZeroMemory(senseInfoBuffer, senseInfoBufferLength); - - goto __Retry_DsmpReportTargetPortGroups; - } - - if (DsmpIsDeviceRemoved(senseInfoBuffer, senseInfoBufferLength)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Device not available.\n", - DeviceObject)); - - // - // Sense key was illegal request. SPC 6.25 says response to TPG should follow Test Unit Ready responses - // - status = STATUS_NO_SUCH_DEVICE; - - } - - // RTPG was unsuccessful - // Here it is possible that status is success, but scsi status is not. - // and there was no RTPG retry. If so, set status to unsuccessful. - if (NT_SUCCESS(status)) { - status = STATUS_UNSUCCESSFUL; - } - - // - // TPG resulted HW to respond with Check Condition but Sense Key indicates it is not for retry or illegal request - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): TPG returned Check Condition, NTStatus 0x%x, ScsiStatus 0x%x.\n", - DeviceObject, - status, - SrbGetScsiStatus(srb))); - } else { - - // RTPG was unsuccessful - // Here it is possible that status is success, but scsi status is not. - // If so, set status to unsuccessful. - if (NT_SUCCESS(status)) { - status = STATUS_UNSUCCESSFUL; - } - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): NTStatus 0x%x, ScsiStatus 0x%x.\n", - DeviceObject, - status, - SrbGetScsiStatus(srb))); - } - -__Exit_DsmpReportTargetPortGroups: - - // - // The port driver may have allocated its own sense buffer so we need to - // make sure we free that here. - // - if (srb != NULL && - SrbGetSrbFlags(srb) & SRB_FLAGS_PORT_DRIVER_ALLOCSENSE && - SrbGetSrbFlags(srb) & SRB_FLAGS_FREE_SENSE_BUFFER && - SrbGetSenseInfoBuffer(srb) != NULL) { - DsmpFreePool(SrbGetSenseInfoBuffer(srb)); - } - - if (senseInfoBuffer) { - DsmpFreePool(senseInfoBuffer); - } - - if (srb) { - DsmpFreePool(srb); - } - - if (irp) { - if (irp->MdlAddress) { - IoFreeMdl(irp->MdlAddress); - } - IoFreeIrp(irp); - } - - if (!NT_SUCCESS(status) && targetPortGroupsInfo) { - DsmpFreePool(targetPortGroupsInfo); - *TargetPortGroupsInfoLength = 0; - *TargetPortGroupsInfo = NULL; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpReportTargetPortGroups (DevObj %p): Exiting function with status %x.\n", - DeviceObject, - status)); - - return status; -} - -NTSTATUS -DsmpReportTargetPortGroupsAsync( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, - _Inout_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, - _In_ IN ULONG TargetPortGroupsInfoLength, - _Inout_ __drv_aliasesMem IN OUT PUCHAR TargetPortGroupsInfo - ) -/*++ - -Routine Description: - - Helper routine to send down ReportTargetPortGroups request asynchronously. - Used if device supports ALUA. - - NOTE: Caller needs to free Irp, system buffer, and passThrough buffer. - -Arguments: - - DeviceInfo - The deviceInfo whose corresponding port PDO the command should be sent to. - CompletionRoutine - completion routine passed in by the caller. - CompletionContext - context to be passed to be completion routine. - TargetPortGroupsInfoLength - size of the returned buffer. - TargetPortGroupsInfo - preallocated (by caller) buffer that'll contain the returned data. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = CompletionContext; - PSCSI_REQUEST_BLOCK srb = NULL; - PSPC3_CDB_REPORT_TARGET_PORT_GROUPS cdb; - NTSTATUS status; - PIRP irp = NULL; - PIO_STACK_LOCATION irpStack; - PMDL mdl = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpReportTargetPortGroupsAsync (DevInfo %p): Entering function.\n", - DeviceInfo)); - - srb = tpgCompletionContext->Srb; - - SrbZeroSrb(srb); - - // - // Allocate an irp. - // - irp = IoAllocateIrp(DeviceInfo->TargetObject->StackSize + 1, FALSE); - if (!irp) { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpReportTargetPortGroupsAsync (DevInfo %p): Failed to allocate IRP.\n", - DeviceInfo)); - goto __Exit_DsmpReportTargetPortGroupsAsync; - } - - mdl = IoAllocateMdl(TargetPortGroupsInfo, - TargetPortGroupsInfoLength, - FALSE, - FALSE, - irp); - if (!mdl) { - - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpReportTargetPortGroupsAsync (DevInfo %p): Failed to allocate MDL.\n", - DeviceInfo)); - goto __Exit_DsmpReportTargetPortGroupsAsync; - } - - MmBuildMdlForNonPagedPool(irp->MdlAddress); - - // - // It is possible that if an implicit access state transition took place, - // each I_T nexus will return UA for asymmetric access state changed. So - // set the number of retries to be one more than the total number of paths. - // Worst case scenario is the it is sent down each path once (assuming every - // is a different I_T nexus) and then one more for a retry one one of the - // paths. - // - tpgCompletionContext->NumberRetries = DeviceInfo->Group->NumberDevices + 1; - - // - // Set-up the completion routine. - // - IoSetCompletionRoutine(irp, - CompletionRoutine, - (PVOID)CompletionContext, - TRUE, - TRUE, - TRUE); - - // - // Get the recipient's irpstack location. - // - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->Parameters.Scsi.Srb = srb; - irpStack->DeviceObject = DeviceInfo->TargetObject; - - // - // Set the major function code to IRP_MJ_SCSI. - // - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - - // - // Set the minor function, or many requests will get kicked by by port. - // - irpStack->MinorFunction = IRP_MN_SCSI_CLASS; - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->Length = sizeof(SCSI_REQUEST_BLOCK); - - SrbSetCdbLength(srb, sizeof(SPC3_CDB_REPORT_TARGET_PORT_GROUPS)); - cdb = (PSPC3_CDB_REPORT_TARGET_PORT_GROUPS)SrbGetCdb(srb); - cdb->OperationCode = SPC3_SCSIOP_REPORT_TARGET_PORT_GROUPS; - cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; - Get4ByteArrayFromUlong(TargetPortGroupsInfoLength, cdb->AllocationLength); - - SrbSetTimeOutValue(srb, SPC3_REPORT_TARGET_PORT_GROUPS_TIMEOUT); - SrbSetSenseInfoBuffer(srb, tpgCompletionContext->SenseInfoBuffer); - SrbSetSenseInfoBufferLength(srb, tpgCompletionContext->SenseInfoBufferLength); - SrbSetDataTransferLength(srb, TargetPortGroupsInfoLength); - SrbSetDataBuffer(srb, TargetPortGroupsInfo); - srb->SrbStatus = 0; - SrbSetScsiStatus(srb, 0); - SrbSetNextSrb(srb, NULL); - SrbSetSrbFlags(srb, SRB_FLAGS_DONT_START_NEXT_PACKET | SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER | - SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE); - SrbSetQueueAction(srb, SRB_HEAD_OF_QUEUE_TAG_REQUEST); - SrbSetOriginalRequest(srb, irp); - - irp->UserBuffer = TargetPortGroupsInfo; - irp->Tail.Overlay.Thread = PsGetCurrentThread(); - - // - // Send the IRP asynchronously - // - DsmSendRequestEx(((PDSM_CONTEXT)(DeviceInfo->DsmContext))->MPIOContext, - DeviceInfo->TargetObject, - irp, - (PVOID)DeviceInfo, - DSM_CALL_COMPLETION_ON_MPIO_ERROR); - - // - // We know that the completion routine will always be called. - // - status = STATUS_PENDING; - -__Exit_DsmpReportTargetPortGroupsAsync: - - if (status != STATUS_PENDING) { - - // - // This indicates Irp was never sent down to stack (completion routine was never called). - // We need to clean up. - // - if (irp) { - - if (irp->MdlAddress) { - IoFreeMdl(irp->MdlAddress); - } - - IoFreeIrp(irp); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpReportTargetPortGroupsAsync (DevInfo %p): Exiting function with status %x\n.", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryLBPolicyForDevice( - _In_ IN PWSTR RegistryKeyName, - _In_ IN ULONGLONG PathId, - _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, - _Out_ OUT PULONG PrimaryPath, - _Out_ OUT PULONG OptimizedPath, - _Out_ OUT PULONG PathWeight - ) -/*++ - -Routine Description: - - This routine opens the device's registry subkey, builds the path subkey from - the passed in PathId, then queries that subkey for the value of PrimaryPath, - OptimizedPath and PathWeight. - -Arguments: - - RegistryKeyName - The device's registry subkey name. - PathId - The pathId for this instance of the device. - LoadBalanceType - The current load balance policy. - PrimaryPath - Output of the queried PrimaryPath value. - OptimizedPath - Output of the queried OptimizedPath value. - PathWeight - Output of the queried PathWeight value. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - HANDLE lbSettingsKey = NULL; - HANDLE deviceKey = NULL; - HANDLE dsmPathKey = NULL; - UNICODE_STRING subKeyName; - WCHAR dsmPathName[128] = {0}; - OBJECT_ATTRIBUTES objectAttributes; - NTSTATUS status; - NTSTATUS pathWeightQueryStatus = STATUS_SUCCESS; - - PAGED_CODE(); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Entering function.\n", - RegistryKeyName)); - - // - // Query PrimaryPath and PathWeight for the given path. - // These values are stored under DsmPath#Suffix key for - // this path. If this key doesn't exist create it and - // create PrimaryPath and PathWeight values - use the - // values passed in PrimaryPath and PathWeight in this case. - // - status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to open LB Settings key. Status %x.\n", - RegistryKeyName, - status)); - - goto __Exit_DsmpQueryLBPolicyForDevice; - } - - RtlInitUnicodeString(&subKeyName, RegistryKeyName); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - lbSettingsKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(&deviceKey, KEY_ALL_ACCESS, &objectAttributes); - if (NT_SUCCESS(status)) { - - // - // Create or open DsmPath#Suffix key for this path - // - DsmpGetDSMPathKeyName(PathId, dsmPathName, 128); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Will query %ws for PrimaryPath, OptimizedPath and PathWeight.\n", - RegistryKeyName, - dsmPathName)); - - RtlInitUnicodeString(&subKeyName, dsmPathName); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - deviceKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwCreateKey(&dsmPathKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (NT_SUCCESS(status)) { - - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - - // - // Query the Path Weight value. - // - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | - RTL_QUERY_REGISTRY_REQUIRED | - RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_PATH_WEIGHT; - queryTable[0].EntryContext = PathWeight; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - pathWeightQueryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - dsmPathKey, - queryTable, - dsmPathKey, - NULL); - - if (!NT_SUCCESS(pathWeightQueryStatus)) { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to query PathWeight. Status %x.\n", - RegistryKeyName, - pathWeightQueryStatus)); - } - - // - // Query the Primary Path value. - // - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | - RTL_QUERY_REGISTRY_REQUIRED | - RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_PRIMARY_PATH; - queryTable[0].EntryContext = PrimaryPath; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - dsmPathKey, - queryTable, - dsmPathKey, - NULL); - if (NT_SUCCESS(status)) { - - // - // Query the Optimized Path value. - // - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | - RTL_QUERY_REGISTRY_REQUIRED | - RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_OPTIMIZED_PATH; - queryTable[0].EntryContext = OptimizedPath; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - dsmPathKey, - queryTable, - dsmPathKey, - NULL); - if (!NT_SUCCESS(status)) { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to query OptimizedPath. Status %x.\n", - RegistryKeyName, - status)); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to query PrimaryPath. Status %x.\n", - RegistryKeyName, - status)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to create DSM Path key %ws. Status %x.\n", - RegistryKeyName, - dsmPathName, - status)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to open key. Status %x.\n", - RegistryKeyName, - status)); - } - - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): PrimaryPath %d, OptmizedPath %d, PathWeight %d.\n", - RegistryKeyName, - *PrimaryPath, - *OptimizedPath, - *PathWeight)); - } - -__Exit_DsmpQueryLBPolicyForDevice: - - if (dsmPathKey) { - ZwClose(dsmPathKey); - } - - if (deviceKey) { - ZwClose(deviceKey); - } - - if (lbSettingsKey) { - ZwClose(lbSettingsKey); - } - - // - // If the load balance policy is Weighted Paths and we failed to read in - // the path weight value, we need to return the failure status from the - // path weight value query. - // - if (LoadBalanceType == DSM_LB_WEIGHTED_PATHS && !NT_SUCCESS(pathWeightQueryStatus)) { - status = pathWeightQueryStatus; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryLBPolicyForDevice (DevName %ws): Exiting function with status %x.\n", - RegistryKeyName, - status)); - - return status; -} - - -VOID -DsmpGetDSMPathKeyName( - _In_ ULONGLONG DSMPathId, - _Out_writes_(DsmPathKeyNameSize) PWCHAR DsmPathKeyName, - _In_ ULONG DsmPathKeyNameSize - ) -/*++ - -Routine Description: - - This routine builds the string that corresponds to the device's Path subkey - name in the registry. - -Arguments: - - DSMPathId - The pathId of this instance of the device. - DsmPathKeyName - Output buffer in which the subkey name for path is returned. - DsmPathKeyNameSize - size of the output buffer in WCHARs. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - PWCHAR pathPtr; - SIZE_T wcharsLeft; - SIZE_T size; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetDSMPathKeyName (PathId %I64x): Entering function.\n", - DSMPathId)); - - // - // This routine will build a name for a given DSM Path. - // The name is of the format DsmPath#Suffix, where Suffix - // is derived from the PathId - // - pathPtr = DsmPathKeyName; - - wcharsLeft = DsmPathKeyNameSize; - - size = wcslen(DSM_PATH); - - if (size < wcharsLeft) { - - // - // First copy the string DsmPath# - // - if (NT_SUCCESS(RtlStringCchCopyNW(pathPtr, wcharsLeft, DSM_PATH, wcslen(DSM_PATH)))) { - - wcharsLeft -= size; - pathPtr += size; - - if (wcharsLeft > 2) { - - RtlStringCchCatW(pathPtr, wcharsLeft, L"#"); - wcharsLeft--; - pathPtr++; - - // - // Each nibble in the path id would need 1 WCHAR - // upon conversion to WCHAR string. So we'll need - // 2 WCHARs for each byte. Include the NULL char also - // - size = (sizeof(PVOID) + 1) * 2; - if (size <= wcharsLeft) { - - PVOID pathId; - PUCHAR pathIdPtr; - ULONG inx; - UCHAR tmpChar; - - // - // Convert the ULONGLONG path id to a string and - // append that to DsmPath# - // - pathId = (PVOID) DSMPathId; - - pathIdPtr = (PUCHAR) &pathId; - - for (inx = 0; inx < sizeof(PVOID); inx++) { - - tmpChar = (*pathIdPtr & 0xF0) >> 4; - *pathPtr++ = DsmpGetAsciiForBinary(tmpChar); - - tmpChar = (*pathIdPtr & 0x0F); - *pathPtr++ = DsmpGetAsciiForBinary(tmpChar); - - pathIdPtr++; - } - - *pathPtr = WNULL; - } - } - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetDSMPathKeyName (PathId %I64x): Exiting function.\n", - DSMPathId)); - - return; -} - - -UCHAR -DsmpGetAsciiForBinary( - _In_ UCHAR BinaryChar - ) -/*++ - -Routine Description: - - This routine converts the passed in binary value into ASCII equivalent. - -Arguments: - - BinaryChar - The binary value that needs to be converted. - -Return Value: - - Corresponding ASCII value. - ---*/ -{ - UCHAR outChar = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetAsciiForBinary (BinaryChar %d): Entering function.\n", - BinaryChar)); - - // - // Convert a binary nibble into an ASCII character. - // - if ((BinaryChar >= 0) && (BinaryChar <= 9)) { - outChar = BinaryChar + '0'; - } else { - outChar = BinaryChar + 'A' - 10; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetAsciiForBinary (BinaryChar %d): Exiting function with outChar %c.\n", - BinaryChar, - outChar)); - - return outChar; -} - - -NTSTATUS -DsmpGetDeviceIdList( - _In_ IN PDEVICE_OBJECT DeviceObject, - _Out_ OUT PSTORAGE_DESCRIPTOR_HEADER *Descriptor - ) -/*++ - -Routine Description: - - This routine will perform a query for the StorageDeviceIdProperty and will - allocate a non-paged buffer to store the data in. - IMPORTANT: It is the responsibility of the caller to ensure that this buffer is freed. - -Arguments: - - DeviceObject - the device to query - Descriptor - a location to store a pointer to the buffer we allocate - -Return Value: - - status. - ---*/ -{ - STORAGE_PROPERTY_QUERY query; - PIO_STATUS_BLOCK ioStatus = NULL; - PSTORAGE_DESCRIPTOR_HEADER descriptor = NULL; - ULONG length; - NTSTATUS status = STATUS_UNSUCCESSFUL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetDeviceIdList (DevObj %p): Entering function.\n", - DeviceObject)); - - if (!DeviceObject) { - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpGetDeviceIdList; - } - - // - // Poison the passed in descriptor. - // - *Descriptor = NULL; - - // - // Setup the query buffer. - // - query.PropertyId = StorageDeviceIdProperty; - query.QueryType = PropertyStandardQuery; - query.AdditionalParameters[0] = 0; - - ioStatus = DsmpAllocatePool(NonPagedPoolNx, sizeof(IO_STATUS_BLOCK), DSM_TAG_IO_STATUS_BLOCK); - - if (!ioStatus) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetDeviceIdList (DevObj %p): Failed to allocate an IO_STATUS_BLOCK.\n", - DeviceObject)); - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpGetDeviceIdList; - } - - ioStatus->Status = 0; - ioStatus->Information = 0; - - // - // On the first call, just need to get the length of the descriptor. - // - descriptor = (PVOID)&query; - DsmSendDeviceIoControlSynchronous(IOCTL_STORAGE_QUERY_PROPERTY, - DeviceObject, - &query, - &query, - sizeof(STORAGE_PROPERTY_QUERY), - sizeof(STORAGE_DESCRIPTOR_HEADER), - FALSE, - ioStatus); - - status = ioStatus->Status; - - if(!NT_SUCCESS(status)) { - - descriptor = NULL; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetDeviceIdList (DevObj %p): Query failed (%x) on attempt 1.\n", - DeviceObject, - ioStatus->Status)); - - goto __Exit_DsmpGetDeviceIdList; - } - - NT_ASSERT(descriptor->Size); - if (descriptor->Size == 0) { - status = STATUS_UNSUCCESSFUL; - goto __Exit_DsmpGetDeviceIdList; - } - - // - // This time we know how much data there is so we can - // allocate a buffer of the correct size - // - length = descriptor->Size; - - descriptor = DsmpAllocatePool(NonPagedPoolNx, length, DSM_TAG_DEVICE_ID_LIST); - - if(!descriptor) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetDeviceIdList (DevObj %p): Couldn't allocate descriptor of %ld.\n", - DeviceObject, - length)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpGetDeviceIdList; - } - - // - // setup the query again. - // - query.PropertyId = StorageDeviceIdProperty; - query.QueryType = PropertyStandardQuery; - query.AdditionalParameters[0] = 0; - - // - // copy the input to the new outputbuffer - // - RtlCopyMemory(descriptor, - &query, - sizeof(STORAGE_PROPERTY_QUERY)); - - DsmSendDeviceIoControlSynchronous(IOCTL_STORAGE_QUERY_PROPERTY, - DeviceObject, - descriptor, - descriptor, - sizeof(STORAGE_PROPERTY_QUERY), - length, - 0, - ioStatus); - - status = ioStatus->Status; - - if(!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpGetDeviceIdList (DevObj %p): Query Failed (%x) on attempt 2.\n", - DeviceObject, - ioStatus->Status)); - - goto __Exit_DsmpGetDeviceIdList; - } - -__Exit_DsmpGetDeviceIdList: - - if (ioStatus) { - DsmpFreePool(ioStatus); - } - - if (!NT_SUCCESS(status)) { - - if (descriptor) { - DsmpFreePool(descriptor); - } - - } else { - *Descriptor = descriptor; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetDeviceIdList (DevObj %p): Exiting function with status %x.\n", - DeviceObject, - status)); - - return status; -} - - -NTSTATUS -DsmpSetTargetPortGroups( - _In_ IN PDEVICE_OBJECT DeviceObject, - _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, - _In_ IN ULONG TargetPortGroupsInfoLength - ) -/*++ - -Routine Description: - - Helper routine to send down SetTargetPortGroups request. - -Arguments: - - DeviceObject - The port PDO to which the command should be sent. - TargetPortGroupsInfo - buffer containing the TPG data. - TargetPortGroupsInfoLength - size of the TPG buffer. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER passThrough; - PSPC3_CDB_SET_TARGET_PORT_GROUPS cdb; - IO_STATUS_BLOCK ioStatus; - ULONG alignmentMask = DeviceObject->AlignmentRequirement; - PUCHAR dataBuffer = NULL; - SIZE_T allocatedLength = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpSetTargetPortGroups (DevObj %p): Entering function.\n", - DeviceObject)); - - NT_ASSERT(TargetPortGroupsInfoLength && TargetPortGroupsInfo); - - // - // Build request. - // - RtlZeroMemory(&passThrough, sizeof(passThrough)); - - dataBuffer = DsmpAllocateAlignedPool(NonPagedPoolNx, - TargetPortGroupsInfoLength, - alignmentMask, - DSM_TAG_PASS_THRU, - &allocatedLength); - if (!dataBuffer) { - - status = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetTargetPortGroups (DevObj %p): Failed to allocate mem for passthrough's databuffer.\n", - DeviceObject)); - goto __Exit_DsmpSetTargetPortGroups; - } - -__Retry_Request: - - // - // Build the cdb. - // - cdb = (PSPC3_CDB_SET_TARGET_PORT_GROUPS)passThrough.ScsiPassThroughDirect.Cdb; - - cdb->OperationCode = SPC3_SCSIOP_SET_TARGET_PORT_GROUPS; - cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; - Get4ByteArrayFromUlong(TargetPortGroupsInfoLength, cdb->ParameterListLength); - - passThrough.ScsiPassThroughDirect.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); - passThrough.ScsiPassThroughDirect.CdbLength = 12; - passThrough.ScsiPassThroughDirect.SenseInfoLength = SPTWB_SENSE_LENGTH; - passThrough.ScsiPassThroughDirect.DataIn = 0; - passThrough.ScsiPassThroughDirect.DataTransferLength = TargetPortGroupsInfoLength; - passThrough.ScsiPassThroughDirect.TimeOutValue = 20; - passThrough.ScsiPassThroughDirect.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseInfoBuffer); - passThrough.ScsiPassThroughDirect.DataBuffer = dataBuffer; - RtlCopyMemory(dataBuffer, - TargetPortGroupsInfo, - TargetPortGroupsInfoLength); - - DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH_DIRECT, - DeviceObject, - &passThrough, - &passThrough, - sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), - sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), - FALSE, - &ioStatus); - - if ((passThrough.ScsiPassThroughDirect.ScsiStatus == SCSISTAT_GOOD) && - (NT_SUCCESS(ioStatus.Status))) { - - status = STATUS_SUCCESS; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetTargetPortGroups (DevObj %p): STPG succeeded.\n", - DeviceObject)); - - } else if (NT_SUCCESS(ioStatus.Status) && - passThrough.ScsiPassThroughDirect.ScsiStatus == SCSISTAT_CHECK_CONDITION && - DsmpShouldRetryTPGRequest((PSENSE_DATA)&passThrough.SenseInfoBuffer, passThrough.ScsiPassThroughDirect.SenseInfoLength)) { - - // - // Retry the request - // - RtlZeroMemory(dataBuffer, TargetPortGroupsInfoLength); - goto __Retry_Request; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetTargetPortGroups (DevObj %p): NTStatus 0%x, ScsiStatus 0x%x.\n", - DeviceObject, - ioStatus.Status, - passThrough.ScsiPassThroughDirect.ScsiStatus)); - - status = ioStatus.Status; - } - -__Exit_DsmpSetTargetPortGroups: - - // - // Free the passthrough + data buffer. - // - if (dataBuffer) { - DsmpFreePool(dataBuffer); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpSetTargetPortGroups (DevObj %p): Exiting function with status %x.\n", - DeviceObject, - status)); - - return status; -} - - -NTSTATUS -DsmpSetTargetPortGroupsAsync( - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, - _In_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, - _In_ IN ULONG TargetPortGroupsInfoLength, - _In_ __drv_aliasesMem IN PUCHAR TargetPortGroupsInfo - ) -/*++ - -Routine Description: - - Helper routine to send down SetTargetPortGroups request asynchronously. - - IMPORTANT: Caller needs to free the IRP and allocated system buffer. - -Arguments: - - DeviceInfo - The deviceInfo whose corresponding port PDO the command should be sent to. - CompletionRoutine - completion routine provided by the caller. - CompletionContext - context passed into the completion routine. - TargetPortGroupsInfoLength - size of the TPG buffer. - TargetPortGroupsInfo - buffer containing the TPG data. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = CompletionContext; - PSCSI_REQUEST_BLOCK srb; - PSPC3_CDB_SET_TARGET_PORT_GROUPS cdb; - NTSTATUS status; - PIRP irp = NULL; - PIO_STACK_LOCATION irpStack; - PMDL mdl = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetTargetPortGroupsAsync (DevInfo %p): Entering function.\n", - DeviceInfo)); - - srb = tpgCompletionContext->Srb; - - SrbZeroSrb(srb); - - // - // Allocate an irp. - // - irp = IoAllocateIrp(DeviceInfo->TargetObject->StackSize + 1, FALSE); - if (!irp) { - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetTargetPortGroupsAsync (DevInfo %p): Failed to allocate IRP.\n", - DeviceInfo)); - goto __Exit_DsmpSetTargetPortGroupsAsync; - } - - mdl = IoAllocateMdl(TargetPortGroupsInfo, - TargetPortGroupsInfoLength, - FALSE, - FALSE, - irp); - if (!mdl) { - - status = STATUS_INSUFFICIENT_RESOURCES; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_RW, - "DsmpSetTargetPortGroupsAsync (DevInfo %p): Failed to allocate MDL.\n", - DeviceInfo)); - goto __Exit_DsmpSetTargetPortGroupsAsync; - } - - MmBuildMdlForNonPagedPool(irp->MdlAddress); - - // - // It is possible that an implicit state transition may have occurred which - // will cause every I_T nexus to return an UA (for asymmetric access state - // changed). So set the number of retries to number of paths (worst case of - // every path being a separate I_T nexus) plus one for a retry down one of - // paths. - // - tpgCompletionContext->NumberRetries = DeviceInfo->Group->NumberDevices + 1; - - // - // Set-up the completion routine. - // - IoSetCompletionRoutine(irp, - CompletionRoutine, - (PVOID)CompletionContext, - TRUE, - TRUE, - TRUE); - - // - // Get the recipient's irpstack location. - // - irpStack = IoGetNextIrpStackLocation(irp); - - irpStack->Parameters.Scsi.Srb = srb; - irpStack->DeviceObject = DeviceInfo->TargetObject; - - // - // Set the major function code to IRP_MJ_SCSI. - // - irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; - - // - // Set the minor function, or many requests will get kicked by by port. - // - irpStack->MinorFunction = IRP_MN_SCSI_CLASS; - - srb->Function = SRB_FUNCTION_EXECUTE_SCSI; - srb->Length = sizeof(SCSI_REQUEST_BLOCK); - - SrbSetCdbLength(srb, sizeof(SPC3_CDB_SET_TARGET_PORT_GROUPS)); - cdb = (PSPC3_CDB_SET_TARGET_PORT_GROUPS)SrbGetCdb(srb); - cdb->OperationCode = SPC3_SCSIOP_SET_TARGET_PORT_GROUPS; - cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; - Get4ByteArrayFromUlong(TargetPortGroupsInfoLength, cdb->ParameterListLength); - - SrbSetTimeOutValue(srb, SPC3_SET_TARGET_PORT_GROUPS_TIMEOUT); - SrbSetSenseInfoBuffer(srb, tpgCompletionContext->SenseInfoBuffer); - SrbSetSenseInfoBufferLength(srb, tpgCompletionContext->SenseInfoBufferLength); - SrbSetDataTransferLength(srb, TargetPortGroupsInfoLength); - SrbSetDataBuffer(srb, TargetPortGroupsInfo); - srb->SrbStatus = 0; - SrbSetScsiStatus(srb, 0); - SrbSetNextSrb(srb, NULL); - SrbSetSrbFlags(srb, SRB_FLAGS_DONT_START_NEXT_PACKET | SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_SYNCH_TRANSFER | - SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE); - SrbSetQueueAction(srb, SRB_HEAD_OF_QUEUE_TAG_REQUEST); - SrbSetOriginalRequest(srb, irp); - - irp->UserBuffer = TargetPortGroupsInfo; - irp->Tail.Overlay.Thread = PsGetCurrentThread(); - - // - // Send the IRP asynchronously - // - DsmSendRequestEx(((PDSM_CONTEXT)(DeviceInfo->DsmContext))->MPIOContext, - DeviceInfo->TargetObject, - irp, - DeviceInfo, - DSM_CALL_COMPLETION_ON_MPIO_ERROR); - - // - // We know that the completion routine will always be called. - // - status = STATUS_PENDING; - - -__Exit_DsmpSetTargetPortGroupsAsync: - - if (status != STATUS_PENDING) { - - // - // This indicates Irp was never sent down to stack (completion routine was never called). - // We need to clean up. - // - if (irp) { - - if (irp->MdlAddress) { - IoFreeMdl(irp->MdlAddress); - } - - IoFreeIrp(irp); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_RW, - "DsmpSetTargetPortGroupsAsync (DevInfo %p): Exiting function with status %x.\n", - DeviceInfo, - status)); - - return status; -} - - -PDSM_LOAD_BALANCE_POLICY_SETTINGS -DsmpCopyLoadBalancePolicies( - _In_ IN PDSM_GROUP_ENTRY GroupEntry, - _In_ IN ULONG DsmWmiVersion, - _In_ IN PVOID SupportedLBPolicies - ) -/*+++ - -Routine Description: - - This routine copies the LB Policies that needs to be persisted in registry. - This is done because registry routines can be called at PASSIVE IRQL only. - So a spinlock cannot be held while accessing registry. So hold a spinlock, - save the values in a temp buffer, release spinlock, and save data to registry - from the temp buffer. - - NOTE: This routine MUST be called with DSM_CONTEXT lock held. - -Arguements: - - GroupEntry - Group entry - DsmWmiVersion - version of the MPIO_DSM_Path class to use - SupportedLBPolicies - LB policy for the group - - Return Value: - - Pointer to LOAD_BALANCE_POLICY_SETTINGS if successful. Else, NULL ---*/ -{ - PDSM_LOAD_BALANCE_POLICY_SETTINGS lbSettings = NULL; - ULONG sizeNeeded; - ULONG inx; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpCopyLoadBalancePolicies (Group %p): Entering function.\n", - GroupEntry)); - - if (((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount == 0) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpCopyLoadBalancePolicies (Group %p): No paths specified in Set LB policies.\n", - GroupEntry)); - - goto __Exit_DsmpCopyLoadBalancePolicies; - } - - sizeNeeded = sizeof(DSM_LOAD_BALANCE_POLICY_SETTINGS) + - ((((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount - 1) * sizeof(MPIO_DSM_Path_V2));; - - lbSettings = DsmpAllocatePool(NonPagedPoolNx, - sizeNeeded, - DSM_TAG_LB_POLICY); - - if (!lbSettings) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpCopyLoadBalancePolicies (Group %p): Failed to allocate memory for LBSettings.\n", - GroupEntry)); - goto __Exit_DsmpCopyLoadBalancePolicies; - } - - // - // Copy the registry key name used to store the LB policies. - // - RtlStringCchCopyNW(lbSettings->RegistryKeyName, - sizeof(lbSettings->RegistryKeyName) / sizeof(lbSettings->RegistryKeyName[0]), - GroupEntry->RegistryKeyName, - ((sizeof(lbSettings->RegistryKeyName) - sizeof(WCHAR))/sizeof(WCHAR))); - - // - // Copy the Load Balance settings for this group - // - lbSettings->LoadBalancePolicy = ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->LoadBalancePolicy; - - lbSettings->PathCount = ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount; - - for (inx = 0; inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount; inx++) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - RtlCopyMemory(&(lbSettings->DsmPath[inx]), - &(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]), - sizeof(MPIO_DSM_Path)); - - // - // DSM_WMI_VERSION_1 supports only active and standby states - // - (lbSettings->DsmPath[inx]).OptimizedPath = TRUE; - - } else { - - RtlCopyMemory(&(lbSettings->DsmPath[inx]), - &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]), - sizeof(MPIO_DSM_Path_V2)); - } - } - -__Exit_DsmpCopyLoadBalancePolicies: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpCopyLoadBalancePolicies (Group %p): Exiting function with lbSettings %p.\n", - GroupEntry, - lbSettings)); - - return lbSettings; -} - - -NTSTATUS -DsmpPersistLBSettings( - _In_ IN PDSM_LOAD_BALANCE_POLICY_SETTINGS LoadBalanceSettings - ) -/*+++ - -Routine Description: - - This routine will save the Load Balance settings from LoadBalanceSettings - to registry. - - NOTE: This routine MUST be called at PASSIVE IRQL - - The format of the registry tree is : - - Services\MSDSM\LoadBalanceSettings -> - - DeviceName -> LoadBalancePolicy REG_DWORD - - DsmPath#Suffix -> PrimaryPath REG_DWORD - OptimizedPath REG_DWORD - PathWeight REG_DWORD - - The device name is the one built in DsmpBuildDeviceName - - The Suffix in DsmPath#Suffix is built from the PathId. It is built in - the routine DsmpGetDSMPathKeyName. - -Arguements: - - LoadBalanceSettings - Load Balance settings to be persisted in registry - -Return Value: - - STATUS_SUCCESS if the data could be successfully stored in the registry - Appropriate NT Status code on failure. ---*/ -{ - PMPIO_DSM_Path_V2 dsmPath; - HANDLE lbSettingsKey = NULL; - HANDLE deviceKey = NULL; - HANDLE dsmPathKey = NULL; - UNICODE_STRING subKeyName; - WCHAR dsmPathName[128]; - OBJECT_ATTRIBUTES objectAttributes; - NTSTATUS status; - ULONG inx; - PMPIO_DSM_Path_V2 preferredPath = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Entering function.\n", - LoadBalanceSettings->RegistryKeyName)); - - // - // First open LoadBalanceSettings key under the Service key - // - status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to open LB Settings key. Status %x.\n", - LoadBalanceSettings->RegistryKeyName, - status)); - - goto __Exit_DsmpPersistLBSettings; - } - - // - // Now open the key under which the LB settings for the given device is stored - // - RtlInitUnicodeString(&subKeyName, LoadBalanceSettings->RegistryKeyName); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - lbSettingsKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(&deviceKey, KEY_ALL_ACCESS, &objectAttributes); - - if (NT_SUCCESS(status)) { - - // - // Remove all LB policy information as we are going to rewrite it. - // We do this in case there is stale information about a path that - // no longer exists - // - status = DsmpRegDeleteTree(deviceKey); - - if (NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Deleted key along with its subkeys.\n", - LoadBalanceSettings->RegistryKeyName)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to delete key. Status %x\n", - LoadBalanceSettings->RegistryKeyName, - status)); - - } - - ZwClose(deviceKey); - deviceKey = NULL; - - } - - status = ZwCreateKey(&deviceKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (NT_SUCCESS(status)) { - - PDSM_DEVICE_INFO devInfo; - - for (inx = 0; inx < LoadBalanceSettings->PathCount; inx++) { - - dsmPath = &(LoadBalanceSettings->DsmPath[inx]); - - if (dsmPath->DsmPathId == 0) { - - continue; - } - - RtlZeroMemory(dsmPathName, sizeof(dsmPathName)); - - // - // Get the sub key name under which the LB settings for - // the given path is stored. - // - DsmpGetDSMPathKeyName(dsmPath->DsmPathId, dsmPathName, 128); - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Will open subkey %ws.\n", - LoadBalanceSettings->RegistryKeyName, - dsmPathName)); - - RtlInitUnicodeString(&subKeyName, dsmPathName); - - RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - deviceKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwCreateKey(&dsmPathKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (NT_SUCCESS(status)) { - - if (dsmPath->PreferredPath) { - - preferredPath = dsmPath; - } - - devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; - - // - // Save PrimaryPath, PathWeight and OptimizedPath values for this path - // - if (devInfo->DesiredState != DSM_DEV_UNDETERMINED) { - - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - dsmPathKey, - DSM_PRIMARY_PATH, - REG_DWORD, - &(dsmPath->PrimaryPath), - sizeof(ULONG)); - - if (NT_SUCCESS(status)) { - - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - dsmPathKey, - DSM_OPTIMIZED_PATH, - REG_DWORD, - &(dsmPath->OptimizedPath), - sizeof(ULONG)); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to save OptimizedPath. Status %x.\n", - LoadBalanceSettings->RegistryKeyName, - status)); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to save Primary Path. Status %x.\n", - LoadBalanceSettings->RegistryKeyName, - status)); - } - } - - if (NT_SUCCESS(status)) { - - if (LoadBalanceSettings->LoadBalancePolicy == DSM_LB_WEIGHTED_PATHS) { - - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - dsmPathKey, - DSM_PATH_WEIGHT, - REG_DWORD, - &(dsmPath->PathWeight), - sizeof(ULONG)); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to save PathWeight. Status %x.\n", - LoadBalanceSettings->RegistryKeyName, - status)); - } - } - } - - ZwClose(dsmPathKey); - dsmPathKey = NULL; - } else { - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to open DSM Path key. Status %x.\n", - LoadBalanceSettings->RegistryKeyName, - status)); - } - - if (!NT_SUCCESS(status)) { - break; - } - } - - if (NT_SUCCESS(status)) { - - // - // Save the new Load Balance Policy value, - // - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_LOAD_BALANCE_POLICY, - REG_DWORD, - &(LoadBalanceSettings->LoadBalancePolicy), - sizeof(ULONG)); - if (NT_SUCCESS(status)) { - - UCHAR explicitlySet = TRUE; - - // - // Write out that the policy has been explicitly set - // - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_POLICY_EXPLICITLY_SET, - REG_BINARY, - &explicitlySet, - sizeof(UCHAR)); - - if (NT_SUCCESS(status)) { - - // - // If FailOver-Only policy, set the PreferredPath, if specified - // - if (preferredPath) { - - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_PREFERRED_PATH, - REG_BINARY, - &(preferredPath->DsmPathId), - sizeof(ULONGLONG)); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to save LB Settings (ES).\n", - LoadBalanceSettings->RegistryKeyName)); - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Failed to save LB Settings (LBP).\n", - LoadBalanceSettings->RegistryKeyName)); - } - } - } - -__Exit_DsmpPersistLBSettings: - - if (dsmPathKey) { - ZwClose(dsmPathKey); - } - - if (deviceKey) { - ZwClose(deviceKey); - } - - if (lbSettingsKey) { - ZwClose(lbSettingsKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpPersistLBSettings (DevName %ws): Exiting function with status %x.\n", - LoadBalanceSettings->RegistryKeyName, - status)); - - return status; -} - - -NTSTATUS -DsmpSetDeviceALUAState( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_ IN DSM_DEVICE_STATE DevState - ) -/*++ - -Routine Description: - - Helper routine to build the STPG info and send it down to modify the passed in - devInfo's state. - -Arguments: - - DsmContext - DSM context. - DeviceInfo - DevInfo whose state needs to be changed. - DevState - New state to be set. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength; - PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR tpgDescriptor = NULL; - NTSTATUS status; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpSetDeviceALUAState (DevInfo %p): Entering function.\n", - DeviceInfo)); - - // - // Send down SetTPG to set the appropriate access state - // (The TPG block will contain the header and a SetTPG descriptor). - // - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); - - targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, - targetPortGroupsInfoLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo) { - - tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)(targetPortGroupsInfo + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE); - tpgDescriptor->AsymmetricAccessState = DevState; - REVERSE_BYTES_SHORT(&tpgDescriptor->TPG_Identifier, &DeviceInfo->TargetPortGroup->Identifier); - - status = DsmpSetTargetPortGroups(DeviceInfo->TargetObject, - targetPortGroupsInfo, - targetPortGroupsInfoLength); - - if (NT_SUCCESS(status)) { - - // - // An explicit transition may cause changes to some other TPGs. - // So we need to query for the states of all the TPGs and update - // our internal list and its elements. - // - status = DsmpGetDeviceALUAState(DsmContext, - DeviceInfo, - NULL); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetDeviceALUAState (DevInfo %p): Failed to SetTPG with %x.\n", - DeviceInfo, - status)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpSetDeviceALUAState (DevInfo %p): Failed to allocate TPG.\n", - DeviceInfo)); - status = STATUS_INSUFFICIENT_RESOURCES; - } - - if (targetPortGroupsInfo) { - DsmpFreePool(targetPortGroupsInfo); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpSetDeviceALUAState (DevInfo %p): Exiting function with status %x\n", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpAdjustDeviceStatesALUA( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_opt_ IN PDSM_DEVICE_INFO PreferredActiveDeviceInfo, - _In_ IN ULONG SpecialHandlingFlag - ) -/*++ - -Routine Description: - - Helper routine to build the adjust every device state in the group taking - the following into consideration: - 1. PreferredActiveDeviceInfo - 2. DeviceInfo's TPG state - 3. Preferred Path - 4. LB Policy - -Arguments: - - Group - Pseudo-LUN whose path states need to be adjusted. - PreferredActiveDeviceInfo - DevInfo whose state needs to preferrably made - A/O, if possible. This parameter is optional. - - SpecialHandlingFlag - Flags to indicate any special handling requirement - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - ULONG index; - PDSM_DEVICE_INFO deviceInfo; - PDSM_DEVICE_INFO activeDevice = NULL; - DSM_DEVICE_STATE devState; - NTSTATUS status = STATUS_SUCCESS; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): Entering function with preferred active devInfo %p.\n", - Group, - PreferredActiveDeviceInfo)); - - // - // Ensure that: - // 1. All devices match their ALUA state. - // 2. For RRWS, if a device's desired state is non-A/O, but ALUA state is A/O, mask it. - // 3. For FOO there must be only one A/O device. Preferably the preferred path. - // - for (index = 0; index < DSM_MAX_PATHS; index++) { - - deviceInfo = Group->DeviceList[index]; - - if (deviceInfo) { - - devState = deviceInfo->State; - - if (!DsmpIsDeviceFailedState(deviceInfo->State) && - DsmpIsDeviceInitialized(deviceInfo) && - DsmpIsDeviceUsable(deviceInfo) && - DsmpIsDeviceUsablePR(deviceInfo)) { - - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = deviceInfo->ALUAState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (its ALUA state).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - - if (deviceInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { - - // - // In FOO and RRWS, we need to mask states. - // - switch (Group->LoadBalanceType) { - case DSM_LB_FAILOVER: { - - // - // Cache the first available devInfo that is in A/O - // - if (!activeDevice) { - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p choosen as the active device.\n", - Group, - activeDevice)); - - break; - } - - // - // Check if this deviceInfo is the preferred path. If yes, - // mask the active device's state and make this the new - // active device. - // - if (Group->PreferredPath == (ULONGLONG)((ULONG_PTR)deviceInfo->FailGroup->PathId)) { - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || - activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): Previous active devInfo %p transitioning from %u to %u.\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active device (preferred path).\n", - Group, - activeDevice)); - - break; - } - - // - // If active device's desired state is not A/O but this - // deviceInfo's is, then mask the active device's state - // and make this one the new active device. - // - if (activeDevice->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - activeDevice->DesiredState != DSM_DEV_UNDETERMINED) { - - // - // The exception though is if the current active device - // is the preferred path - // - if (Group->PreferredPath == (ULONGLONG)((ULONG_PTR)activeDevice->FailGroup->PathId)) { - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = (deviceInfo->DesiredState == DSM_DEV_UNDETERMINED || - deviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : deviceInfo->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (active DI is PrefPath).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - } else { - - // - // If this is the devInfo that is preferred to be A/O, make it such - // - if (PreferredActiveDeviceInfo && - PreferredActiveDeviceInfo == deviceInfo) { - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (found a preferred active DI).\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active DI (preferred).\n", - Group, - activeDevice)); - } else { - - // - // Check if this devInfo desires to be in A/O, since the currently - // active one doesn't want to be. - // - if (deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - deviceInfo->DesiredState != DSM_DEV_UNDETERMINED) { - - // - // This deviceInfo's desire is also not to be in A/O, - // so just leave the current one active. - // - if (devState == DSM_DEV_ACTIVE_OPTIMIZED) { - - // - // Exception is if we're processing the device whose state before - // RTPG was sent was already A/O, it is best to leave this device - // in A/O state. - // - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || - activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u. Found a DI that was previously active.\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p now the new active device (previously A/O).\n", - Group, - activeDevice)); - } else { - - // - // This device wasn't in A/O state before, so just leave - // the currently selected active device as is. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = deviceInfo->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (active device already exists).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - } - } else { - - // - // Current devInfo wants (or doesn't) mind being in - // A/O, whereas the current active device doesn't, so - // mask the active device and make this devInfo the - // active device. - // - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u. Current DI prefers being A/O.\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active device (desired state).\n", - Group, - activeDevice)); - } - } - } - } else { - - // - // The single overriding factor is always the preferred path. - // Everything else is secondary, so first check if the currently - // active device can even be overridden by another one. - // - if (Group->PreferredPath != (ULONGLONG)((ULONG_PTR)activeDevice->FailGroup->PathId)) { - - // - // It can't be overridden, so we're done. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = (deviceInfo->DesiredState == DSM_DEV_UNDETERMINED || - deviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : deviceInfo->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (current active DI is PrefPath).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - } else { - - // - // Active device's desired state is A/O but it isn't the preferred - // path. Check if this devInfo is preferred as A/O. - // - if (PreferredActiveDeviceInfo && - PreferredActiveDeviceInfo == deviceInfo) { - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || - activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u. New DI is preferred active.\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active device (this DI is preferred active).\n", - Group, - activeDevice)); - } else { - - // - // Active device's desired state is A/O but it isn't the - // preferred path. Check if this devInfo's desired state - // is also A/O. If yes, we'll need to make certain decisions. - // - if (deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - deviceInfo->DesiredState != DSM_DEV_UNDETERMINED) { - - // - // Since this device doesn't desire to be in - // A/O and we already have an active device, just - // mask its state. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = deviceInfo->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (prefers being in non-A/O).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - } else { - - // - // Active device is in A/O and this device desires to be in - // A/O too. Make this the new active device only if its state - // before the RTPG was already A/O. - // - if (devState == DSM_DEV_ACTIVE_OPTIMIZED) { - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || - activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (new DI was already in A/O previously).\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is new active device (since it was in A/O previously too).\n", - Group, - activeDevice)); - } else { - - // - // Just leave the currently active one alone. - // - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = (deviceInfo->DesiredState == DSM_DEV_UNDETERMINED || - deviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : deviceInfo->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (leave current active DI alone).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - } - } - } - } - } - break; - } - - case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { - - // - // At least one path needs to be in A/O state, so - // cache the first available devInfo that is in A/O - // - if (!activeDevice) { - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): We have atleast one A/O DevInfo %p.\n", - Group, - activeDevice)); - - break; - } - - // - // Check if this device is preferred to be in A/O - // - if (PreferredActiveDeviceInfo && - PreferredActiveDeviceInfo == deviceInfo) { - - // - // If the currently active device, doesn't desire to be in - // A/O state, mask its state. - // - if (activeDevice->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - activeDevice->DesiredState != DSM_DEV_UNDETERMINED) { - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (desired state non-A/O).\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - } - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p now the new active device (preferred active DI).\n", - Group, - activeDevice)); - } else { - - // - // If this device's desired state is specified and not A/O, - // mask its path state. - // - if (deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - deviceInfo->DesiredState != DSM_DEV_UNDETERMINED) { - - deviceInfo->PreviousState = deviceInfo->State; - deviceInfo->State = deviceInfo->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (desires to be in non-A/O).\n", - Group, - deviceInfo, - deviceInfo->PreviousState, - deviceInfo->State)); - } else { - - // - // Since this devInfo desires to be in A/O, we are assured - // of at least one path in A/O. So check to see if the - // currently active device doesn't desire to be in A/O. - // - if (activeDevice->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && - activeDevice->DesiredState != DSM_DEV_UNDETERMINED) { - - activeDevice->PreviousState = activeDevice->State; - activeDevice->State = activeDevice->DesiredState; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (new DI desires to be in A/O).\n", - Group, - activeDevice, - activeDevice->PreviousState, - activeDevice->State)); - - activeDevice = deviceInfo; - - TracePrint((TRACE_LEVEL_INFORMATION, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p now the new active DI (desires to be in A/O).\n", - Group, - activeDevice)); - } - } - } - - break; - } - - default: { - - // - // For RR, LQD and WP, paths must be in the same - // state as their corresponding TPG. Preferably - // all should be A/O. - // - if (deviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED) { - DSM_ASSERT(deviceInfo->State == deviceInfo->ALUAState); - } - - break; - } - } - } - } - } - } - - // - // There may have been a change to the device states. - // DsmpGetPath() will pick these changes for RR, RRWS and LQD. - // However, it won't for FOO and WP, so update PTBU if needed. - // - if (Group->LoadBalanceType == DSM_LB_FAILOVER || - Group->LoadBalanceType == DSM_LB_WEIGHTED_PATHS) { - - deviceInfo = DsmpGetActivePathToBeUsed(Group, FALSE, SpecialHandlingFlag); - - if (deviceInfo) { - - InterlockedExchangePointer(&(Group->PathToBeUsed), deviceInfo->FailGroup); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpAdjustDeviceStatesALUA (Group %p): Exiting function with status %x\n", - Group, - status)); - - return status; -} - - -PDSM_WORKITEM -DsmpAllocateWorkItem( - _In_ IN PDEVICE_OBJECT DeviceObject, - _In_ IN PVOID Context - ) -/*++ - -Routine Description: - - Allocates a work item to handle reservation failover. - -Arguments: - - DeviceObject - Target device. - Context - Workitem context - -Return Value: - - Allocated workitem or NULL (if low memory). - ---*/ -{ - PDSM_WORKITEM dsmWorkItem = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpAllocateWorkItem (DevObj %p): Entering function.\n", - DeviceObject)); - - dsmWorkItem = DsmpAllocatePool(NonPagedPoolNx, - sizeof(DSM_WORKITEM), - DSM_TAG_WORKITEM); - if (dsmWorkItem != NULL) { - - dsmWorkItem->WorkItem = IoAllocateWorkItem(DeviceObject); - if (dsmWorkItem->WorkItem != NULL) { - - dsmWorkItem->Context = Context; - } else { - - DsmpFreePool(dsmWorkItem); - dsmWorkItem = NULL; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpAllocateWorkItem (DevObj %p): Exiting function. dsmWorkItem %p.\n", - DeviceObject, - dsmWorkItem)); - - return dsmWorkItem; -} - - -VOID -DsmpFreeWorkItem( - _In_ IN PDSM_WORKITEM DsmWorkItem - ) -{ - PVOID temp = DsmWorkItem; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpFreeWorkItem (WorkItem %p): Entering function.\n", - DsmWorkItem)); - - if (DsmWorkItem != NULL) { - - if (DsmWorkItem->WorkItem != NULL) { - IoFreeWorkItem(DsmWorkItem->WorkItem); - } - - DsmpFreePool(DsmWorkItem); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_IOCTL, - "DsmpFreeWorkItem (WorkItem %p): Exiting function.\n", - temp)); - - return; -} - - -VOID -DsmpFreeZombieGroupList( - _In_ IN PDSM_FAILOVER_GROUP FailGroup - ) -{ - PLIST_ENTRY zombieEntry = NULL; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFreeZombieGroupList (FailGroup %p): Entering function.\n", - FailGroup)); - - while (!IsListEmpty(&FailGroup->ZombieGroupList)) { - - zombieEntry = RemoveHeadList(&FailGroup->ZombieGroupList); - - if (zombieEntry) { - - DsmpFreePool(zombieEntry); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpFreeZombieGroupList (FailGroup %p): Exiting function.\n", - FailGroup)); -} - - -NTSTATUS -DsmpGetDeviceALUAState( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_DEVICE_INFO DeviceInfo, - _In_opt_ IN PDSM_DEVICE_STATE DevState - ) -/*++ - -Routine Description: - - Helper routine to build the RTPG info and send it down to retrieve the - devInfo's current state. - -Arguments: - - DsmContext - DSM context. - DeviceInfo - DevInfo whose state needs to be changed. - DevState - Current state of passed in DeviceInfo. - -Return Value: - - STATUS_SUCCESS or appropriate failure code. - ---*/ -{ - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength = 0; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = NULL; - KIRQL irql; - NTSTATUS status; - ULONG index; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetDeviceALUAState (DevInfo %p): Entering function.\n", - DeviceInfo)); - - status = DsmpReportTargetPortGroups(DeviceInfo->TargetObject, - &targetPortGroupsInfo, - &targetPortGroupsInfoLength); - - - if (NT_SUCCESS(status) && targetPortGroupsInfo != NULL) { - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - status = DsmpParseTargetPortGroupsInformation(DsmContext, - DeviceInfo->Group, - targetPortGroupsInfo, - targetPortGroupsInfoLength); - - for (index = 0; index < DSM_MAX_PATHS; index++) { - - targetPortGroup = DeviceInfo->Group->TargetPortGroupList[index]; - - if (targetPortGroup) { - - DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - if (DevState) { - - *DevState = DeviceInfo->State; - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_GENERAL, - "DsmpGetDeviceALUAState (DevInfo %p): ReportTPG failed with %x.\n", - DeviceInfo, - status)); - } - - if (targetPortGroupsInfo) { - - DsmpFreePool(targetPortGroupsInfo); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_GENERAL, - "DsmpGetDeviceALUAState (DevInfo %p): Exiting function with status %x\n", - DeviceInfo, - status)); - - return status; -} - - -NTSTATUS -DsmpRegCopyTree( - _In_ IN HANDLE SourceKey, - _In_ IN HANDLE DestKey - ) -/*++ - -Routine Description: - - Copies a reg subtree from source key to destination key. - This routine will first copy over all the key's values, and then - copy the subkeys, each time recursively handling the subkey's - values and its subtree. - -Arguments: - - SourceKey - Handle to the root of the subtree to copy over. - DestKey - Handle to the root of the new tree. - -Return Value: - - STATUS_SUCCESS upon successfully coping over the tree. - Appropriate NT error code in case of failure. - ---*/ -{ - ULONG numValues = 0; - ULONG numSubKeys = 0; - ULONG lengthOfValueName = 0; - ULONG lengthOfValueData = 0; - ULONG lengthOfKeyName = 0; - LPWSTR valueBuf = NULL; - BYTE *valueDataBuf = NULL; - ULONG valueDataType; - ULONG titleIndex; - HANDLE srcSubKey = NULL; - HANDLE destSubKey = NULL; - LPWSTR subKey = NULL; - NTSTATUS status; - PKEY_FULL_INFORMATION keyFullInfo = NULL; - ULONG length = sizeof(KEY_FULL_INFORMATION); - ULONG index = 0; - PKEY_VALUE_FULL_INFORMATION keyValueFullInfo = NULL; - PKEY_BASIC_INFORMATION keyBasicInfo = NULL; - OBJECT_ATTRIBUTES objectAttributes; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Entering function.\n", - SourceKey)); - - if (!SourceKey || !DestKey) { - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpRegCopyTree; - } - - // - // Query the source key for information about number of subkeys, number of values, etc. - // - do { - if (keyFullInfo) { - - DsmpFreePool(keyFullInfo); - } - - keyFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); - - if (!keyFullInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for key full info.\n", - SourceKey)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegCopyTree; - } - - status = ZwQueryKey(SourceKey, - KeyFullInformation, - keyFullInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to query key. Status %x.\n", - SourceKey, - status)); - - goto __Exit_DsmpRegCopyTree; - } - - numSubKeys = keyFullInfo->SubKeys; - numValues = keyFullInfo->Values; - lengthOfKeyName = keyFullInfo->MaxNameLen + sizeof(WCHAR); - lengthOfValueName = keyFullInfo->MaxValueNameLen + sizeof(WCHAR); - lengthOfValueData = keyFullInfo->MaxValueDataLen + sizeof(WCHAR); - - // - // Allocate a buffer for the name of the value - // - valueBuf = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - lengthOfValueName, - DSM_TAG_REG_KEY_RELATED); - if (!valueBuf) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for value name.\n", - SourceKey)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegCopyTree; - } - - // - // Allocate a buffer for the value data - // - valueDataBuf = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - lengthOfValueData, - DSM_TAG_REG_KEY_RELATED); - - if (!valueDataBuf) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for value's data.\n", - SourceKey)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegCopyTree; - } - - // - // First enumerate all of the values - // - status = STATUS_SUCCESS; - for (index = 0; index < numValues && NT_SUCCESS(status); index++) { - - UNICODE_STRING valueName; - - length = sizeof(KEY_VALUE_FULL_INFORMATION); - - do { - - if (keyValueFullInfo) { - - DsmpFreePool(keyValueFullInfo); - } - - keyValueFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); - - if (!keyValueFullInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for value full info.\n", - SourceKey)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegCopyTree; - } - - // - // Get the information of the index'th value - // - status = ZwEnumerateValueKey(SourceKey, - index, - KeyValueFullInformation, - keyValueFullInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to enumerate key's value information. Status %x.\n", - SourceKey, - status)); - - goto __Exit_DsmpRegCopyTree; - } - - // - // Capture the data type, data value, and value name. - // - titleIndex = keyValueFullInfo->TitleIndex; - valueDataType = keyValueFullInfo->Type; - - RtlZeroMemory(valueDataBuf, lengthOfValueData); - RtlCopyMemory(valueDataBuf, - (PUCHAR)keyValueFullInfo + keyValueFullInfo->DataOffset, - keyValueFullInfo->DataLength); - - RtlZeroMemory(valueBuf, lengthOfValueName); - RtlStringCbCopyNW(valueBuf, lengthOfValueName, keyValueFullInfo->Name, keyValueFullInfo->NameLength); - RtlInitUnicodeString(&valueName, valueBuf); - - // - // Copy the value over to the new key - // - status = ZwSetValueKey(DestKey, - &valueName, - titleIndex, - valueDataType, - valueDataBuf, - keyValueFullInfo->DataLength); - } - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate set new key's value information. Status %x.\n", - SourceKey, - status)); - - goto __Exit_DsmpRegCopyTree; - } - - // - // Allocate buffer for subkey name - // - subKey = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - lengthOfKeyName, - DSM_TAG_REG_KEY_RELATED); - - if(!subKey) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for sub key name.\n", - SourceKey)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegCopyTree; - } - - // - // Now Enumerate all of the subkeys - // - length = sizeof(KEY_BASIC_INFORMATION); - for(index = 0; index < numSubKeys && NT_SUCCESS(status); index++) { - - UNICODE_STRING subKeyName; - - do { - if (keyBasicInfo) { - - DsmpFreePool(keyBasicInfo); - } - - keyBasicInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - length, - DSM_TAG_REG_KEY_RELATED); - - if (!keyBasicInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for key basic info.\n", - SourceKey)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegCopyTree; - } - - // - // Enumerate the index'th subkey - // - status = ZwEnumerateKey(SourceKey, - index, - KeyBasicInformation, - keyBasicInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to enumerate sub key's info. Status %x.\n", - SourceKey, - status)); - - goto __Exit_DsmpRegCopyTree; - } - - RtlZeroMemory(subKey, lengthOfKeyName); - RtlStringCbCopyNW(subKey, lengthOfKeyName, keyBasicInfo->Name, keyBasicInfo->NameLength); - RtlInitUnicodeString(&subKeyName, subKey); - - // - // Open a handle to the the subkey on the old device. - // - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - SourceKey, - (PSECURITY_DESCRIPTOR) NULL); - - if (srcSubKey) { - ZwClose(srcSubKey); - srcSubKey = NULL; - } - - status = ZwOpenKey(&srcSubKey, - KEY_ALL_ACCESS, - &objectAttributes); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to open reg key %ws. Status %x.\n", - SourceKey, - subKey, - status)); - - goto __Exit_DsmpRegCopyTree; - } - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - DestKey, - (PSECURITY_DESCRIPTOR) NULL); - - if (destSubKey) { - ZwClose(destSubKey); - destSubKey = NULL; - } - - // - // Create the subkey on the new device. - // - status = ZwCreateKey(&destSubKey, - KEY_ALL_ACCESS, - &objectAttributes, - 0, - NULL, - REG_OPTION_NON_VOLATILE, - NULL); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Failed to create reg key %ws. Status %x.\n", - SourceKey, - subKey, - status)); - - goto __Exit_DsmpRegCopyTree; - } - - // - // That's it. We've got everything we need (ie. handles to the two new - // subtrees' roots. Call recursively. - // - status = DsmpRegCopyTree(srcSubKey, destSubKey); - } - -__Exit_DsmpRegCopyTree: - - if (keyFullInfo) { - DsmpFreePool(keyFullInfo); - } - - if (valueBuf) { - DsmpFreePool(valueBuf); - } - - if (valueDataBuf) { - DsmpFreePool(valueDataBuf); - } - - if (keyValueFullInfo) { - DsmpFreePool(keyValueFullInfo); - } - - if (subKey) { - DsmpFreePool(subKey); - } - - if (keyBasicInfo) { - DsmpFreePool(keyBasicInfo); - } - - if (srcSubKey) { - ZwClose(srcSubKey); - } - - if (destSubKey) { - ZwClose(destSubKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRegCopyTree (SrcKey %p): Exiting function with status %x.\n", - SourceKey, - status)); - - return status; -} - - -NTSTATUS -DsmpRegDeleteTree( - _In_ IN HANDLE KeyRoot - ) -/*++ -Routine Description: - - This routine is a recursive worker that enumerates the subkeys - of a given key, applies itself to each one, then deletes itself. - -Arguments: - - KeyRoot - Supplies a handle to the root of subtree to be deleted. - -Return Value: - - STATUS_SUCCESS - upon successful deletion of subtree. - Appropriate NT error code upon failure. - ---*/ -{ - NTSTATUS status; - PKEY_FULL_INFORMATION keyFullInfo = NULL; - ULONG length = sizeof(KEY_FULL_INFORMATION); - ULONG numSubKeys; - ULONG lengthOfKeyName; - LPWSTR subKey = NULL; - PKEY_BASIC_INFORMATION keyBasicInfo = NULL; - ULONG index = 0; - HANDLE srcSubKey = NULL; - OBJECT_ATTRIBUTES objectAttributes; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Entering function.\n", - KeyRoot)); - - if (!KeyRoot) { - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpRegDeleteTree; - } - - // - // Query the source key for information about number of subkeys and max - // length needed for subkey name. - // - do { - if (keyFullInfo) { - - DsmpFreePool(keyFullInfo); - } - - keyFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); - - if (!keyFullInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Failed to allocate resources for key full info.\n", - KeyRoot)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegDeleteTree; - } - - status = ZwQueryKey(KeyRoot, - KeyFullInformation, - keyFullInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Failed to query key. Status %x.\n", - KeyRoot, - status)); - - goto __Exit_DsmpRegDeleteTree; - } - - numSubKeys = keyFullInfo->SubKeys; - lengthOfKeyName = keyFullInfo->MaxNameLen + sizeof(WCHAR); - - if (numSubKeys) { - - // - // Allocate buffer for subkey name - // - subKey = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - lengthOfKeyName, - DSM_TAG_REG_KEY_RELATED); - - if(!subKey) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Failed to allocate resources for sub key.\n", - KeyRoot)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegDeleteTree; - } - - // - // Now Enumerate all of the subkeys - // - index = numSubKeys - 1; - length = sizeof(KEY_BASIC_INFORMATION); - do { - - UNICODE_STRING subKeyName; - - do { - if (keyBasicInfo) { - - DsmpFreePool(keyBasicInfo); - } - - keyBasicInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - length, - DSM_TAG_REG_KEY_RELATED); - - if (!keyBasicInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Failed to allocate resources for key basic info.\n", - KeyRoot)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpRegDeleteTree; - } - - // - // Enumerate the index'th subkey - // - status = ZwEnumerateKey(KeyRoot, - index, - KeyBasicInformation, - keyBasicInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (NT_SUCCESS(status)) { - - RtlZeroMemory(subKey, lengthOfKeyName); - RtlStringCbCopyNW(subKey, lengthOfKeyName, keyBasicInfo->Name, keyBasicInfo->NameLength); - RtlInitUnicodeString(&subKeyName, subKey); - - // - // Open a handle to the the current root's subkey. - // - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - KeyRoot, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(&srcSubKey, - KEY_ALL_ACCESS, - &objectAttributes); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Failed to open key %ws. Status %x.\n", - KeyRoot, - subKey, - status)); - - goto __Exit_DsmpRegDeleteTree; - } - - // - // Delete this key's subtree (recursively). - // - status = DsmpRegDeleteTree(srcSubKey); - - ZwClose(srcSubKey); - srcSubKey = NULL; - } - - index--; - - } while (status != STATUS_NO_MORE_ENTRIES && (LONG)index >= 0); - - if (status == STATUS_NO_MORE_ENTRIES) { - - status = STATUS_SUCCESS; - } - } - - ZwDeleteKey(KeyRoot); - -__Exit_DsmpRegDeleteTree: - - if (srcSubKey) { - ZwClose(srcSubKey); - } - - if (keyFullInfo) { - DsmpFreePool(keyFullInfo); - } - - if (subKey) { - DsmpFreePool(subKey); - } - - if (keyBasicInfo) { - DsmpFreePool(keyBasicInfo); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpRegDeleteTree (SrcKey %p): Exiting function with status %x.\n", - KeyRoot, - status)); - - return status; -} - - -#if defined (_WIN64) -VOID -DsmpPassThroughPathTranslate32To64( - _In_ IN PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32, - _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64 - ) -/*++ - -Routine Description: - - On WIN64, the SCSI_PASS_THROUGH field of the MPIO_PASS_THROUGH_PATH structure - sent down by a 32-bit application must be marshaled into a 64-bit version - of the structure. This function performs that marshaling. - -Arguments: - - MpioPassThroughPath32 - Supplies a pointer to a 32-bit MPIO_PASS_THROUGH_PATH - struct. - - MpioPassThroughPath64 - Supplies a pointer to a 64-bit MPIO_PASS_THROUGH_PATH - structure, into which we'll copy the marshaled - 32-bit data. - -Return Value: - - None. - ---*/ -{ - // - // Copy the first set of fields out of the 32-bit structure. These - // fields all line up between the 32 & 64 bit versions. - // - // Note that we do NOT adjust the length in the SrbControl. This is to - // allow the calling routine to compare the length of the actual - // control area against the offsets embedded within. If we adjusted the - // length then requests with the sense area backed against the control - // area would be rejected because the 64-bit control area is 4 bytes - // longer. - // - RtlCopyMemory(MpioPassThroughPath64, - MpioPassThroughPath32, - FIELD_OFFSET(SCSI_PASS_THROUGH, DataBufferOffset)); - - // - // Copy over the CDB. - // - RtlCopyMemory(MpioPassThroughPath64->PassThrough.Cdb, - MpioPassThroughPath32->PassThrough.Cdb, - 16 * sizeof(UCHAR) - ); - - // - // Copy over the rest of the fields of the structure. - // - MpioPassThroughPath64->Version = MpioPassThroughPath32->Version; - MpioPassThroughPath64->Length = MpioPassThroughPath32->Length; - MpioPassThroughPath64->Flags = MpioPassThroughPath32->Flags; - MpioPassThroughPath64->PortNumber = MpioPassThroughPath32->PortNumber; - MpioPassThroughPath64->MpioPathId = MpioPassThroughPath32->MpioPathId; - - // - // Copy the fields that follow the ULONG_PTR. - // - MpioPassThroughPath64->PassThrough.DataBufferOffset = (ULONG_PTR)MpioPassThroughPath32->PassThrough.DataBufferOffset; - MpioPassThroughPath64->PassThrough.SenseInfoOffset = MpioPassThroughPath32->PassThrough.SenseInfoOffset; - - return; -} - - -VOID -DsmpPassThroughPathTranslate64To32( - _In_ IN PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64, - _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32 - ) -/*++ - -Routine Description: - - On WIN64, the SCSI_PASS_THROUGH field of MPIO_PASS_THROUGH_PATH structure - sent down by a 32-bit application must be marshaled into a 64-bit version - of the structure. This function marshals a 64-bit version of the structure - back into a 32-bit version. - -Arguments: - - MpioPassThroughPath64 - Supplies a pointer to a 64-bit MPIO_PASS_THROUGH_PATH - struct. - - MpioPassThroughPath32 - Supplies the address of a pointer to a 32-bit - MPIO_PASS_THROUGH_PATH structure, into which we'll - copy the marshaled 64-bit data. - -Return Value: - - None. - ---*/ -{ - // - // Copy back the fields through the data offsets. - // - RtlCopyMemory(MpioPassThroughPath32, - MpioPassThroughPath64, - FIELD_OFFSET(SCSI_PASS_THROUGH, DataBufferOffset)); - - - // - // Copy over the CDB. - // - RtlCopyMemory(MpioPassThroughPath32->PassThrough.Cdb, - MpioPassThroughPath64->PassThrough.Cdb, - 16 * sizeof(UCHAR) - ); - - // - // Copy over the rest of the fields of the structure. - // - MpioPassThroughPath32->Version = MpioPassThroughPath64->Version; - MpioPassThroughPath32->Length = MpioPassThroughPath64->Length; - MpioPassThroughPath32->Flags = MpioPassThroughPath64->Flags; - MpioPassThroughPath32->PortNumber = MpioPassThroughPath64->PortNumber; - MpioPassThroughPath32->MpioPathId = MpioPassThroughPath64->MpioPathId; - - return; -} -#endif - - -NTSTATUS -DsmpGetMaxPRRetryTime( - _In_ IN PDSM_CONTEXT Context, - _Out_ OUT PULONG RetryTime - ) -/*++ - -Routine Description: - - This routine is used to get the max time period for which a PR request failing - with a retry-able unit attention should be retried before failing back to MSCS. - The value is determined by querying the value found at - "msdsm\Parameters\DsmMaximumStateTransitionTime" - -Arguments: - - Context - The DSM Context value. - RetryTime - The output parameter that will receive the value to be used. - -Return Value: - - Status of the RtlQueryRegistryValues call. - ---*/ -{ - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - WCHAR registryKeyName[56] = {0}; - NTSTATUS status; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetMaxPRRetryTime (DsmCtxt %p): Entering function.\n", - Context)); - - NT_ASSERT(RetryTime); - *RetryTime = DSM_MAX_PR_UNIT_ATTENTION_RETRY_TIME; - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - // - // Build the key value name that we want as the base of the query. - // - RtlStringCbPrintfW(registryKeyName, - sizeof(registryKeyName), - DSM_PARAMETER_PATH_W); - - // - // The query table has two entries. One for the state transition time and - // the second which is the 'NULL' terminator. - // - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_MAX_STATE_TRANSITION_TIME_VALUE_NAME; - queryTable[0].EntryContext = RetryTime; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - registryKeyName, - queryTable, - registryKeyName, - NULL); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpGetMaxPRRetryTime (DsmCtxt %p): Exiting function with status %x.\n", - Context, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryCacheInformationFromRegistry( - _In_ IN PDSM_CONTEXT DsmContext, - _Out_ OUT PBOOLEAN UseCacheForLeastBlocks, - _Out_ OUT PULONGLONG CacheSizeForLeastBlocks - ) -/*++ - -Routine Description: - - This routine is used to get the information about whether sequential IO - should use the same path when employing Least Blocks policy. - It also queries the size of cache set by the administrator. - The value is determined by querying the value found at - "msdsm\Parameters\DsmUseCacheForLeastBlocks" and - "msdsm\Parameters\DsmCacheSizeForLeastBlocks" - -Arguments: - - Context - The DSM Context value. - UseCacheForLeastBlocks - Returns the flag that indicates whether or not to - use same path for sequential IO when LB policy - is Least Blocks. - CacheSizeForLeastBlocks - Returns the size of the cache (in bytes) set by - the Admin to indicate the amount of sequential - data that should be use the same path when LB - policy is Least Blocks. - -Return Value: - - Status of the RtlQueryRegistryValues call. - ---*/ -{ - RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0}; - WCHAR registryKeyName[56] = {0}; - HANDLE parametersKey = NULL; - UNICODE_STRING keyValueName; - NTSTATUS status; - struct _cacheSizeForLeastBlocks { - KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; - ULONGLONG Data; - } cacheSizeForLeastBlocks; - ULONG length = 0; - BOOLEAN useCacheForLeastBlocksDefault = FALSE; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryCacheInformationFromRegistry (DsmCtxt %p): Entering function.\n", - DsmContext)); - - NT_ASSERT(UseCacheForLeastBlocks); - NT_ASSERT(CacheSizeForLeastBlocks); - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - // - // Build the key value name that we want as the base of the query. - // - RtlStringCbPrintfW(registryKeyName, - sizeof(registryKeyName), - DSM_PARAMETER_PATH_W); - - // - // The query table has two entries. One for whether to use cache, and - // and the second which is the 'NULL' terminator. - // - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_USE_CACHE_FOR_LEAST_BLOCKS; - queryTable[0].EntryContext = UseCacheForLeastBlocks; - queryTable[0].DefaultType = (REG_BINARY << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_BINARY; - queryTable[0].DefaultLength = sizeof(BOOLEAN); - queryTable[0].DefaultData = &useCacheForLeastBlocksDefault; - - status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - registryKeyName, - queryTable, - registryKeyName, - NULL); - - if (NT_SUCCESS(status)) { - - status = DsmpOpenDsmServicesParametersKey(KEY_QUERY_VALUE, ¶metersKey); - - if (NT_SUCCESS(status)) { - - RtlInitUnicodeString(&keyValueName, DSM_CACHE_SIZE_FOR_LEAST_BLOCKS); - - status = ZwQueryValueKey(parametersKey, - &keyValueName, - KeyValuePartialInformation, - &cacheSizeForLeastBlocks, - sizeof(cacheSizeForLeastBlocks), - &length); - - if (NT_SUCCESS(status)) { - - NT_ASSERT(cacheSizeForLeastBlocks.KeyValueInfo.DataLength == sizeof(ULONGLONG)); - *CacheSizeForLeastBlocks = *((ULONGLONG UNALIGNED *)&(cacheSizeForLeastBlocks.KeyValueInfo.Data)); - } - } - - if (parametersKey) { - ZwClose(parametersKey); - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_PNP, - "DsmpQueryCacheInformationFromRegistry (DsmCtxt %p): Exiting function with status %x.\n", - DsmContext, - status)); - - return status; -} - -BOOLEAN -DsmpConvertSharedSpinLockToExclusive( - _Inout_ _Requires_lock_held_(*_Curr_) PEX_SPIN_LOCK SpinLock - ) -/*++ - -Routine Description: - - This routine is a wrapper around ExTryConvertSharedSpinLockExclusive() that - guarantees the given EX_SPIN_LOCK will be acquired in Exclusive mode once - this function returns. - - It's possible the lock may be released and re-acquired within this function - so the caller should be very careful about the use of this function. - - N.B. The caller MUST have acquired the given lock in Shared mode before - calling this function. - -Arguments: - - SpinLock - The EX_SPIN_LOCK to convert from Shared to Exclusive mode. - -Return Value: - - Status of the ExTryConvertSharedSpinLockExclusive() call. This function - will always return with the lock acquired in Exclusive mode. The FALSE is - returned, then the lock had to be released and re-acquired. - ---*/ -{ - BOOLEAN converted = FALSE; - - converted = (BOOLEAN)ExTryConvertSharedSpinLockExclusive(SpinLock); - - // - // If the conversion attempt failed, then we should release the lock from - // Shared mode and try to pick it back up in Exclusive mode to guarantee - // this function will always return with the lock in Exclusive mode. - // - if (converted == FALSE) { - ExReleaseSpinLockSharedFromDpcLevel(SpinLock); - ExAcquireSpinLockExclusiveAtDpcLevel(SpinLock); - } - - return converted; -} - - diff --git a/tests/projects/wdk/wdm/msdsm/wmi.c b/tests/projects/wdk/wdm/msdsm/wmi.c deleted file mode 100644 index 0ee882192..000000000 --- a/tests/projects/wdk/wdm/msdsm/wmi.c +++ /dev/null @@ -1,3822 +0,0 @@ - -/*++ - -Copyright (C) 2004-2010 Microsoft Corporation - -Module Name: - - wmi.c - -Abstract: - - This driver is the Microsoft Device Specific Module (DSM). - It exports behaviours that mpio.sys will use to determine how to - multipath SPC-3 compliant devices. - - This file contains WMI related functions. - -Environment: - - kernel mode only - -Notes: - ---*/ - - - -#include "precomp.h" -#include "msdsmwmi.h" -#include "msdsmdsm.h" - -#ifdef DEBUG_USE_WPP -#include "wmi.tmh" -#endif - -#pragma warning (disable:4305) - -extern BOOLEAN DoAssert; - -#define USE_BINARY_MOF_RESOURCE - -#define DSM_INVALID_LOAD_BALANCE_POLICY STATUS_INVALID_PARAMETER -#define DSM_UNSUPPORTED_VERSION STATUS_NOT_SUPPORTED - -// -// Max length for each of the DeviceId strings (supported device list) -// NOTE: This must be kept in sync with msdsmdsm.mof -// -#define MSDSM_MAX_DEVICE_ID_LENGTH 31 -#define MSDSM_MAX_DEVICE_ID_SIZE (MSDSM_MAX_DEVICE_ID_LENGTH * sizeof(WCHAR)) - -// -// List of supported DSM-centric guids -// -GUID MSDSM_SUPPORTED_DEVICES_LISTGUID = MSDSM_SUPPORTED_DEVICES_LISTGuid; -GUID MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID = MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGuid; -GUID MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID = MSDSM_DEFAULT_LOAD_BALANCE_POLICYGuid; - -// -// Symbolic names for the DSM-centric guid indexes -// -#define MSDSM_SUPPORTED_DEVICES_LISTGUID_Index 0 -#define MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID_Index 1 -#define MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID_Index 2 - -WMIGUIDREGINFO MSDsmGuidList[] = { - { - &MSDSM_SUPPORTED_DEVICES_LISTGUID, - 1, - 0 - }, - - { - &MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID, - 1, - 0 - }, - - { - &MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID, - 1, - 0 - } -}; - -#define MSDsmGuidCount (sizeof(MSDsmGuidList) / sizeof(WMIGUIDREGINFO)) - -// -// List of supported Device-centric guids -// -GUID DSM_LBOperationsGUID = DSM_LB_OperationsGuid; -GUID DSM_QueryLBPolicyGUID = DSM_QueryLBPolicyGuid; -GUID DSM_QuerySupportedLBPoliciesGUID = DSM_QuerySupportedLBPoliciesGuid; -GUID DSM_QueryDsmUniqueIdGUID = DSM_QueryUniqueIdGuid; -GUID DSM_QueryLBPolicyV2GUID = DSM_QueryLBPolicy_V2Guid; -GUID DSM_QuerySupportedLBPoliciesV2GUID = DSM_QuerySupportedLBPolicies_V2Guid; -GUID MSDSM_DEVICE_PERFGUID = MSDSM_DEVICE_PERFGuid; -GUID MSDSM_WMI_METHODSGUID = MSDSM_WMI_METHODSGuid; - -// -// Symbolic names for the Device-centric guid indexes -// -#define DSM_LBOperationsGUID_Index 0 -#define DSM_QueryLBPolicyGUID_Index 1 -#define DSM_QuerySupportedLBPoliciesGUID_Index 2 -#define DSM_QueryDsmUniqueIdGUID_Index 3 -#define DSM_QueryLBPolicyV2GUID_Index 4 -#define DSM_QuerySupportedLBPoliciesV2GUID_Index 5 -#define MSDSM_DEVICE_PERFGuidIndex 6 -#define MSDSM_WMI_METHODSGuidIndex 7 - -WMIGUIDREGINFO DsmGuidList[] = { - { - &DSM_LBOperationsGUID, - 1, - 0 - }, - - { - &DSM_QueryLBPolicyGUID, - 1, - 0 - }, - - { - &DSM_QuerySupportedLBPoliciesGUID, - 1, - 0 - }, - - { - &DSM_QueryDsmUniqueIdGUID, - 1, - 0 - }, - - { - &DSM_QueryLBPolicyV2GUID, - 1, - 0 - }, - - { - &DSM_QuerySupportedLBPoliciesV2GUID, - 1, - 0 - }, - - { - &MSDSM_DEVICE_PERFGUID, - 1, - 0 - }, - - { - &MSDSM_WMI_METHODSGUID, - 1, - 0 - } -}; - -#define DsmGuidCount (sizeof(DsmGuidList) / sizeof(WMIGUIDREGINFO)) - -VOID -DsmpDsmWmiInitialize( - _In_ IN PDSM_WMILIB_CONTEXT WmiGlobalInfo, - _In_ IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - - This routine intializes the DSM-specific WmiGlobalInfo structure that is passed - back to MPIO during DriverEntry. - -Arguments: - - WmiGlobalInfo - WMI information structure to initialize. - RegistryPath - Registry path to the service key for this driver. - -Return Value: - - None - ---*/ -{ - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmpDsmWmiInitialize (RegPath %ws): Entering function.\n", - RegistryPath->Buffer)); - - RtlZeroMemory(WmiGlobalInfo, sizeof(DSM_WMILIB_CONTEXT)); - - // - // Build the mof resource name. This tells wmi via the busdriver, - // where to find the mof data. This is found in the .rc. - // - RtlInitUnicodeString(&WmiGlobalInfo->MofResourceName, L"DsmMofResourceName"); - - // - // This will jam in the entry points and guids for supported WMI - // operations. SetDataBlock, SetDataItem, ExecuteMethod and FunctionControl are - // currently not needed, so leave them set to zero. - // - WmiGlobalInfo->GuidCount = MSDsmGuidCount; - WmiGlobalInfo->GuidList = MSDsmGuidList; - - WmiGlobalInfo->QueryWmiDataBlockEx = DsmGlobalQueryData; - WmiGlobalInfo->SetWmiDataBlockEx = DsmGlobalSetData; - - // - // Allocate a buffer for the reg. path. - // - WmiGlobalInfo->RegistryPath.Buffer = DsmpAllocatePool(NonPagedPoolNx, - RegistryPath->MaximumLength, - DSM_TAG_REG_PATH); - if (WmiGlobalInfo->RegistryPath.Buffer) { - - // - // Set maximum length of the new string and copy it. - // - WmiGlobalInfo->RegistryPath.MaximumLength = RegistryPath->MaximumLength; - - RtlCopyUnicodeString(&WmiGlobalInfo->RegistryPath, RegistryPath); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_INIT, - "DsmpDsmWmiInitialize (RegPath %ws): Failed to allocate memory for Registry path in WmiGlobalInfo.\n", - RegistryPath->Buffer)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmpDsmWmiInitialize (RegPath %ws): Exiting function.\n", - RegistryPath->Buffer)); - - return; -} - - -NTSTATUS -DsmGlobalQueryData( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG InstanceCount, - _Inout_ IN OUT PULONG InstanceLengthArray, - _In_ IN ULONG BufferAvail, - _Out_writes_to_(BufferAvail, *DataLength) OUT PUCHAR Buffer, - _Out_ OUT PULONG DataLength, - ... - ) -/*++ - -Routine Description: - - This is the WMI query entry point for DSM-specific GUIDs. The index into the - GUID array is found and assuming the buffer is large enough, the data will be - copied over. - -Arguments: - - DsmContext - Global DSM Context - DsmIds - Dsm Ids - Irp - The WMI Irp - GuidIndex - Index into the WMIGUIDINFO array - InstanceIndex - Index of the data instance - InstanceCount - Number of instances - InstanceLengthArray - Array of ULONGs that indicate per-instance data lengths. - BufferAvail - Size of the buffer in which data is returned. - Buffer - Buffer in which the data is returned. - DataLength - Storage for the actual data length written. - -Return Value: - - STATUS_BUFFER_TOO_SMALL - If output buffer is not big enough to - to return all the available data. - STATUS_WMI_GUID_NOT_FOUND - If GuidIndex doesn't correspond to an actual entry - in the reginfo array. - STATUS_SUCCESS - On success. - ---*/ -{ - NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; - UNREFERENCED_PARAMETER(DsmContext); - UNREFERENCED_PARAMETER(InstanceLengthArray); - UNREFERENCED_PARAMETER(InstanceCount); - UNREFERENCED_PARAMETER(InstanceIndex); - UNREFERENCED_PARAMETER(Irp); - UNREFERENCED_PARAMETER(DsmIds); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmGlobalQueryData (DsmContext %p): Entering function - GuidIndex %u.\n", - DsmContext, - GuidIndex)); - - // - // Check the GuidIndex - the index into the DsmGuildList array - to see - // whether this is a supported GUID or not. - // - switch(GuidIndex) { - - case MSDSM_SUPPORTED_DEVICES_LISTGUID_Index: { - - *DataLength = BufferAvail; - - status = DsmpQuerySupportedDevicesList(DsmContext, - BufferAvail, - DataLength, - Buffer); - - break; - } - - case MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { - - *DataLength = BufferAvail; - - status = DsmpQueryTargetsDefaultPolicy(DsmContext, - BufferAvail, - DataLength, - Buffer); - - break; - } - - case MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { - - *DataLength = BufferAvail; - - status = DsmpQueryDsmDefaultPolicy(DsmContext, - BufferAvail, - DataLength, - Buffer); - - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalQueryData (DsmContext %p): Unknown GuidIndex %d.\n", - DsmContext, - GuidIndex)); - - *DataLength = 0; - - break; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmGlobalQueryData (DsmContext %p): Exiting function with status 0x%x.\n", - DsmContext, - status)); - - return status; -} - - -NTSTATUS -DsmGlobalSetData( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG BufferAvail, - _In_reads_bytes_(BufferAvail) IN PUCHAR Buffer, - ... - ) -/*++ - -Routine Description: - - This is the WMI set entry point for DSM-specific GUIDs. The index into the - GUID array is found and the contents of the buffer are set to the passed in - instance index. - -Arguments: - - DsmContext - Global DSM Context - DsmIds - Dsm Ids - Irp - The WMI Irp - GuidIndex - Index into the WMIGUIDINFO array - InstanceIndex - Index of the data instance - BufferAvail - Size of the buffer in which data is returned. - Buffer - Buffer in which the data is returned. - -Return Value: - - STATUS_BUFFER_TOO_SMALL - If output buffer is not big enough to - to return all the available data. - STATUS_WMI_GUID_NOT_FOUND - If GuidIndex doesn't correspond to an actual entry - in the reginfo array. - STATUS_SUCCESS - On success. - ---*/ -{ - NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; - ULONG dataLength; - PDSM_CONTEXT dsmContext = (PDSM_CONTEXT)DsmContext; - - UNREFERENCED_PARAMETER(DsmIds); - UNREFERENCED_PARAMETER(Irp); - UNREFERENCED_PARAMETER(InstanceIndex); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): Entering function - GuidIndex %u.\n", - DsmContext, - GuidIndex)); - - switch (GuidIndex) { - - case MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { - - PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY targetsPolicyInfo = (PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY)Buffer; - PMSDSM_TARGET_DEFAULT_POLICY_INFO targetPolicyInfo; - PWSTR vidpidIndex; - DSM_LOAD_BALANCE_TYPE loadBalancePolicy; - ULONGLONG preferredPath; - DWORD index; - NTSTATUS errorStatus = STATUS_SUCCESS; - - // - // Determine the correct buffer size. - // - dataLength = AlignOn8Bytes(FIELD_OFFSET(MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY, TargetDefaultPolicyInfo)); - - if (BufferAvail < dataLength) { - - status = STATUS_BUFFER_TOO_SMALL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Incorrect buffer size. Status %x\n", - DsmContext, - GuidIndex, - status)); - break; - } - - dataLength += targetsPolicyInfo->NumberDevices * sizeof(MSDSM_TARGET_DEFAULT_POLICY_INFO); - - if (BufferAvail < dataLength) { - - status = STATUS_BUFFER_TOO_SMALL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Incorrect buffer size for %u targets. Status %x\n", - DsmContext, - GuidIndex, - targetsPolicyInfo->NumberDevices, - status)); - break; - } - - targetPolicyInfo = targetsPolicyInfo->TargetDefaultPolicyInfo; - - for (index = 0; index < targetsPolicyInfo->NumberDevices; index++, targetPolicyInfo++) { - - size_t stringLength = 0; - - // - // First ensure that these values make sense. The VID/PID should be - // a string of 8+16 chars and the LB policy must be one that MSDSM - // supports. - // - // The WMI string is like a unicode string with the first USHORT - // containing the size. - // - vidpidIndex = targetPolicyInfo->HardwareId; - vidpidIndex++; - - if (!NT_SUCCESS(RtlStringCchLengthW(vidpidIndex, DSM_VENDPROD_ID_LEN + 1, &stringLength)) || (stringLength != DSM_VENDPROD_ID_LEN)) { - - errorStatus = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Ignoring incorrect VID/PID %ws. Status %x\n", - DsmContext, - GuidIndex, - vidpidIndex, - errorStatus)); - continue; - } - - if (targetPolicyInfo->LoadBalancePolicy >= DSM_LB_VENDOR_SPECIFIC) { - - errorStatus = STATUS_INVALID_PARAMETER; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Ignoring policy %u for %ws. Status %x\n", - DsmContext, - GuidIndex, - targetPolicyInfo->LoadBalancePolicy, - vidpidIndex, - errorStatus)); - continue; - } - - loadBalancePolicy = targetPolicyInfo->LoadBalancePolicy; - preferredPath = (ULONGLONG)((ULONG_PTR)targetPolicyInfo->PreferredPath); - - // - // Now update/create the key in the registry with the LB policy info. - // If the LB policy is specified as 0, delete the key. - // - status = DsmpSetVidPidLBPolicyInRegistry(vidpidIndex, loadBalancePolicy, preferredPath); - - // - // If above was successful, find the group that corresponds to this - // targetId and update its LB policy as well as the states of the paths - // - if (NT_SUCCESS(status)) { - - DsmpSetLBForVidPidPolicyAdjustment(dsmContext, vidpidIndex, loadBalancePolicy, preferredPath); - } else { - errorStatus = status; - } - } - - // - // If any error occurred, return the last error. - // - if (!NT_SUCCESS(errorStatus)) { - status = errorStatus; - } - - break; - } - - case MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { - - PMSDSM_DEFAULT_LOAD_BALANCE_POLICY dsmPolicyInfo = (PMSDSM_DEFAULT_LOAD_BALANCE_POLICY)Buffer; - DSM_LOAD_BALANCE_TYPE loadBalancePolicy; - ULONGLONG preferredPath; - - // - // Determine the correct buffer size. - // - dataLength = sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY); - - if (BufferAvail < dataLength) { - - status = STATUS_BUFFER_TOO_SMALL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Incorrect buffer size. Status %x\n", - DsmContext, - GuidIndex, - status)); - break; - } - - loadBalancePolicy = dsmPolicyInfo->LoadBalancePolicy; - preferredPath = (ULONGLONG)((ULONG_PTR)dsmPolicyInfo->PreferredPath); - - // - // First ensure that the values make sense. - // - if (loadBalancePolicy >= DSM_LB_VENDOR_SPECIFIC) { - - status = STATUS_INVALID_PARAMETER; - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Invalid policy %u specified. Status %x\n", - DsmContext, - GuidIndex, - loadBalancePolicy, - status)); - - } else { - - // - // Update/create the values in the registry with the LB policy info. - // If the LB policy is specified as 0, delete the values. - // - status = DsmpSetDsmLBPolicyInRegistry(loadBalancePolicy, preferredPath); - - // - // If above is successful, find the groups that haven't had their LB policy - // explicitly set or haven't had their policy set in accordance with target - // hardware id. For each of these, adjust the states of the paths as well. - // - if (NT_SUCCESS(status)) { - - DsmpSetLBForDsmPolicyAdjustment(dsmContext, loadBalancePolicy, preferredPath); - } - } - - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): Unknown GuidIndex %d.\n", - DsmContext, - GuidIndex)); - - break; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmGlobalSetData (DsmContext %p): Exiting function with status 0x%x.\n", - DsmContext, - status)); - - return status; -} - - -VOID -DsmpWmiInitialize( - _In_ IN PDSM_WMILIB_CONTEXT WmiInfo, - _In_ IN PUNICODE_STRING RegistryPath - ) -/*++ - -Routine Description: - - This routine intializes the Device-specific WmiInfo structure that is passed - back to MPIO during DriverEntry. - -Arguments: - - WmiInfo - WMI information structure to initialize. - RegistryPath - Registry path to the service key for this driver. - -Return Value: - - None - ---*/ -{ - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmpWmiInitialize (RegPath %ws): Entering function.\n", - RegistryPath->Buffer)); - - RtlZeroMemory(WmiInfo, sizeof(DSM_WMILIB_CONTEXT)); - - // - // Build the mof resource name. This tells wmi via the busdriver, - // where to find the mof data. This is found in the .rc. - // - RtlInitUnicodeString(&WmiInfo->MofResourceName, L"MofResourceName"); - - // - // This will jam in the entry points and guids for supported WMI - // operations. SetDataBlock, SetDataItem, and FunctionControl are - // currently not needed, so leave them set to zero. - // - WmiInfo->GuidCount = DsmGuidCount; - WmiInfo->GuidList = DsmGuidList; - - WmiInfo->QueryWmiDataBlockEx = DsmQueryData; - WmiInfo->ExecuteWmiMethodEx = DsmExecuteMethod; - - // - // Allocate a buffer for the reg. path. - // - WmiInfo->RegistryPath.Buffer = DsmpAllocatePool(NonPagedPoolNx, - RegistryPath->MaximumLength, - DSM_TAG_REG_PATH); - if (WmiInfo->RegistryPath.Buffer) { - - // - // Set maximum length of the new string and copy it. - // - WmiInfo->RegistryPath.MaximumLength = RegistryPath->MaximumLength; - - RtlCopyUnicodeString(&WmiInfo->RegistryPath, RegistryPath); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_INIT, - "DsmpWmiInitialize (RegPath %ws): Failed to allocate memory for Registry path in WMIInfo.\n", - RegistryPath->Buffer)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_INIT, - "DsmpWmiInitialize (RegPath %ws): Exiting function.\n", - RegistryPath->Buffer)); - - return; -} - - -NTSTATUS -DsmQueryData( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG InstanceCount, - _Inout_ IN OUT PULONG InstanceLengthArray, - _In_ IN ULONG BufferAvail, - _When_(GuidIndex == DSM_LBOperationsGUID_Index || GuidIndex == MSDSM_WMI_METHODSGuidIndex, _Pre_notnull_ _Const_) - _When_(!(GuidIndex == DSM_LBOperationsGUID_Index || GuidIndex == MSDSM_WMI_METHODSGuidIndex), _Out_writes_to_(BufferAvail, *DataLength)) - OUT PUCHAR Buffer, - _Out_ OUT PULONG DataLength, - ... - ) -/*++ - -Routine Description: - - This is the main WMI query entry point. The index into the GUID array is found - and assuming the buffer is large enough, the data will be copied over. - -Arguments: - - DsmContext - Global DSM Context - DsmIds - Dsm Ids - Irp - The WMI Irp - GuidIndex - Index into the WMIGUIDINFO array - InstanceIndex - Index of the data instance - InstanceCount - Number of instances - InstanceLengthArray - Array of ULONGs that indicate per-instance data lengths. - BufferAvail - Size of the buffer in which data is returned. - Buffer - Buffer in which the data is returned. - DataLength - Storage for the actual data length written. - -Return Value: - - STATUS_BUFFER_TOO_SMALL - If output buffer is not big enough to - to return all the available data. - STATUS_WMI_GUID_NOT_FOUND - If GuidIndex doesn't correspond to an actual entry - in the reginfo array. - STATUS_SUCCESS - On success. - ---*/ -{ - ULONG sizeNeeded; - NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; - - UNREFERENCED_PARAMETER(DsmContext); - UNREFERENCED_PARAMETER(InstanceCount); - UNREFERENCED_PARAMETER(InstanceIndex); - UNREFERENCED_PARAMETER(Irp); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmQueryData (DsmIds %p): Entering function - GuidIndex %u.\n", - DsmIds, - GuidIndex)); - - // - // Check the GuidIndex - the index into the DsmGuildList array - to see - // whether this is a supported GUID or not. - // - switch(GuidIndex) { - - case DSM_LBOperationsGUID_Index: { - - // - // Even though this class only has methods, we need to respond - // to any queries for it since WMI expects that there is an actual - // instance of the class on which to execute the method - // - - sizeNeeded = sizeof(ULONG); - - *DataLength = sizeNeeded; - - if (BufferAvail >= sizeNeeded) { - - *InstanceLengthArray = sizeNeeded; - status = STATUS_SUCCESS; - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_WMI, - "DsmQueryData (DsmIds %p): Buffer too small in query data. Needed %d, Given %d.\n", - DsmIds, - sizeNeeded, - BufferAvail)); - - status = STATUS_BUFFER_TOO_SMALL; - } - - break; - } - - case DSM_QueryLBPolicyGUID_Index: - case DSM_QueryLBPolicyV2GUID_Index: { - - *DataLength = BufferAvail; - - status = DsmpQueryLoadBalancePolicy(DsmContext, - DsmIds, - ((GuidIndex == DSM_QueryLBPolicyGUID_Index) ? DSM_WMI_VERSION_1 : DSM_WMI_VERSION_2), - BufferAvail, - DataLength, - Buffer); - break; - } - - case DSM_QuerySupportedLBPoliciesGUID_Index: - case DSM_QuerySupportedLBPoliciesV2GUID_Index: { - - *DataLength = BufferAvail; - - status = DsmpQuerySupportedLBPolicies(DsmContext, - DsmIds, - BufferAvail, - ((GuidIndex == DSM_QuerySupportedLBPoliciesGUID_Index) ? DSM_WMI_VERSION_1 : DSM_WMI_VERSION_2), - DataLength, - Buffer); - break; - } - - case DSM_QueryDsmUniqueIdGUID_Index: { - - PDSM_QueryUniqueId dsmQueryUniqueId; - - *DataLength = sizeof(DSM_QueryUniqueId); - - if (BufferAvail >= sizeof(DSM_QueryUniqueId)) { - - dsmQueryUniqueId = (PDSM_QueryUniqueId) Buffer; - dsmQueryUniqueId->DsmUniqueId = (ULONGLONG)((ULONG_PTR)DsmContext); - status = STATUS_SUCCESS; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmQueryData (DsmIds %p): Buffersize %d too small for Query Unique Id.\n", - DsmIds, - BufferAvail)); - - status = STATUS_BUFFER_TOO_SMALL; - } - - break; - } - - case MSDSM_DEVICE_PERFGuidIndex: { - - *DataLength = BufferAvail; - - status = DsmpQueryDevicePerf(DsmContext, - DsmIds, - BufferAvail, - DataLength, - Buffer); - - break; - } - - case MSDSM_WMI_METHODSGuidIndex: { - - // - // Even though this class only has methods, we need to respond - // to any queries for it since WMI expects that there is an actual - // instance of the class on which to execute the method - // - - sizeNeeded = sizeof(ULONG); - - *DataLength = sizeNeeded; - - if (BufferAvail >= sizeNeeded) { - - *InstanceLengthArray = sizeNeeded; - status = STATUS_SUCCESS; - - } else { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_WMI, - "DsmQueryData (DsmIds %p): Buffer too small in query data. Needed %d, Given %d.\n", - DsmIds, - sizeNeeded, - BufferAvail)); - - status = STATUS_BUFFER_TOO_SMALL; - } - - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmQueryData (DsmIds %p): Unknown GuidIndex %d in DsmQueryData.\n", - DsmIds, - GuidIndex)); - - *DataLength = 0; - - break; - } - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmQueryData (DsmIds %p): Exiting function with status 0x%x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryLoadBalancePolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG DsmWmiVersion, - _In_ IN ULONG InBufferSize, - _In_ IN PULONG OutBufferSize, - _Out_writes_bytes_(*OutBufferSize) OUT PVOID Buffer - ) -/*+++ - -Routine Description: - - This routine returns the current Load Balance policy settings - for the given device. - -Arguements: - - DsmContext - Global DSM context - DsmIds - DSM Ids for the given device - DsmWmiVersion - version of the MPIO_DSM_Path class to use - InBufferSize - Size of the input buffer - OutBufferSize - Size of the output buffer - Buffer - Buffer in which the current Load Balance policy settings - is returned, if the buffer is big enough - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - PDSM_GROUP_ENTRY groupEntry; - PDSM_DEVICE_INFO devInfo; - PDSM_DEVICE_INFO rtpgDeviceInfo = NULL; - ULONG inx; - ULONG sizeNeeded; - NTSTATUS status = STATUS_SUCCESS; - KIRQL irql; - PDSM_Load_Balance_Policy_V2 supportedLBPolicies; - PMPIO_DSM_Path_V2 dsmPath; - PDSM_FAILOVER_GROUP foGroup; - ULONG SpecialHandlingFlag = 0; - - UNREFERENCED_PARAMETER(InBufferSize); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryLoadBalancePolicy (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // At least one device should be given - // - if (DsmIds->Count == 0) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryLoadBalancePolicy (DsmIds %p): No DSM Ids given in DsmpQueryLoadBalancePolicy.\n", - DsmIds)); - - *OutBufferSize = 0; - status = STATUS_INVALID_PARAMETER; - - goto __Exit_DsmpQueryLoadBalancePolicy; - } - - // - // Compute the size needed for returning LoadBalance policy information - // - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths)); - sizeNeeded += (DsmIds->Count) * sizeof(MPIO_DSM_Path); - - } else { - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths)); - sizeNeeded += (DsmIds->Count * sizeof(MPIO_DSM_Path_V2)); - } - - if (*OutBufferSize < sizeNeeded) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryLoadBalancePolicy (DsmIds %p): Output buffer too small for QueryLBPolicy.\n", - DsmIds)); - - *OutBufferSize = sizeNeeded; - status = STATUS_BUFFER_TOO_SMALL; - - goto __Exit_DsmpQueryLoadBalancePolicy; - } - - // - // Set the size of the data returned to user - // - *OutBufferSize = sizeNeeded; - - // - // Zero out the output buffer first - // - RtlZeroMemory(Buffer, sizeNeeded); - - devInfo = DsmIds->IdList[0]; - DSM_ASSERT(devInfo && devInfo->DeviceSig == DSM_DEVICE_SIG); - groupEntry = devInfo->Group; - - // - // Send down an RTPG to get the current state info if implicit transitions - // are supported, since the states may have changed from under us. - // Storages that support both implicit and explicit transitions that haven't - // allowed us to turn OFF their implicit transitions, may have also changed - // TPG states from under us. So do this for such storages also. - // - if (!DsmpIsSymmetricAccess(devInfo) && - devInfo->ALUASupport != DSM_DEVINFO_ALUA_EXPLICIT) { - - rtpgDeviceInfo = DsmpGetActivePathToBeUsed(groupEntry, FALSE, SpecialHandlingFlag); - - if (!rtpgDeviceInfo) { - - BOOLEAN sendTPG = FALSE; - - rtpgDeviceInfo = DsmpFindStandbyPathToActivateALUA(groupEntry, &sendTPG, SpecialHandlingFlag); - } - - if (rtpgDeviceInfo) { - - status = DsmpGetDeviceALUAState(DsmContext, rtpgDeviceInfo, NULL); - } - } - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // If an RTPG was sent down, update all the devInfo states. - // - if (NT_SUCCESS(status) && rtpgDeviceInfo) { - - DsmpAdjustDeviceStatesALUA(groupEntry, NULL, SpecialHandlingFlag); - } - - supportedLBPolicies = &(((PDSM_QueryLBPolicy_V2)Buffer)->LoadBalancePolicy); - supportedLBPolicies->Version = DSM_WMI_VERSION; - supportedLBPolicies->LoadBalancePolicy = groupEntry->LoadBalanceType; - supportedLBPolicies->DSMPathCount = DsmIds->Count; - dsmPath = supportedLBPolicies->DSM_Paths; - - // - // Indicate which path is active and which path(s) are standby paths - // - inx = 0; - while (inx < DsmIds->Count) { - - devInfo = (PDSM_DEVICE_INFO)DsmIds->IdList[inx]; - - dsmPath->PathWeight = devInfo->PathWeight; - dsmPath->Reserved = DSM_STATE_ACTIVE_OPTIMIZED_SUPPORTED; - - if (devInfo->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED) { - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - dsmPath->TargetPortGroup_State = DSM_DEV_NOT_USED_STATE; - } - - dsmPath->Reserved |= DSM_STATE_STANDBY_SUPPORTED; - - } else { - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - dsmPath->TargetPortGroup_State = devInfo->TargetPortGroup->AsymmetricAccessState; - dsmPath->TargetPortGroup_Preferred = devInfo->TargetPortGroup->Preferred; - dsmPath->TargetPortGroup_Identifier = devInfo->TargetPortGroup->Identifier; - - if (devInfo->TargetPort) { - - dsmPath->TargetPort_Identifier = devInfo->TargetPort->Identifier; - } - - if (groupEntry->Symmetric) { - - // - // For certain policies like FOO and RRWS, we need to be able to put - // path in standby. - // - dsmPath->Reserved |= DSM_STATE_STANDBY_SUPPORTED; - } - } - - dsmPath->Reserved |= devInfo->TargetPortGroup->ActiveUnoptimizedSupported ? DSM_STATE_ACTIVE_UNOPTIMIZED_SUPPORTED : 0; - dsmPath->Reserved |= devInfo->TargetPortGroup->StandBySupported ? DSM_STATE_STANDBY_SUPPORTED : 0; - dsmPath->Reserved |= devInfo->TargetPortGroup->UnavailableSupported ? DSM_STATE_UNAVAILABLE_SUPPORTED : 0; - } - - groupEntry = devInfo->Group; - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - dsmPath->SymmetricLUA = groupEntry->Symmetric; - dsmPath->ALUASupport = devInfo->ALUASupport; - - } - - if (DsmpIsDeviceFailedState(devInfo->State) || !DsmpIsDeviceInitialized(devInfo)) { - - dsmPath->PrimaryPath = FALSE; - dsmPath->DsmPathId = 0; - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - dsmPath->OptimizedPath = dsmPath->PreferredPath = FALSE; - dsmPath->FailedPath = TRUE; - } - - } else { - - foGroup = devInfo->FailGroup; - dsmPath->DsmPathId = (ULONGLONG)((ULONG_PTR)foGroup->PathId); - - if (DsmpIsDeviceStateActive(devInfo->State)) { - - dsmPath->PrimaryPath = TRUE; - } - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - if (devInfo->State == DSM_DEV_ACTIVE_OPTIMIZED || - devInfo->State == DSM_DEV_STANDBY) { - - dsmPath->OptimizedPath = TRUE; - } - - if (((ULONGLONG)((ULONG_PTR)(foGroup->PathId))) == (devInfo->Group->PreferredPath)) { - - dsmPath->PreferredPath = TRUE; - } - } - } - -#if DBG - if (!dsmPath->PrimaryPath && - !dsmPath->FailedPath) { - NT_ASSERT(groupEntry->LoadBalanceType != DSM_LB_ROUND_ROBIN && - groupEntry->LoadBalanceType != DSM_LB_WEIGHTED_PATHS && - groupEntry->LoadBalanceType != DSM_LB_DYN_LEAST_QUEUE_DEPTH && - groupEntry->LoadBalanceType != DSM_LB_LEAST_BLOCKS); - } -#endif - - dsmPath = DsmWmiVersion == DSM_WMI_VERSION_1 ? - (PVOID)((PUCHAR)dsmPath + sizeof(MPIO_DSM_Path)) : - (PVOID)((PUCHAR)dsmPath + sizeof(MPIO_DSM_Path_V2)); - - inx++; - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - -__Exit_DsmpQueryLoadBalancePolicy: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryLoadBalancePolicy (DsmIds %p): Exiting with status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpQuerySupportedLBPolicies( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG BufferAvail, - _In_ IN ULONG DsmWmiVersion, - _Out_ OUT PULONG OutBufferSize, - _Out_writes_to_(BufferAvail, *OutBufferSize) OUT PUCHAR Buffer - ) -/*+++ - -Routine Description: - - This routine returns the load balance policies supported by this DSM for the - given LUN (specified by the DsmIds). - -Arguements: - - DsmContext - Global DSM context - DsmIds - DSM Ids for the given device - BufferAvail - Size of buffer available. - DsmWmiVersion - Indicates which version of MPIO_DSMPath to use. - OutBufferSize - Size of the output buffer. - Buffer - Buffer in which the supported Load Balance policies are - returned, if the buffer is big enough. - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - PDSM_QuerySupportedLBPolicies_V2 supportedLBPolicies; - PDSM_Load_Balance_Policy_V2 dsmLBPolicy; - ULONG sizeNeeded; - ULONG policyCount; - ULONG inx; - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN skipRR = FALSE; - PDSM_DEVICE_INFO devInfo = NULL; - PUCHAR endOfBuffer; - - UNREFERENCED_PARAMETER(DsmContext); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI,"DsmpQuerySupportedLBPolicies (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // At least one device should be given - // - if (DsmIds->Count == 0) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQuerySupportedLBPolicies (DsmIds %p): No DSM Ids given in DsmpQuerySupportedLBPolicies.\n", - DsmIds)); - - *OutBufferSize = 0; - status = STATUS_INVALID_PARAMETER; - - goto __Exit_DsmpQuerySupportedLBPolicies; - } - - devInfo = DsmIds->IdList[0]; - DSM_ASSERT(devInfo && devInfo->DeviceSig == DSM_DEVICE_SIG); - - policyCount = DSM_NUMBER_OF_LB_POLICIES; - - // - // Round Robin policy is not supported for arrays that are AAA. - // - if (!DsmpIsSymmetricAccess(devInfo)) { - - skipRR = TRUE; - policyCount--; - } - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_QuerySupportedLBPolicies, Supported_LB_Policies)); - sizeNeeded += policyCount * AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths)); - - } else { - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_QuerySupportedLBPolicies_V2, Supported_LB_Policies)); - sizeNeeded += policyCount * AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths)); - } - - // - // Set the size of the data returned to user or needed but not provided. - // - *OutBufferSize = sizeNeeded; - - if (sizeNeeded > BufferAvail) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQuerySupportedLBPolicies (Buffer %p): Output buffer too small. Size needed = %u.\n", - Buffer, - sizeNeeded)); - - status = STATUS_BUFFER_TOO_SMALL; - - goto __Exit_DsmpQuerySupportedLBPolicies; - } - - endOfBuffer = Buffer + sizeNeeded - 1; - - // - // Zero out the output buffer first - // - supportedLBPolicies = (PDSM_QuerySupportedLBPolicies_V2)Buffer; - RtlZeroMemory(Buffer, sizeNeeded); - - supportedLBPolicies->SupportedLBPoliciesCount = policyCount; - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - dsmLBPolicy = &(supportedLBPolicies->Supported_LB_Policies[0]); - - } else { - - dsmLBPolicy = (PVOID)&(((PDSM_QuerySupportedLBPolicies)supportedLBPolicies)->Supported_LB_Policies[0]); - } - - // - // All Load Balance policies are supported in Windows Server 2003 - // and above. - // - for (inx = 0; inx < DSM_NUMBER_OF_LB_POLICIES; inx++) { - - // - // Skip reporting Round Robin for AAA arrays. - // - if (((inx + 1) == DSM_LB_ROUND_ROBIN) && skipRR) { - - continue; - } - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - if ((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths)) - 1 > endOfBuffer) { - - status = STATUS_BUFFER_TOO_SMALL; - break; - } - } else { - - if ((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths)) - 1 > endOfBuffer) { - - status = STATUS_BUFFER_TOO_SMALL; - break; - } - } - - dsmLBPolicy->Version = DSM_WMI_VERSION; - - // - // The value set for LoadBalancePolicy is based on - // the #define for LB policies in LBPolicy.h - // - dsmLBPolicy->LoadBalancePolicy = inx + 1; - - // - // Point to the next DSM_Load_Balance_Policy area - // - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - dsmLBPolicy = (PDSM_Load_Balance_Policy_V2)((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths))); - - } else { - - dsmLBPolicy = (PVOID)((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths))); - } - } - -__Exit_DsmpQuerySupportedLBPolicies: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQuerySupportedLBPolicies (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmExecuteMethod( - _In_ IN PVOID DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN PIRP Irp, - _In_ IN ULONG GuidIndex, - _In_ IN ULONG InstanceIndex, - _In_ IN ULONG MethodId, - _In_ IN ULONG InBufferSize, - _In_ IN PULONG OutBufferSize, - _Inout_ IN OUT PUCHAR Buffer, - ... - ) -/*++ - -Routine Description: - - This routine handles the invocation of WMI methods defined in the DSM mof. - -Arguments: - - DsmContext - Global DSM context - DsmIds - DSM Ids - Irp - The WMI Irp - GuidIndex - Index into the WMIGUIDINFO array - InstanceIndex - Index value indicating for which instance data should be returned. - MethodId - Specifies which method to invoke. - InBufferSize - Buffer size, in bytes, of input parameter data. - OutBufferSize - Buffer size, in bytes, of output data. - Buffer - Buffer to which the data is read/written. - -Return Value: - - Status of the method, or STATUS_WMI_ITEMID_NOT_FOUND - ---*/ -{ - NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; - UNREFERENCED_PARAMETER(DsmContext); - UNREFERENCED_PARAMETER(InstanceIndex); - UNREFERENCED_PARAMETER(Irp); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmExecuteMethod (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // This should be the index for ExecMethod Index - // - if (GuidIndex == DSM_LBOperationsGUID_Index) { - - switch (MethodId) { - - case DsmSetLoadBalancePolicy: - case DsmSetLoadBalancePolicyALUA: { - - status = DsmpSetLoadBalancePolicy(DsmContext, - DsmIds, - (MethodId == DsmSetLoadBalancePolicy) ? DSM_WMI_VERSION_1 : DSM_WMI_VERSION_2, - InBufferSize, - OutBufferSize, - Buffer); - break; - } - - default: { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmExecuteMethod (DsmIds %p): Unknown MethodId %d in DsmExecuteMethod.\n", - DsmIds, - MethodId)); - - status = STATUS_WMI_ITEMID_NOT_FOUND; - - break; - } - } - } else if (GuidIndex == MSDSM_WMI_METHODSGuidIndex) { - - if (MethodId == MSDsmClearCounters) { - - status = DsmpClearPerfCounters(DsmContext, DsmIds); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmExecuteMethod (DsmIds %p): Unknown MethodId %d for GuidIndex %d in DsmExecuteMethod.\n", - DsmIds, - MethodId, - GuidIndex)); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmExecuteMethod (DsmIds %p): Unknown GuidIndex %d in DsmExecuteMethod.\n", - DsmIds, - GuidIndex)); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmExecuteMethod (DsmIds %p): Exiting function with status 0x%x.\n", - DsmIds, - status)); - - return status; -} - -NTSTATUS -DsmpClearLoadBalancePolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds - ) -/*++ - -Routine Description: - - This routine is called to clear the LUN-specific load balance policy for the given device. - - First, the routine will try to clear the "explicitly set" registry key for the device. If - this fails, the whole routine is aborted. - - If the registry key is successfully cleared, the following happens: - 1. Check to see if there is a target-wide load balance policy set for this device's VID/PID. - If yes, we set the device's load balance policy accordingly and return. - 2. Check to see if there is an MSDSM-wide load balance policy set. - If yes, we set the device's load balance policy accordingly and return. - 3. If steps 1 and 2 fall through, we set the device's load balance policy to RR, or RRWS if - ALUA is enabled. - -Arguements: - - DsmContext - Global DSM context - DsmIds - DSM Ids for the given device - -Return Value: - - Appropriate status indicating the error if the input is malformed or - if the function was unable to clear the load balance policy. - STATUS_SUCCESS on success - ---*/ - -{ - NTSTATUS status = STATUS_SUCCESS; - PDSM_DEVICE_INFO deviceInfo = NULL; - PDSM_GROUP_ENTRY group = NULL; - HANDLE lbSettingsKey = NULL; - HANDLE deviceKey = NULL; - UNICODE_STRING subKeyName; - OBJECT_ATTRIBUTES objectAttributes; - DSM_LOAD_BALANCE_TYPE loadBalanceType; - ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - ULONG devInfoIndex; - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpClearLoadBalancePolicy (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // There should be at least one device - // - if (DsmIds->Count == 0) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_WMI, - "DsmpClearLoadBalancePolicy (DsmIds %p): No DSM Ids given.\n", - DsmIds)); - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpClearLoadBalancePolicy; - } - - deviceInfo = (PDSM_DEVICE_INFO)DsmIds->IdList[0]; - group = deviceInfo->Group; - - // - // First open LoadBalanceSettings key under the Services key - // - status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpClearLoadBalancePolicy (DevName %ws): Failed to open LB Settings key. Status %x.\n", - group->RegistryKeyName, - status)); - - goto __Exit_DsmpClearLoadBalancePolicy; - } - - // - // Now open the key under which the LB settings for the given device is stored - // and clear the DsmLoadBalancePolicyExplicitlySet key. - // - RtlInitUnicodeString(&subKeyName, group->RegistryKeyName); - - InitializeObjectAttributes(&objectAttributes, - &subKeyName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - lbSettingsKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(&deviceKey, KEY_ALL_ACCESS, &objectAttributes); - - if (NT_SUCCESS(status)) { - - UCHAR explicitlySet = FALSE; - - status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, - deviceKey, - DSM_POLICY_EXPLICITLY_SET, - REG_BINARY, - &explicitlySet, - sizeof(UCHAR)); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpClearLoadBalancePolicy (DevName %ws): Failed to clear DsmLoadBalancePolicyExplicitlySet key.\n", - group->RegistryKeyName)); - - goto __Exit_DsmpClearLoadBalancePolicy; - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpClearLoadBalancePolicy (DevName %ws): Failed to open device subkey.\n", - group->RegistryKeyName)); - - goto __Exit_DsmpClearLoadBalancePolicy; - } - - - - // - // Set the defaults. These will be used if no target-wide or MSDSM-wide - // load balance policies are set. - // - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; - loadBalanceType = DSM_LB_ROUND_ROBIN; - preferredPath = 0; - - // - // Check to see if target-wide (VID/PID) LB policy is set for this device. - // - status = DsmpQueryTargetLBPolicyFromRegistry(deviceInfo, - &loadBalanceType, - &preferredPath); - if (NT_SUCCESS(status)) { - - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_VID_PID; - - } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { - - // - // Since the policy hasn't been set for this VID/PID, check if - // overall MSDSM-wide policy has been set. - // - status = DsmpQueryDsmLBPolicyFromRegistry(&loadBalanceType, - &preferredPath); - if (NT_SUCCESS(status)) { - - group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpClearLoadBalancePolicy (DevInfo %p): Failed to query Dsm overall LB policy from registry. Status %x.\n", - deviceInfo, - status)); - - NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); - status = STATUS_SUCCESS; - } - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_PNP, - "DsmpClearLoadBalancePolicy (DevInfo %p): Failed to query VID/PID LB policy from registry. Status %x.\n", - deviceInfo, - status)); - - NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); - status = STATUS_SUCCESS; - } - - - // - // If the storage is ALUA enabled and we specified Round Robin, change - // it to Round Robin with Subset instead. - // - if (!DsmpIsSymmetricAccess(deviceInfo) && loadBalanceType == DSM_LB_ROUND_ROBIN) { - - loadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; - } - - // - // Finally set the load balance policy and the preferred path. - // - group->LoadBalanceType = loadBalanceType; - group->PreferredPath = preferredPath; - - // - // Update the path states in accordance with the new policy. - // - for (devInfoIndex = 0; devInfoIndex < DSM_MAX_PATHS; devInfoIndex++) { - - DsmpSetNewDefaultLBPolicy(DsmContext, - group->DeviceList[devInfoIndex], - group->LoadBalanceType, - SpecialHandlingFlag); - } - -__Exit_DsmpClearLoadBalancePolicy: - - if (deviceKey) { - ZwClose(deviceKey); - } - - if (lbSettingsKey) { - ZwClose(lbSettingsKey); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpClearLoadBalancePolicy (DsmIds %p): Exiting function with status 0x%x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpSetLoadBalancePolicy( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG DsmWmiVersion, - _In_ IN ULONG InBufferSize, - _In_ IN PULONG OutBufferSize, - _In_ IN PVOID Buffer - ) -/*++ - -Routine Description: - - This routine is called to set the load balance policy for the given device. - - If zero is passed in as the load balance policy, the LUN-specific load balance - policy will attempt to be cleared. See DsmpClearLoadBalancePolicy for more details. - -Arguements: - - DsmContext - Global DSM context - DsmIds - DSM Ids for the given device - DsmWmiVersion - version of the MPIO_DSM_Path class to use - InBufferSize - Size of the input buffer - OutBufferSize - Size of the output buffer - Buffer - Buffer for input\output data - -Return Value: - - STATUS_BUFFER_TOO_SMALL - If the input buffer is too small - Appropriate status indicating the error if the input is malformed. - STATUS_SUCCESS on success - ---*/ - -{ - PDsmSetLoadBalancePolicyALUA_IN setLoadBalancePolicyIN = (PDsmSetLoadBalancePolicyALUA_IN) Buffer; - PDsmSetLoadBalancePolicyALUA_OUT setLoadBalancePolicyOUT = (PDsmSetLoadBalancePolicyALUA_OUT) Buffer; - PVOID supportedLBPolicies; - PMPIO_DSM_Path_V2 dsmPath; - ULONG inx = 0; - ULONG jnx; - NTSTATUS status = STATUS_SUCCESS; - BOOLEAN lengthOkay = TRUE; - PDSM_DEVICE_INFO devInfo = NULL; - PDSM_DEVICE_INFO tempDevInfo = NULL; - PDSM_GROUP_ENTRY groupEntry; - PDSM_LOAD_BALANCE_POLICY_SETTINGS savedLBSettings = NULL; - KIRQL irql; - BOOLEAN optimized = TRUE; - BOOLEAN preferred = FALSE; - ULONG activePaths = 0; - ULONG activeTPGs = 0; - ULONG numberDevInfoChanged = 0; - ULONG numberPreferredPaths = 0; - DSM_LOAD_BALANCE_TYPE loadBalancePolicy; - BOOLEAN sendSTPG = FALSE; - ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - ULONG SpecialHandlingFlag = 0; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // There should be at least one device - // - if (DsmIds->Count == 0) { - - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): No DSM Ids given.\n", - DsmIds)); - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpSetLoadBalancePolicy; - } - - groupEntry = ((PDSM_DEVICE_INFO)DsmIds->IdList[0])->Group; - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - if (*OutBufferSize < sizeof(DsmSetLoadBalancePolicy_OUT)) { - - *OutBufferSize = sizeof(DsmSetLoadBalancePolicy_OUT); - lengthOkay = FALSE; - } - } else { - - if (*OutBufferSize < sizeof(DsmSetLoadBalancePolicyALUA_OUT)) { - - *OutBufferSize = sizeof(DsmSetLoadBalancePolicyALUA_OUT); - lengthOkay = FALSE; - } - } - - if (!lengthOkay) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Buffer too small for SetLBPolicy.\n", - DsmIds)); - - status = STATUS_BUFFER_TOO_SMALL; - goto __Exit_DsmpSetLoadBalancePolicy; - } - - *OutBufferSize = (DsmWmiVersion == DSM_WMI_VERSION_1) ? sizeof(DsmSetLoadBalancePolicy_OUT) : sizeof(DsmSetLoadBalancePolicyALUA_OUT); - - // - // If the user specified zero as the load balance policy, we need to clear the - // LUN-specific load balance policy. - // - if (setLoadBalancePolicyIN->LoadBalancePolicy.LoadBalancePolicy == 0) { - status = DsmpClearLoadBalancePolicy(DsmContext, DsmIds); - goto __Exit_DsmpSetLoadBalancePolicy; - } - - status = DsmpValidateSetLBPolicyInput(DsmContext, - DsmIds, - DsmWmiVersion, - Buffer, - InBufferSize); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Failed to validate input. Status %x.\n", - DsmIds, - status)); - - goto __Exit_DsmpSetLoadBalancePolicy; - } - - // - // At this point the Reserved field in each MPIO_DSM_Path should - // contain the respective Device Info - // - supportedLBPolicies = &(setLoadBalancePolicyIN->LoadBalancePolicy); - loadBalancePolicy = ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->LoadBalancePolicy; - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Cache each DeviceInfo's current state. - // This will be used to rollback in case of errors. - // - DsmpSaveDeviceState(supportedLBPolicies, DsmWmiVersion); - - while (inx < ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSMPathCount) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); - - optimized = TRUE; - preferred = FALSE; - - } else { - - dsmPath = &(((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSM_Paths[inx]); - - optimized = dsmPath->OptimizedPath ? TRUE : FALSE; - preferred = dsmPath->PreferredPath ? TRUE : FALSE; - - if (preferred && loadBalancePolicy == DSM_LB_FAILOVER) { - - preferredPath = dsmPath->DsmPathId; - - if (preferredPath != 0) { - - numberPreferredPaths++; - } - - if (numberPreferredPaths > 1) { - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - status = STATUS_INVALID_PARAMETER; - break; - } - } - } - - // - // Reserved field in MPIO_DSM_Path is set to DeviceInfo in - // DsmpValidateSetLBPolicyInput routine. - // - devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; - - if (!devInfo) { - - inx++; - continue; - - } else { - - if (!tempDevInfo) { - - tempDevInfo = devInfo; - - if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || - loadBalancePolicy == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { - - InterlockedExchangePointer(&(groupEntry->PathToBeUsed), NULL); - } - } - } - - if (!DsmpIsDeviceFailedState(devInfo->State)) { - - if (devInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { - - activeTPGs++; - } - - if (dsmPath->PrimaryPath) { - - // - // Optimized flag decides between AO and AU - // - if (optimized) { - - // - // For implicit-only ALUA, state cannot be explicitly changed to A/O - // - if (!DsmpIsSymmetricAccess(devInfo) && devInfo->ALUASupport == DSM_DEVINFO_ALUA_IMPLICIT) { - - // - // While we can mask off acutal A/O to be A/U, there is no - // way to explicitly make non-A/O state A/O - // - if (devInfo->ALUAState != DSM_DEV_ACTIVE_OPTIMIZED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Can't make non-AO path A/O for Implicit-only transitions.\n", - DsmIds)); - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - status = STATUS_INVALID_PARAMETER; - break; - } - } - - numberDevInfoChanged++; - - devInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; - activePaths++; - - // - // Check to see if the actual making of this path state A/O - // will require an STPG to be sent down. - // - if (devInfo->TargetPortGroup && - devInfo->ALUAState != DSM_DEV_ACTIVE_OPTIMIZED) { - - sendSTPG = TRUE; - } - - if (loadBalancePolicy == DSM_LB_FAILOVER) { - - // - // Only ONE path can be specified as AO for FailOverOnly policy. - // - if (activePaths > 1) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): More than one AO node given for FO Only.\n", - DsmIds)); - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - status = STATUS_INVALID_PARAMETER; - break; - } - } - - if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || - loadBalancePolicy == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { - - if (!groupEntry->PathToBeUsed) { - InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)devInfo->FailGroup); - } - } - } else { - - // - // This is an ActiveUnoptimized path - // - devInfo->State = DSM_DEV_ACTIVE_UNOPTIMIZED; - - // - // For LB policy RR, WP, LB and LQD, all paths must be in A/O - // state. However, this is not possible for ALUA storages. - // For these storages, A/U is allowable only if that is the - // access state that the TPG is in. - // - if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || - loadBalancePolicy == DSM_LB_WEIGHTED_PATHS || - loadBalancePolicy == DSM_LB_DYN_LEAST_QUEUE_DEPTH || - loadBalancePolicy == DSM_LB_LEAST_BLOCKS) { - - if (devInfo->TargetPortGroup && devInfo->ALUAState != DSM_DEV_ACTIVE_UNOPTIMIZED) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Path (%u) specified in A/U state when TPG is in %u state (for LB %u).\n", - DsmIds, - inx, - devInfo->ALUAState, - loadBalancePolicy)); - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - status = STATUS_INVALID_PARAMETER; - break; - } - } - } - } else { - - if (optimized) { - - // - // This is a standby path - // - devInfo->State = DSM_DEV_STANDBY; - - } else { - - // - // This is unavailable path - // - devInfo->State = DSM_DEV_UNAVAILABLE; - } - - // - // For RR, LQD, LB and WP, all paths must be in A/O state for non-ALUA - // storage. For ALUA storage, the only time path states can be in - // S/B or U/A is if the TPG itself is in that state. - // - if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || - loadBalancePolicy == DSM_LB_WEIGHTED_PATHS || - loadBalancePolicy == DSM_LB_DYN_LEAST_QUEUE_DEPTH || - loadBalancePolicy == DSM_LB_LEAST_BLOCKS) { - - if ((!devInfo->TargetPortGroup) || - (devInfo->TargetPortGroup && devInfo->State != devInfo->ALUAState)) { - - // - // No paths can be in SB or UA unless its TPG is in that state. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Path (%u) specified in non-active state for LB %u.\n", - DsmIds, - inx, - loadBalancePolicy)); - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - status = STATUS_INVALID_PARAMETER; - break; - } - } else if (loadBalancePolicy == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { - - // - // It is okay to set a path to be in S/B or U/A state in RRWS - // if either the storage is non-ALUA, or if the storage is - // ALUA but the TPG is in A/O (where it can be masked) or the - // TPG is in the state that the path is being set to. - // - if ((devInfo->TargetPortGroup) && - (devInfo->ALUAState != DSM_DEV_ACTIVE_OPTIMIZED && devInfo->State != devInfo->ALUAState)) { - - // - // No paths can be in SB or UA unless its TPG is in that state. - // - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Path (%u) (in TPG state %u) can't be specified in non-active state for LB %u.\n", - DsmIds, - inx, - devInfo->ALUAState, - loadBalancePolicy)); - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - status = STATUS_INVALID_PARAMETER; - break; - } - } - } - } - - inx++; - } - - if (NT_SUCCESS(status)) { - - - // - // If we arrive here, that means DsmpValidateSetLBPolicyInput already returned success. - // The device info is found. - // - _Analysis_assume_(tempDevInfo != NULL); - - // - // There must be at least one AO path. Unless there are no A/O TPGs. - // eg. During a controller failover, it is possible that the TPG through - // the TPG through other controller is still in non-A/O state and the - // storage supports implicit transitions and is still in the midst of - // making the transition of the non-A/O TPG to A/O. During such windows - // the states for all paths will be non-A/O and there's nothing that can - // be done about it. This is not an error condition. - // - if (!activePaths) { - - if ((tempDevInfo->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED) || - (tempDevInfo->ALUASupport != DSM_DEVINFO_ALUA_NOT_SUPPORTED && activeTPGs)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): No active node given for LB %u.\n", - DsmIds, - loadBalancePolicy)); - - // - // Roll back to DeviceState to the state it was before - // processing this SetLB policy request - // - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - - status = STATUS_INVALID_PARAMETER; - } - } - } - - if (NT_SUCCESS(status)) { - - // - // If we arrive here, that means DsmpValidateSetLBPolicyInput already returned success. - // The device info is found. - // - _Analysis_assume_(tempDevInfo != NULL); - - // - // If device supports explicit transitions, we need to send down an - // STPG to enforce A/O path selection if we need to make a path in a - // non-A/O TPG active/optimized. - // - if (tempDevInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT && sendSTPG) { - - PUCHAR targetPortGroupsInfo = NULL; - ULONG targetPortGroupsInfoLength = 0; - PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR tpgDescriptor = NULL; - - // - // Build the target port groups info to set the new states. - // Send down an STPG for TPG descriptors for those devInfos' TPGs - // that need to be in AO state. If this causes side-effects in - // state transitions (these can't be considered implicit according - // to the spec), fake the devInfo states to what was selected. - // - targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + - activePaths * sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); - - targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, - targetPortGroupsInfoLength, - DSM_TAG_TARGET_PORT_GROUPS); - - if (targetPortGroupsInfo) { - - PDSM_DEVICE_INFO devInfoToUse = NULL; - - // - // Set the new asymmetric access states for the the devices' target port groups - // - tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)(targetPortGroupsInfo + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE); - - for (inx = 0, jnx = 0; - inx < ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSMPathCount; - inx++) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); - - } else { - - dsmPath = &(((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSM_Paths[inx]); - } - - devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; - - if (!devInfo) { - - continue; - } - - if (devInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { - - tpgDescriptor->AsymmetricAccessState = devInfo->State; - REVERSE_BYTES_SHORT(&tpgDescriptor->TPG_Identifier, &devInfo->TargetPortGroup->Identifier); - - tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)((PUCHAR)tpgDescriptor + sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)); - - jnx++; - } - - if (devInfo->TempPreviousStateForLB == DSM_DEV_ACTIVE_OPTIMIZED) { - - devInfoToUse = devInfo; - } - } - - NT_ASSERT(jnx == numberDevInfoChanged); - NT_ASSERT(devInfoToUse); - - if (devInfoToUse) { - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - status = DsmpSetTargetPortGroups(devInfoToUse->TargetObject, - targetPortGroupsInfo, - targetPortGroupsInfoLength); - - if (NT_SUCCESS(status)) { - - DsmpFreePool(targetPortGroupsInfo); - targetPortGroupsInfo = NULL; - targetPortGroupsInfoLength = 0; - status = DsmpReportTargetPortGroups(devInfoToUse->TargetObject, - &targetPortGroupsInfo, - &targetPortGroupsInfoLength); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): STPG failed with status %x.\n", - DsmIds, - status)); - - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - } - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - } - - if (NT_SUCCESS(status)) { - - ULONG index; - PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup; - - status = DsmpParseTargetPortGroupsInformation(DsmContext, - groupEntry, - targetPortGroupsInfo, - targetPortGroupsInfoLength); - - NT_ASSERT(NT_SUCCESS(status)); - - for (index = 0; index < DSM_MAX_PATHS; index++) { - - targetPortGroup = groupEntry->TargetPortGroupList[index]; - - if (targetPortGroup) { - - DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); - } - } - - // - // Update TPGs with new state - // - for (inx = 0; - inx < ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSMPathCount; - inx++) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); - - } else { - - dsmPath = &(((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSM_Paths[inx]); - } - - devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; - - if (devInfo) { - - // - // An explicit state transition can cause TPGs that were not specified - // in the parameter list to also change (this is not considered to be - // an implicit transition. It is SPC3 behavior and we must take - // this into consideration and update the devInfo states. - // This is an unfortunate side-effect in that the Admin may not get - // the paths to be in the exact states that he has set. - // - if (devInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { - - if (devInfo->ALUAState == DSM_DEV_ACTIVE_UNOPTIMIZED || - devInfo->ALUAState == DSM_DEV_STANDBY || - devInfo->ALUAState == DSM_DEV_UNAVAILABLE) { - - // - // An A/O TPG's devInfos can be masked as A/U. - // However, the reverse the is not true (ie. we can't - // mark a non-A/O TPG's devInfo(s) to be in A/O state. - // - devInfo->State = devInfo->ALUAState; - } - } - - // - // The devInfo->State has already been set. Update its previous state. - // - devInfo->PreviousState = devInfo->TempPreviousStateForLB; - } - } - - NT_ASSERT(jnx == numberDevInfoChanged); - } - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Failed to allocate targetPortGroupsInfo.\n", - DsmIds)); - - status = STATUS_INSUFFICIENT_RESOURCES; - } - } - - if (NT_SUCCESS(status)) { - - groupEntry->LoadBalanceType = loadBalancePolicy; - - if (loadBalancePolicy == DSM_LB_FAILOVER) { - - groupEntry->PreferredPath = preferredPath; - } - - savedLBSettings = DsmpCopyLoadBalancePolicies(groupEntry, - DsmWmiVersion, - supportedLBPolicies); - - } else { - - // - // Roll back to DeviceState to the state it was before - // processing this SetLB policy request - // - DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); - } - } - - if (NT_SUCCESS(status)) { - - // - // LUN's LB policy has been explicitly set by Admin - // - groupEntry->LBPolicySelection = DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT; - - // - // Update the states and if appropriate, the path weight - // - DsmpUpdateDesiredStateAndWeight(groupEntry, - DsmWmiVersion, - supportedLBPolicies); - - // - // Update the next path to be used for the group - // - devInfo = DsmpGetActivePathToBeUsed(groupEntry, - DsmpIsSymmetricAccess(tempDevInfo), - SpecialHandlingFlag); - if (devInfo != NULL) { - - InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)devInfo->FailGroup); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): After setting LB policy No FOG available for group %p\n", - DsmIds, - groupEntry)); - - InterlockedExchangePointer(&(groupEntry->PathToBeUsed), NULL); - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - if (NT_SUCCESS(status) && savedLBSettings) { - - DsmpPersistLBSettings(savedLBSettings); - - DsmpFreePool(savedLBSettings); - } - -__Exit_DsmpSetLoadBalancePolicy: - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - ((PDsmSetLoadBalancePolicy_OUT)setLoadBalancePolicyOUT)->Status = status; - - } else { - - setLoadBalancePolicyOUT->Status = status; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSetLoadBalancePolicy (DsmIds %p): Exiting function with status 0x%x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpValidateSetLBPolicyInput( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds, - _In_ IN ULONG DsmWmiVersion, - _In_ IN PVOID SetLoadBalancePolicyIN, - _In_ IN ULONG InBufferSize - ) -/*++ - -Routine Description: - - This routine validates the input buffer given for setting - Load Balance policy - -Arguements: - - DsmContext - DSM Global Context - DsmIds - DSM Ids for the given device - DsmWmiVersion - version of the MPIO_DSM_Path class to use - SetLoadBalancePolicyIN - Describes the load balance policy to be set - InBufferSize - Number of bytes in SetLoadBalancePolicyIN - -Return Value: - - STATUS_SUCCESS - if the input buffer is well formed - Appropriate error status if the input buffer is malformed. - ---*/ -{ - PDSM_Load_Balance_Policy_V2 supportedLBPolicies; - PMPIO_DSM_Path_V2 dsmPath0; - PMPIO_DSM_Path_V2 dsmPath1; - NTSTATUS status = STATUS_SUCCESS; - ULONG inx; - ULONG jnx; - ULONG sizeNeeded; - KIRQL irql; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // Validate the input buffer for setting Load Balance policy - // - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - sizeNeeded = FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths); - - } else { - - sizeNeeded = FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths); - } - - if (InBufferSize < sizeNeeded) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Insufficient buffer in SetLB. Expected %d, Given %d.\n", - DsmIds, - sizeNeeded, - InBufferSize)); - - status = STATUS_BUFFER_TOO_SMALL; - goto __Exit_DsmpValidateSetLBPolicyInput; - } - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - supportedLBPolicies = (PVOID)&(((PDsmSetLoadBalancePolicy_IN)SetLoadBalancePolicyIN)->LoadBalancePolicy); - - sizeNeeded += supportedLBPolicies->DSMPathCount * sizeof(MPIO_DSM_Path); - - } else { - - supportedLBPolicies = &(((PDsmSetLoadBalancePolicyALUA_IN)SetLoadBalancePolicyIN)->LoadBalancePolicy); - - sizeNeeded += supportedLBPolicies->DSMPathCount * sizeof(MPIO_DSM_Path_V2); - } - - if (InBufferSize < sizeNeeded) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Insufficient buffer in SetLB. Expected %d, Given %d.\n", - DsmIds, - sizeNeeded, - InBufferSize)); - - status = STATUS_BUFFER_TOO_SMALL; - goto __Exit_DsmpValidateSetLBPolicyInput; - } - - if (supportedLBPolicies->Version > DSM_WMI_VERSION) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): WMI Version mismatch. Expected %d, Given %d.\n", - DsmIds, - DSM_WMI_VERSION, - supportedLBPolicies->Version)); - - status = DSM_UNSUPPORTED_VERSION; - goto __Exit_DsmpValidateSetLBPolicyInput; - - } else if (supportedLBPolicies->Version < DSM_WMI_VERSION) { - - ULONG dsmWmiVersion = DSM_WMI_VERSION; - TracePrint((TRACE_LEVEL_WARNING, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Use of older management app (WMI-Version %x) with newer DSM (WMI-Version %x).\n", - DsmIds, - supportedLBPolicies->Version, - dsmWmiVersion)); - - NT_ASSERT(supportedLBPolicies->Version == DSM_WMI_VERSION); - } - - if ((supportedLBPolicies->LoadBalancePolicy < DSM_LB_FAILOVER) || - (supportedLBPolicies->LoadBalancePolicy > DSM_LB_LEAST_BLOCKS)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Invalid LB Policy %d.\n", - DsmIds, - supportedLBPolicies->LoadBalancePolicy)); - - status = DSM_INVALID_LOAD_BALANCE_POLICY; - goto __Exit_DsmpValidateSetLBPolicyInput; - } - - // - // It is expected that the user provide LB policy settings - // for all the paths and not just a subset of the paths. - // - if (supportedLBPolicies->DSMPathCount != DsmIds->Count) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Path Count %d not equal to DSM IDs count %d.\n", - DsmIds, - supportedLBPolicies->DSMPathCount, - DsmIds->Count)); - - status = STATUS_INVALID_PARAMETER; - goto __Exit_DsmpValidateSetLBPolicyInput; - } - - // - // Make sure user did not provide duplicate path ids - // - for (inx = 0; inx < supportedLBPolicies->DSMPathCount && NT_SUCCESS(status); inx++) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath0 = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); - - } else { - - dsmPath0 = &(supportedLBPolicies->DSM_Paths[inx]); - } - - dsmPath0->Reserved = 0; - - for (jnx = 0; jnx < supportedLBPolicies->DSMPathCount; jnx++) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath1 = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[jnx]); - - } else { - - dsmPath1 = &(supportedLBPolicies->DSM_Paths[jnx]); - } - - if ((inx != jnx) && - ((dsmPath0->DsmPathId == dsmPath1->DsmPathId) && (dsmPath1->DsmPathId != 0))) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Duplicate path id %I64x at %d and %d.\n", - DsmIds, - dsmPath0->DsmPathId, - inx, - jnx)); - - status = STATUS_INVALID_PARAMETER; - - break; - } - } - } - - if (NT_SUCCESS(status)) { - - PDSM_DEVICE_INFO devInfo; - PDSM_FAILOVER_GROUP foGroup; - PVOID pathId; - BOOLEAN foundPath; - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - // - // Make sure the user has provided path id corresponding - // to all the DSM IDs given to us. - // - for (inx = 0; inx < DsmIds->Count; inx++) { - - devInfo = DsmIds->IdList[inx]; - - if (!DsmpIsDeviceInitialized(devInfo)) { - - continue; - } - - foGroup = devInfo->FailGroup; - if (!foGroup) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): FO Group NULL for %p at index %d.\n", - DsmIds, - devInfo, - inx)); - - status = STATUS_INVALID_PARAMETER; - - break; - } - - foundPath = FALSE; - - for (jnx = 0; jnx < supportedLBPolicies->DSMPathCount; jnx++) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath0 = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[jnx]); - - } else { - - dsmPath0 = &(supportedLBPolicies->DSM_Paths[jnx]); - } - - pathId = (PVOID) dsmPath0->DsmPathId; - if (foGroup->PathId == pathId) { - - // - // Found the device info corresponding to the given path. - // Use the reserved field in MPIO_DSM_Path to store - // the pointer to the device info. Device Info is used - // later on to set the load balance policy for the device. - // - foundPath = TRUE; - - dsmPath0->Reserved = (ULONG_PTR) devInfo; - - // - // If ALUA, RoundRobin is not an allowed LB policy since not all paths can - // be in A/O state. RRWS must be used instead. - // - if (supportedLBPolicies->LoadBalancePolicy == DSM_LB_ROUND_ROBIN && !DsmpIsSymmetricAccess(devInfo)) { - - status = DSM_INVALID_LOAD_BALANCE_POLICY; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Invalid LB policy for ALUA. Status %x.\n", - DsmIds, - status)); - } - - break; - } - } - - if (!foundPath) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Failed to find path %p for %p at index %d.\n", - DsmIds, - foGroup->PathId, - devInfo, - inx)); - - status = STATUS_INVALID_PARAMETER; - - break; - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - } - -__Exit_DsmpValidateSetLBPolicyInput: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpValidateSetLBPolicyInput (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -VOID -DsmpSaveDeviceState( - _In_ IN PVOID SupportedLBPolicies, - _In_ IN ULONG DsmWmiVersion - ) -/*+++ - -Routine Description: - - This routine saves the current Load Balance policy settings. - If there is any error while setting the new policy given - by the user, the saved values will be used to restore - the old state. - - Note: This routine MUST be called with DsmContextLock held in Exclusive mode. - -Arguements: - - SupportedLBPolicies - New Load Balance policy values - DsmWmiVersion - version of the MPIO_DSM_Path class to use - -Return Value: - - None ---*/ -{ - PDSM_DEVICE_INFO devInfo; - PMPIO_DSM_Path_V2 dsmPath; - ULONG inx; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSaveDeviceState (LBP %p): Entering function.\n", - SupportedLBPolicies)); - - inx = 0; - - while (inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]); - - } else { - - dsmPath = &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]); - } - - devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; - - if (devInfo) { - - devInfo->TempPreviousStateForLB = devInfo->State; - } - - inx++; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpSaveDeviceState (LBP %p): Exiting function.\n", - SupportedLBPolicies)); - - return; -} - - -VOID -DsmpRestorePreviousDeviceState( - _In_ IN PVOID SupportedLBPolicies, - _In_ IN ULONG DsmWmiVersion - ) -/*++ - -Routine Description: - - This routine restores the old Load Balance policy settings. - If there is any error while setting the new policy given - by the user, the old state is restored from the saved state. - - Note: This routine MUST be called with DsmContextLock held in Exclusive mode. - -Arguements: - - SupportedLBPolicies - New Load Balance policy values - DsmWmiVersion - version of the MPIO_DSM_Path class to use - -Return Value: - - None ---*/ -{ - PDSM_DEVICE_INFO devInfo; - PMPIO_DSM_Path_V2 dsmPath; - ULONG inx; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpRestorePreviousDeviceState (LBP %p): Entering function.\n", - SupportedLBPolicies)); - - inx = 0; - - while (inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]); - - } else { - - dsmPath = &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]); - } - - devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; - - if (devInfo) { - - devInfo->State = devInfo->TempPreviousStateForLB; - } - - inx++; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpRestorePreviousDeviceState (LBP %p): Exiting function.\n", - SupportedLBPolicies)); - - return; -} - - -VOID -DsmpUpdateDesiredStateAndWeight( - _In_ IN PDSM_GROUP_ENTRY Group, - _In_ IN ULONG DsmWmiVersion, - _In_ IN PVOID SupportedLBPolicies - ) -/*++ - -Routine Description: - - This routine updates the desired state and path weights - based on admin's LB selection. - - Note: This routine MUST be called with DsmContextLock held in Exclusive mode. - -Arguements: - - Group - The group entry correponding to the pseudo-LUN. - SupportedLBPolicies - New Load Balance policy values - DsmWmiVersion - version of the MPIO_DSM_Path class to use - -Return Value: - - None ---*/ -{ - PMPIO_DSM_Path_V2 dsmPath; - PDSM_DEVICE_INFO devInfo; - ULONG inx; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpUpdatedDesiredState (Group %p): Entering function.\n", - Group)); - - inx = 0; - while (inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount) { - - if (DsmWmiVersion == DSM_WMI_VERSION_1) { - - dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]); - - } else { - - dsmPath = &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]); - } - - devInfo = (PDSM_DEVICE_INFO) dsmPath->Reserved; - - if (!devInfo) { - - inx++; - continue; - } - - DSM_ASSERT(devInfo->DeviceSig == DSM_DEVICE_SIG); - NT_ASSERT(devInfo->Group == Group); - - // - // We'll honor the chosen path for FOO for ALUA storage - // since we know for a fact that the Admin has chosen the path. - // We'll also honor path state in RRWS if it is different from TPG state - // as that too is an indication that it was explicitly selected. - // - if ((DsmpIsSymmetricAccess(devInfo)) || - (Group->LoadBalanceType == DSM_LB_FAILOVER) || - (!DsmpIsSymmetricAccess(devInfo) && Group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET && devInfo->State != devInfo->ALUAState)) { - - // - // Check if this is the primary path or a standby path - // - if (dsmPath->PrimaryPath) { - - devInfo->DesiredState = DSM_DEV_ACTIVE_OPTIMIZED; - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - if (!dsmPath->OptimizedPath) { - - devInfo->DesiredState = DSM_DEV_ACTIVE_UNOPTIMIZED; - } - } - - } else { - - devInfo->DesiredState = DSM_DEV_STANDBY; - - if (DsmWmiVersion > DSM_WMI_VERSION_1) { - - if (!dsmPath->OptimizedPath) { - - devInfo->DesiredState = DSM_DEV_UNAVAILABLE; - } - } - } - } else { - - devInfo->DesiredState = DSM_DEV_UNDETERMINED; - } - - if (Group->LoadBalanceType == DSM_LB_WEIGHTED_PATHS) { - - devInfo->PathWeight = dsmPath->PathWeight; - } - - inx++; - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpUpdatedDesiredState (Group %p): Exiting function.\n", - Group)); - - return; -} - - -NTSTATUS -DsmpQueryDevicePerf( - _In_ PDSM_CONTEXT DsmContext, - _In_ PDSM_IDS DsmIds, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ) -/*++ - -Routine Description: - - This routine returns the perf counters for each path for the - device that corresponds to the passed in DsmIds. - -Arguements: - - DsmContext - Global DSM context - DsmIds - DSM Ids for the given device - InBufferSize - Size of the input buffer - OutBufferSize - Size of the output buffer - Buffer - Buffer in which the current Load Balance policy settings - is returned, if the buffer is big enough - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDSM_DEVICE_INFO devInfo; - ULONG sizeNeeded; - PMSDSM_DEVICE_PERF devicePerf; - ULONG i; - PMSDSM_DEVICEPATH_PERF pathPerf; - KIRQL irql; - - UNREFERENCED_PARAMETER(InBufferSize); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryDevicePerf (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // At least one device should be given - // - if (DsmIds->Count == 0) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryDevicePerf (DsmIds %p): No DSM Ids given.\n", - DsmIds)); - - *OutBufferSize = 0; - status = STATUS_INVALID_PARAMETER; - - goto __Exit_DsmpQueryDevicePerf; - } - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(MSDSM_DEVICE_PERF, PerfInfo)); - sizeNeeded += (DsmIds->Count * sizeof(MSDSM_DEVICEPATH_PERF)); - - if (*OutBufferSize < sizeNeeded) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryDevicePerf (DsmIds %p): Output buffer too small for QueryLBPolicy.\n", - DsmIds)); - - *OutBufferSize = sizeNeeded; - status = STATUS_BUFFER_TOO_SMALL; - - goto __Exit_DsmpQueryDevicePerf; - } - - // - // Zero out the output buffer first - // - RtlZeroMemory(Buffer, sizeNeeded); - -#if DBG - devInfo = DsmIds->IdList[0]; - DSM_ASSERT(devInfo); - DSM_ASSERT(devInfo->DeviceSig == DSM_DEVICE_SIG); -#endif - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - devicePerf = (PMSDSM_DEVICE_PERF)Buffer; - devicePerf->NumberPaths = DsmIds->Count; - - // - // For each path, get the stats info - // - for (i = 0; i < DsmIds->Count; i++) { - - pathPerf = &devicePerf->PerfInfo[i]; - devInfo = DsmIds->IdList[i]; - - if (DsmpIsDeviceInitialized(devInfo)) { - - pathPerf->PathId = (ULONGLONG)((ULONG_PTR)((devInfo->FailGroup)->PathId)); - pathPerf->NumberReads = (devInfo->DeviceStats).NumberReads; - pathPerf->NumberWrites = (devInfo->DeviceStats).NumberWrites; - pathPerf->BytesRead = (devInfo->DeviceStats).BytesRead; - pathPerf->BytesWritten = (devInfo->DeviceStats).BytesWritten; - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - - *OutBufferSize = sizeNeeded; - -__Exit_DsmpQueryDevicePerf: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryDevicePerf (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpClearPerfCounters( - _In_ IN PDSM_CONTEXT DsmContext, - _In_ IN PDSM_IDS DsmIds - ) -/*++ - -Routine Description: - - This routine clears the perf counters for each path for the - device that corresponds to the passed in DsmIds. - -Arguements: - - DsmContext - Global DSM context - DsmIds - DSM Ids for the given device - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - NTSTATUS status = STATUS_SUCCESS; - PDSM_DEVICE_INFO devInfo; - KIRQL irql; - ULONG i; - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpClearPerfCounters (DsmIds %p): Entering function.\n", - DsmIds)); - - // - // At least one device should be given - // - if (DsmIds->Count == 0) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpClearPerfCounters (DsmIds %p): No DSM Ids given.\n", - DsmIds)); - - status = STATUS_INVALID_PARAMETER; - - goto __Exit_DsmpClearPerfCounters; - } - - irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); - - for (i = 0; i < DsmIds->Count; i++) { - - devInfo = DsmIds->IdList[i]; - DSM_ASSERT(devInfo); - DSM_ASSERT(devInfo->DeviceSig == DSM_DEVICE_SIG); - - if (devInfo) { - (devInfo->DeviceStats).BytesRead = 0; - (devInfo->DeviceStats).BytesWritten = 0; - (devInfo->DeviceStats).NumberReads = 0; - (devInfo->DeviceStats).NumberWrites = 0; - } - } - - ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); - -__Exit_DsmpClearPerfCounters: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpClearPerfCounters (DsmIds %p): Exiting function with status %x.\n", - DsmIds, - status)); - - return status; -} - - -NTSTATUS -DsmpQuerySupportedDevicesList( - _In_ PDSM_CONTEXT DsmContext, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ) -/*++ - -Routine Description: - - This routine returns the list of devices that are supported by MSDSM. - -Arguements: - - DsmContext - Global DSM context - InBufferSize - Size of the input buffer - OutBufferSize - Size of the output buffer - Buffer - Buffer in which the current Load Balance policy settings - is returned, if the buffer is big enough - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - NTSTATUS status; - ULONG sizeNeeded; - PMSDSM_SUPPORTED_DEVICES_LIST supportedDeviceIds; - PWSTR szIndex; - PWSTR deviceIdIndex; - ULONG numberDeviceIds = 0; - ULONG index = 0; - KIRQL oldIrql; - PWSTR tempBuffer = NULL; - - UNREFERENCED_PARAMETER(InBufferSize); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQuerySupportedDevicesList (DsmContext %p): Entering function.\n", - DsmContext)); - - // - // It is possible that manually changes to the registry weren't yet picked up, - // so query for the list in its current state. Failure to get this list is not - // fatal, so ignore errors. - // -#if DBG - status = DsmpGetDeviceList(DsmContext); - NT_ASSERT(NT_SUCCESS(status)); -#else - DsmpGetDeviceList(DsmContext); -#endif - - // - // Since it is possible that this list may change if a new device arrival - // gets processed at the same time as this query being processed, we need - // to protect it. - // - KeAcquireSpinLock(&DsmContext->SupportedDevicesListLock, &oldIrql); - - tempBuffer = DsmpAllocatePool(NonPagedPoolNx, DsmContext->SupportedDevices.MaximumLength, DSM_TAG_REG_VALUE_RELATED); - - if (tempBuffer) { - - RtlCopyMemory(tempBuffer, DsmContext->SupportedDevices.Buffer, DsmContext->SupportedDevices.Length); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQuerySupportedDevicesList (DsmContext %p): Failed to allocate temporary list.\n", - DsmContext)); - - status = STATUS_INSUFFICIENT_RESOURCES; - KeReleaseSpinLock(&DsmContext->SupportedDevicesListLock, oldIrql); - - goto __Exit_DsmpQuerySupportedDevicesList; - } - - KeReleaseSpinLock(&DsmContext->SupportedDevicesListLock, oldIrql); - - status = STATUS_SUCCESS; - szIndex = tempBuffer; - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(MSDSM_SUPPORTED_DEVICES_LIST, DeviceId)); - - if (szIndex) { - - while (*szIndex) { - - szIndex += wcslen(szIndex) + 1; - numberDeviceIds++; - } - - sizeNeeded += numberDeviceIds * (MSDSM_MAX_DEVICE_ID_SIZE + sizeof(WNULL)); - } - - if (*OutBufferSize < sizeNeeded) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQuerySupportedDevicesList (DsmContext %p): Output buffer too small for QuerySupportedDevicesList.\n", - DsmContext)); - - *OutBufferSize = sizeNeeded; - status = STATUS_BUFFER_TOO_SMALL; - - goto __Exit_DsmpQuerySupportedDevicesList; - } - - // - // Zero out the output buffer first - // - RtlZeroMemory(Buffer, sizeNeeded); - - *OutBufferSize = sizeNeeded; - - supportedDeviceIds = (PMSDSM_SUPPORTED_DEVICES_LIST)Buffer; - supportedDeviceIds->NumberDevices = numberDeviceIds; - - for (index = 0, szIndex = tempBuffer, deviceIdIndex = supportedDeviceIds->DeviceId; - index < numberDeviceIds; - index++, szIndex += wcslen(szIndex) + 1, deviceIdIndex += MSDSM_MAX_DEVICE_ID_LENGTH) { - - *((PUSHORT)deviceIdIndex) = MSDSM_MAX_DEVICE_ID_SIZE; - deviceIdIndex++; - - RtlStringCchCopyW(deviceIdIndex, - MSDSM_MAX_DEVICE_ID_LENGTH - 1, - szIndex); - } - -__Exit_DsmpQuerySupportedDevicesList: - - if (tempBuffer) { - DsmpFreePool(tempBuffer); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQuerySupportedDevicesList (DsmContext %p): Exiting function with status %x.\n", - DsmContext, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryTargetsDefaultPolicy( - _In_ PDSM_CONTEXT DsmContext, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ) -/*++ - -Routine Description: - - This routine is used to build the target list (for which the override default LB policy - was explicitly set), by querying the services key for the subkeys under - "msdsm\Parameters\DsmTargetsLoadBalanceSetting" - -Arguements: - - Context - The DSM Context value. It contains storage for the target hardware ids and their - default policy info. - InBufferSize - Size of the input buffer - OutBufferSize - Size of the output buffer - Buffer - Buffer in which the current targets whose default policy settings is returned, if the buffer is big enough - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - ULONG sizeNeeded; - PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY targetsPolicyInfo = (PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY)Buffer; - PMSDSM_TARGET_DEFAULT_POLICY_INFO targetPolicyInfo; - HANDLE targetsLBSettingKey = NULL; - NTSTATUS status; - PKEY_FULL_INFORMATION keyFullInfo = NULL; - ULONG length = sizeof(KEY_FULL_INFORMATION); - ULONG numSubKeys = 0; - WCHAR vidPid[25] = {0}; - PKEY_BASIC_INFORMATION keyBasicInfo = NULL; - OBJECT_ATTRIBUTES objectAttributes; - HANDLE targetKey = NULL; - ULONG index = 0; - RTL_QUERY_REGISTRY_TABLE queryTable[2]; - DSM_LOAD_BALANCE_TYPE loadBalanceType; - ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - PWCHAR policyInfoIndex; - UNICODE_STRING keyValueName; - PKEY_VALUE_PARTIAL_INFORMATION keyValueInfo = NULL; - - UNREFERENCED_PARAMETER(InBufferSize); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Entering function.\n", - DsmContext)); - - status = DsmpOpenTargetsLoadBalanceSettingKey(KEY_ALL_ACCESS, &targetsLBSettingKey); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to open Targets LB Setting key. Status %x.\n", - DsmContext, - status)); - - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - // - // Query for number of subkeys - // - do { - if (keyFullInfo) { - - DsmpFreePool(keyFullInfo); - } - - keyFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); - - if (!keyFullInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to allocate resources for key full info.\n", - DsmContext)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - status = ZwQueryKey(targetsLBSettingKey, - KeyFullInformation, - keyFullInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to query key. Status %x.\n", - DsmContext, - status)); - - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - // - // Calculate total buffer size required - // - numSubKeys = keyFullInfo->SubKeys; - - sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY, TargetDefaultPolicyInfo)); - sizeNeeded += numSubKeys * sizeof(MSDSM_TARGET_DEFAULT_POLICY_INFO); - - if (*OutBufferSize < sizeNeeded) { - - *OutBufferSize = sizeNeeded; - status = STATUS_BUFFER_TOO_SMALL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Buffer insufficient. Status %x.\n", - DsmContext, - status)); - - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - *OutBufferSize = sizeNeeded; - RtlZeroMemory(Buffer, *OutBufferSize); - - targetsPolicyInfo->NumberDevices = numSubKeys; - targetPolicyInfo = targetsPolicyInfo->TargetDefaultPolicyInfo; - - // - // Now Enumerate all of the subkeys - // - for(index = 0; index < numSubKeys && NT_SUCCESS(status); index++) { - - UNICODE_STRING targetName; - - if (targetKey) { - ZwClose(targetKey); - targetKey = NULL; - } - - length = sizeof(KEY_BASIC_INFORMATION); - - do { - if (keyBasicInfo) { - - DsmpFreePool(keyBasicInfo); - } - - keyBasicInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, - length, - DSM_TAG_REG_KEY_RELATED); - - if (!keyBasicInfo) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to allocate resources for key basic info.\n", - DsmContext)); - - status = STATUS_INSUFFICIENT_RESOURCES; - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - // - // Enumerate the index'th subkey - // - status = ZwEnumerateKey(targetsLBSettingKey, - index, - KeyBasicInformation, - keyBasicInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - // - // Ignore errors - this is a best case effort. - // - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to enumerate sub key's info. Status %x.\n", - DsmContext, - status)); - - status = STATUS_SUCCESS; - continue; - } - - RtlZeroMemory(vidPid, sizeof(vidPid)); - RtlStringCbCopyNW(vidPid, sizeof(vidPid), keyBasicInfo->Name, keyBasicInfo->NameLength); - RtlInitUnicodeString(&targetName, vidPid); - - // - // Open a handle to the the target subkey. - // - InitializeObjectAttributes(&objectAttributes, - &targetName, - (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), - targetsLBSettingKey, - (PSECURITY_DESCRIPTOR) NULL); - - status = ZwOpenKey(&targetKey, - KEY_ALL_ACCESS, - &objectAttributes); - - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to open reg key %ws. Status %x.\n", - DsmContext, - vidPid, - status)); - - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - RtlZeroMemory(queryTable, sizeof(queryTable)); - - queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; - queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; - queryTable[0].EntryContext = &loadBalanceType; - queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; - - status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - targetKey, - queryTable, - targetKey, - NULL); - if (!NT_SUCCESS(status)) { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to query LB Policy for %ws - error %x.\n", - DsmContext, - vidPid, - status)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): LB Policy for %ws is %d.\n", - DsmContext, - vidPid, - loadBalanceType)); - - RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); - - length = sizeof(KEY_VALUE_PARTIAL_INFORMATION); - - do { - DsmpFreePool(keyValueInfo); - keyValueInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); - if (!keyValueInfo) { - - status = STATUS_INSUFFICIENT_RESOURCES; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to allocate resources for keyValueInfo (PP). Status %x.\n", - DsmContext, - status)); - - goto __Exit_DsmpQueryTargetsDefaultPolicy; - } - - status = ZwQueryValueKey(targetKey, - &keyValueName, - KeyValuePartialInformation, - keyValueInfo, - length, - &length); - - } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); - - if (NT_SUCCESS(status)) { - - NT_ASSERT(keyValueInfo->DataLength == sizeof(ULONGLONG)); - - preferredPath = *((ULONGLONG UNALIGNED *)keyValueInfo->Data); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): PreferredPath for %ws is %I64x.\n", - DsmContext, - vidPid, - preferredPath)); - - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to query PreferredPath for %ws. Status %x.\n", - DsmContext, - vidPid, - status)); - } - - // - // Copy over this target's policy info. - // - policyInfoIndex = targetPolicyInfo->HardwareId; - *((PUSHORT)policyInfoIndex) = MSDSM_MAX_DEVICE_ID_SIZE; - policyInfoIndex++; - RtlStringCchCopyW((PWSTR)policyInfoIndex, MSDSM_MAX_DEVICE_ID_LENGTH - 1, vidPid); - targetPolicyInfo->LoadBalancePolicy = loadBalanceType; - targetPolicyInfo->PreferredPath = preferredPath; - - targetPolicyInfo++; - } - } - -__Exit_DsmpQueryTargetsDefaultPolicy: - - if (targetKey) { - ZwClose(targetKey); - } - - if (targetsLBSettingKey) { - ZwClose(targetsLBSettingKey); - } - - if (keyBasicInfo) { - DsmpFreePool(keyBasicInfo); - } - - if (keyValueInfo) { - DsmpFreePool(keyValueInfo); - } - - if (keyFullInfo) { - DsmpFreePool(keyFullInfo); - } - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryTargetsDefaultPolicy (Context %p): Exiting function with status %x.\n", - DsmContext, - status)); - - return status; -} - - -NTSTATUS -DsmpQueryDsmDefaultPolicy( - _In_ PDSM_CONTEXT DsmContext, - _In_ ULONG InBufferSize, - _Inout_ PULONG OutBufferSize, - _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer - ) -/*++ - -Routine Description: - - This routine is used to return the override MSDSM-wide default LB policy - if it was explicitly set, by querying the services key at "msdsm\Parameters" - -Arguements: - - Context - The DSM Context value. It contains storage for the target hardware ids and their - default policy info. - InBufferSize - Size of the input buffer - OutBufferSize - Size of the output buffer - Buffer - Buffer in which the current MSDSM-wide default policy is returned, if the buffer - is big enough - -Return Value: - - STATUS_SUCCESS on success - Appropriate error code on error. - ---*/ -{ - PMSDSM_DEFAULT_LOAD_BALANCE_POLICY dsmPolicyInfo = (PMSDSM_DEFAULT_LOAD_BALANCE_POLICY)Buffer; - NTSTATUS status; - DSM_LOAD_BALANCE_TYPE loadBalanceType; - ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); - - UNREFERENCED_PARAMETER(InBufferSize); - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryDsmDefaultPolicy (Context %p): Entering function.\n", - DsmContext)); - - if (*OutBufferSize < sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY)) { - - *OutBufferSize = sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY); - status = STATUS_BUFFER_TOO_SMALL; - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryDsmDefaultPolicy (Context %p): Buffer insufficient. Status %x.\n", - DsmContext, - status)); - - goto __Exit_DsmpQueryDsmDefaultPolicy; - } - - *OutBufferSize = sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY); - RtlZeroMemory(Buffer, *OutBufferSize); - - status = DsmpQueryDsmLBPolicyFromRegistry(&loadBalanceType, &preferredPath); - - if (NT_SUCCESS(status)) { - - dsmPolicyInfo->LoadBalancePolicy = loadBalanceType; - dsmPolicyInfo->PreferredPath = (ULONGLONG)((ULONG_PTR)preferredPath); - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryDsmDefaultPolicy (Context %p): LB policy = %u, Preferred path = %I64x.\n", - DsmContext, - dsmPolicyInfo->LoadBalancePolicy, - dsmPolicyInfo->PreferredPath)); - } else { - - TracePrint((TRACE_LEVEL_ERROR, - TRACE_FLAG_WMI, - "DsmpQueryDsmDefaultPolicy (Context %p): Query for MSDSM-wide policy, status %x.\n", - DsmContext, - status)); - } - -__Exit_DsmpQueryDsmDefaultPolicy: - - TracePrint((TRACE_LEVEL_VERBOSE, - TRACE_FLAG_WMI, - "DsmpQueryDsmDefaultPolicy (Context %p): Exiting function with status %x.\n", - DsmContext, - status)); - - return status; -} - diff --git a/tests/projects/wdk/wdm/msdsm/xmake.lua b/tests/projects/wdk/wdm/msdsm/xmake.lua deleted file mode 100644 index 3c68aa1b8..000000000 --- a/tests/projects/wdk/wdm/msdsm/xmake.lua +++ /dev/null @@ -1,15 +0,0 @@ -add_rules("mode.debug", "mode.release") - -target("sampledsm") - add_rules("wdk.env.wdm", "wdk.driver") - add_values("wdk.tracewpp.flags", "-func:TracePrint((LEVEL,FLAGS,MSG,...))") - add_files("*.c", {rule = "wdk.tracewpp"}) - add_files("*.rc", "*.inf") - add_files("*.mof|msdsm.mof") - - -- add file msdsm.mof and modify default wdk.mof.header for this file - add_files("msdsm.mof", {values = {wdk_mof_header = "msdsmwmi.h"}}) - - set_pcheader("precomp.h") - add_links("mpio") - diff --git a/tests/projects/wdk/wdm/perfcounters/kcs.c b/tests/projects/wdk/wdm/perfcounters/kcs.c deleted file mode 100644 index 9996addcb..000000000 --- a/tests/projects/wdk/wdm/perfcounters/kcs.c +++ /dev/null @@ -1,407 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - kcs.c - -Abstract: - - This module contains sample code to demonstrate how to provide - counter data from a kernel driver. - -Environment: - - Kernel mode only. - ---*/ - - -#include -#include "kcs.h" -#include "kcsCounters.h" - -#pragma code_seg("PAGE") - -DRIVER_INITIALIZE DriverEntry; -DRIVER_UNLOAD KcsUnload; - -NTSTATUS -KcsAddGeometricInstance ( - _In_ PPCW_BUFFER Buffer, - _In_ PCWSTR Name, - _In_ ULONG MinimalValue, - _In_ ULONG Amplitude - ) - -/*++ - -Routine Description: - - This utility function adds instance to the callback buffer. - -Arguments: - - Buffer - Data will be returned in this buffer. - - Name - Name of instances to be added. - - MinimalValue - Minimum value of the wave. - - Amplitude - Amplitude of the wave. - -Return Value: - - NTSTATUS indicating if the function succeeded. - ---*/ - -{ - ULONG Index; - LARGE_INTEGER Timestamp; - UNICODE_STRING UnicodeName; - GEOMETRIC_WAVE_VALUES Values; - - PAGED_CODE(); - - KeQuerySystemTime(&Timestamp); - - Index = (Timestamp.QuadPart / 10000000) % 10; - - Values.Triangle = MinimalValue + Amplitude * abs(5 - Index) / 5; - Values.Square = MinimalValue + Amplitude * (Index < 5); - - RtlInitUnicodeString(&UnicodeName, Name); - - return KcsAddGeometricWave(Buffer, &UnicodeName, 0, &Values); -} - -NTSTATUS NTAPI -KcsGeometricWaveCallback ( - _In_ PCW_CALLBACK_TYPE Type, - _In_ PPCW_CALLBACK_INFORMATION Info, - _In_opt_ PVOID Context - ) - -/*++ - -Routine Description: - - This function returns the list of counter instances and counter data. - -Arguments: - - Type - Request type. - - Info - Buffer for returned data. - - Context - Not used. - -Return Value: - - NTSTATUS indicating if the function succeeded. - ---*/ - -{ - NTSTATUS Status; - UNICODE_STRING UnicodeName; - - UNREFERENCED_PARAMETER(Context); - - PAGED_CODE(); - - switch (Type) { - case PcwCallbackEnumerateInstances: - - // - // Instances are being enumerated, so we add them without values. - // - - RtlInitUnicodeString(&UnicodeName, L"Small Wave"); - Status = KcsAddGeometricWave(Info->EnumerateInstances.Buffer, - &UnicodeName, - 0, - NULL); - if (!NT_SUCCESS(Status)) { - return Status; - } - - RtlInitUnicodeString(&UnicodeName, L"Medium Wave"); - Status = KcsAddGeometricWave(Info->EnumerateInstances.Buffer, - &UnicodeName, - 0, - NULL); - if (!NT_SUCCESS(Status)) { - return Status; - } - - RtlInitUnicodeString(&UnicodeName, L"Large Wave"); - Status = KcsAddGeometricWave(Info->EnumerateInstances.Buffer, - &UnicodeName, - 0, - NULL); - if (!NT_SUCCESS(Status)) { - return Status; - } - - break; - - case PcwCallbackCollectData: - - // - // Add values for 3 instances of Geometric Wave Counter Set. - // - - Status = KcsAddGeometricInstance(Info->CollectData.Buffer, - L"Small Wave", - 40, - 20); - if (!NT_SUCCESS(Status)) { - return Status; - } - - Status = KcsAddGeometricInstance(Info->CollectData.Buffer, - L"Medium Wave", - 30, - 40); - if (!NT_SUCCESS(Status)) { - return Status; - } - - Status = KcsAddGeometricInstance(Info->CollectData.Buffer, - L"Large Wave", - 20, - 60); - if (!NT_SUCCESS(Status)) { - return Status; - } - - break; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -KcsAddTrignometricInstance ( - _In_ PPCW_BUFFER Buffer, - _In_ PCWSTR Name, - _In_ ULONG MinimalValue, - _In_ ULONG Amplitude - ) - -/*++ - -Routine Description: - - This utility function adds instance to the callback buffer. - -Arguments: - - Buffer - Data will be returned in this buffer. - - Name - Name of instances to be added. - - MinimalValue - Minimum value of the wave. - - Amplitude - Amplitude of the wave. - -Return Value: - - NTSTATUS indicating if the function succeeded. - ---*/ - -{ - double Angle; - KFLOATING_SAVE FloatSave; - NTSTATUS Status; - LARGE_INTEGER Timestamp; - UNICODE_STRING UnicodeName; - TRIGNOMETRIC_WAVE_VALUES Values; - - PAGED_CODE(); - - Status = KeSaveFloatingPointState(&FloatSave); - if (!NT_SUCCESS(Status)) { - return Status; - } - - KeQuerySystemTime(&Timestamp); - - Angle = (double)(Timestamp.QuadPart / 400000) * (22/7) / 180; - - Values.Constant = MinimalValue; - Values.Cosine = (ULONG)(MinimalValue + Amplitude * cos(Angle)); - Values.Sine = (ULONG)(MinimalValue + Amplitude * sin(Angle)); - - KeRestoreFloatingPointState(&FloatSave); - - // - // Add instance name & values to the caller's buffer. - // - - RtlInitUnicodeString(&UnicodeName, Name); - - return KcsAddTrignometricWave(Buffer, &UnicodeName, 0, &Values); -} - -NTSTATUS NTAPI -KcsTrignometricWaveCallback ( - _In_ PCW_CALLBACK_TYPE Type, - _In_ PPCW_CALLBACK_INFORMATION Info, - _In_opt_ PVOID Context - ) - -/*++ - -Routine Description: - - This function returns the list of counter instances and counter data. - -Arguments: - - Type - Request type. - - Info - Buffer for returned data. - - Context - Not used. - -Return Value: - - NTSTATUS indicating if the function succeeded. - ---*/ - -{ - NTSTATUS Status; - UNICODE_STRING UnicodeName; - - UNREFERENCED_PARAMETER(Context); - - PAGED_CODE(); - - switch (Type) { - case PcwCallbackEnumerateInstances: - RtlInitUnicodeString(&UnicodeName, L"default"); - Status = KcsAddTrignometricWave(Info->EnumerateInstances.Buffer, - &UnicodeName, - 0, - NULL); - if (!NT_SUCCESS(Status)) { - return Status; - } - - break; - - case PcwCallbackCollectData: - - // - // Add values for Single Instance of Trignometirc Wave Counter Set. - // - - return KcsAddTrignometricInstance(Info->CollectData.Buffer, - L"default", - 50, - 30); - } - - return STATUS_SUCCESS; -} - -VOID -KcsUnload ( - _In_ PDRIVER_OBJECT DriverObject - ) - -/*++ - -Routine Description: - - This function unregisters countersets - -Arguments: - - DriverObject - Not used. - -Return Value: - - None. - ---*/ - -{ - UNREFERENCED_PARAMETER(DriverObject); - - PAGED_CODE(); - - // - // Unregister Countersets. - // - - KcsUnregisterGeometricWave(); - KcsUnregisterTrignometricWave(); -} - -NTSTATUS -DriverEntry ( - _In_ PDRIVER_OBJECT DriverObject, - _In_ PUNICODE_STRING RegistryPath - ) - -/*++ - -Routine Description: - - This function registers countersets on initial loading of the driver. - -Arguments: - - DriverObject - Supplies the driver object of the driver being loaded. - - RegistryPath - Not used. - -Return Value: - - NTSTATUS indicating if driver was properly loaded. - ---*/ - -{ - NTSTATUS Status; - - UNREFERENCED_PARAMETER(RegistryPath); - - PAGED_CODE(); - - // - // Register Countersets. - // - - Status = KcsRegisterGeometricWave(KcsGeometricWaveCallback, NULL); - if (!NT_SUCCESS(Status)) { - return Status; - } - - Status = KcsRegisterTrignometricWave(KcsTrignometricWaveCallback, NULL); - if (!NT_SUCCESS(Status)) { - KcsUnregisterTrignometricWave(); - return Status; - } - - // - // Success path - set up unload routine and return success. - // - - DriverObject->DriverUnload = KcsUnload; - - return STATUS_SUCCESS; -} - diff --git a/tests/projects/wdk/wdm/perfcounters/kcs.h b/tests/projects/wdk/wdm/perfcounters/kcs.h deleted file mode 100644 index f575b816d..000000000 --- a/tests/projects/wdk/wdm/perfcounters/kcs.h +++ /dev/null @@ -1,34 +0,0 @@ -/*++ - -Copyright (c) Microsoft Corporation. All rights reserved. - - THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY - KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR - PURPOSE. - -Module Name: - - kcs.h - -Abstract: - - This module contains sample code to demonstrate how to provide - counter data from a kernel driver. - -Environment: - - Kernel mode only. - ---*/ - -typedef struct _GEOMETRIC_WAVE_VALUES { - ULONG Square; - ULONG Triangle; -} GEOMETRIC_WAVE_VALUES, *PGEOMETRIC_WAVE_VALUES; - -typedef struct _TRIGNOMETRIC_WAVE_VALUES { - ULONG Constant; - ULONG Cosine; - ULONG Sine; -} TRIGNOMETRIC_WAVE_VALUES, *PTRIGNOMETRIC_WAVE_VALUES; \ No newline at end of file diff --git a/tests/projects/wdk/wdm/perfcounters/kcs.man b/tests/projects/wdk/wdm/perfcounters/kcs.man deleted file mode 100644 index a5a16ffbd..000000000 --- a/tests/projects/wdk/wdm/perfcounters/kcs.man +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tests/projects/wdk/wdm/perfcounters/kcs.rc b/tests/projects/wdk/wdm/perfcounters/kcs.rc deleted file mode 100644 index 7ebb6b97b..000000000 --- a/tests/projects/wdk/wdm/perfcounters/kcs.rc +++ /dev/null @@ -1 +0,0 @@ -#include "kcsCounters.rc" diff --git a/tests/projects/wdk/wdm/perfcounters/xmake.lua b/tests/projects/wdk/wdm/perfcounters/xmake.lua deleted file mode 100644 index 83e4e4d9b..000000000 --- a/tests/projects/wdk/wdm/perfcounters/xmake.lua +++ /dev/null @@ -1,10 +0,0 @@ -add_rules("mode.debug", "mode.release") - -target("kcs") - add_rules("wdk.env.wdm", "wdk.driver") - add_values("wdk.man.prefix", "Kcs") - add_values("wdk.man.resource", "kcsCounters.rc") - add_values("wdk.man.header", "kcsCounters.h") - add_values("wdk.man.counter_header", "kcsCounters_counters.h") - add_files("*.c", "*.rc", "*.man") - diff --git a/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.c b/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.c new file mode 100644 index 000000000..13f811f35 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.c @@ -0,0 +1,1309 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + nonpnp.c + +Abstract: + + Purpose of this driver is to demonstrate how to write a legacy (NON WDM) + driver using framework, show how to handle 4 different ioctls - + METHOD_NEITHER - in particular and also show how to read & write to file + from KernelMode using Zw functions. + + For a non-framework version of sample on how to handle IOCTLs in driver, + study src\general\IOCTL in the DDK. + +Environment: + + Kernel mode only. + +--*/ + +#include "nonpnp.h" + +// +// The trace message header file must be included in a source file +// before any WPP macro calls and after defining a WPP_CONTROL_GUIDS +// macro. During the compilation, WPP scans the source files for +// TraceEvents() calls and builds a .tmh file which stores a unique +// data GUID for each message, the text resource string for each message, +// and the data types of the variables passed in for each message. +// This file is automatically generated and used during post-processing. +// +#include "nonpnp.tmh" + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text( INIT, DriverEntry ) +#pragma alloc_text( PAGE, NonPnpDeviceAdd) +#pragma alloc_text( PAGE, NonPnpEvtDriverContextCleanup) +#pragma alloc_text( PAGE, NonPnpEvtDriverUnload) +#pragma alloc_text( PAGE, NonPnpEvtDeviceIoInCallerContext) +#pragma alloc_text( PAGE, NonPnpEvtDeviceFileCreate) +#pragma alloc_text( PAGE, NonPnpEvtFileClose) +#pragma alloc_text( PAGE, FileEvtIoRead) +#pragma alloc_text( PAGE, FileEvtIoWrite) +#pragma alloc_text( PAGE, FileEvtIoDeviceControl) +#endif // ALLOC_PRAGMA + + +NTSTATUS +DriverEntry( + IN OUT PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + This routine is called by the Operating System to initialize the driver. + + It creates the device object, fills in the dispatch entry points and + completes the initialization. + +Arguments: + DriverObject - a pointer to the object that represents this device + driver. + + RegistryPath - a pointer to our Services key in the registry. + +Return Value: + STATUS_SUCCESS if initialized; an error otherwise. + +--*/ +{ + NTSTATUS status; + WDF_DRIVER_CONFIG config; + WDFDRIVER hDriver; + PWDFDEVICE_INIT pInit = NULL; + WDF_OBJECT_ATTRIBUTES attributes; + + KdPrint(("Driver Frameworks NONPNP Legacy Driver Example\n")); + + + WDF_DRIVER_CONFIG_INIT( + &config, + WDF_NO_EVENT_CALLBACK // This is a non-pnp driver. + ); + + // + // Tell the framework that this is non-pnp driver so that it doesn't + // set the default AddDevice routine. + // + config.DriverInitFlags |= WdfDriverInitNonPnpDriver; + + // + // NonPnp driver must explicitly register an unload routine for + // the driver to be unloaded. + // + config.EvtDriverUnload = NonPnpEvtDriverUnload; + + // + // Register a cleanup callback so that we can call WPP_CLEANUP when + // the framework driver object is deleted during driver unload. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = NonPnpEvtDriverContextCleanup; + + // + // Create a framework driver object to represent our driver. + // + status = WdfDriverCreate(DriverObject, + RegistryPath, + &attributes, + &config, + &hDriver); + if (!NT_SUCCESS(status)) { + KdPrint (("NonPnp: WdfDriverCreate failed with status 0x%x\n", status)); + return status; + } + + // + // Since we are calling WPP_CLEANUP in the DriverContextCleanup + // callback we should initialize WPP Tracing after WDFDRIVER + // object is created to ensure that we cleanup WPP properly + // if we return failure status from DriverEntry. This + // eliminates the need to call WPP_CLEANUP in every path + // of DriverEntry. + // + WPP_INIT_TRACING( DriverObject, RegistryPath ); + + // + // On Win2K system, you will experience some delay in getting trace events + // due to the way the ETW is activated to accept trace messages. + // + KdPrint(("NonPnp: DriverEntry: tracing enabled\n")); + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, + "Driver Frameworks NONPNP Legacy Driver Example"); + + // + // + // In order to create a control device, we first need to allocate a + // WDFDEVICE_INIT structure and set all properties. + // + pInit = WdfControlDeviceInitAllocate( + hDriver, + &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R + ); + + if (pInit == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + return status; + } + + // + // Call NonPnpDeviceAdd to create a deviceobject to represent our + // software device. + // + status = NonPnpDeviceAdd(hDriver, pInit); + + return status; +} + +NTSTATUS +NonPnpDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ) +/*++ + +Routine Description: + + Called by the DriverEntry to create a control-device. This call is + responsible for freeing the memory for DeviceInit. + +Arguments: + + DriverObject - a pointer to the object that represents this device + driver. + + DeviceInit - Pointer to a driver-allocated WDFDEVICE_INIT structure. + +Return Value: + + STATUS_SUCCESS if initialized; an error otherwise. + +--*/ +{ + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_IO_QUEUE_CONFIG ioQueueConfig; + WDF_FILEOBJECT_CONFIG fileConfig; + WDFQUEUE queue; + WDFDEVICE controlDevice; + DECLARE_CONST_UNICODE_STRING(ntDeviceName, NTDEVICE_NAME_STRING) ; + DECLARE_CONST_UNICODE_STRING(symbolicLinkName, SYMBOLIC_NAME_STRING) ; + + UNREFERENCED_PARAMETER( Driver ); + + PAGED_CODE(); + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, + "NonPnpDeviceAdd DeviceInit %p\n", DeviceInit); + // + // Set exclusive to TRUE so that no more than one app can talk to the + // control device at any time. + // + WdfDeviceInitSetExclusive(DeviceInit, TRUE); + + WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); + + + status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); + + if (!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceInitAssignName failed %!STATUS!", status); + goto End; + } + + WdfControlDeviceInitSetShutdownNotification(DeviceInit, + NonPnpShutdown, + WdfDeviceShutdown); + + // + // Initialize WDF_FILEOBJECT_CONFIG_INIT struct to tell the + // framework whether you are interested in handling Create, Close and + // Cleanup requests that gets generated when an application or another + // kernel component opens an handle to the device. If you don't register + // the framework default behaviour would be to complete these requests + // with STATUS_SUCCESS. A driver might be interested in registering these + // events if it wants to do security validation and also wants to maintain + // per handle (fileobject) context. + // + + WDF_FILEOBJECT_CONFIG_INIT( + &fileConfig, + NonPnpEvtDeviceFileCreate, + NonPnpEvtFileClose, + WDF_NO_EVENT_CALLBACK // not interested in Cleanup + ); + + WdfDeviceInitSetFileObjectConfig(DeviceInit, + &fileConfig, + WDF_NO_OBJECT_ATTRIBUTES); + + // + // In order to support METHOD_NEITHER Device controls, or + // NEITHER device I/O type, we need to register for the + // EvtDeviceIoInProcessContext callback so that we can handle the request + // in the calling threads context. + // + WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, + NonPnpEvtDeviceIoInCallerContext); + + // + // Specify the size of device context + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, + CONTROL_DEVICE_EXTENSION); + + status = WdfDeviceCreate(&DeviceInit, + &attributes, + &controlDevice); + if (!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreate failed %!STATUS!", status); + goto End; + } + + // + // Create a symbolic link for the control object so that usermode can open + // the device. + // + + + status = WdfDeviceCreateSymbolicLink(controlDevice, + &symbolicLinkName); + + if (!NT_SUCCESS(status)) { + // + // Control device will be deleted automatically by the framework. + // + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateSymbolicLink failed %!STATUS!", status); + goto End; + } + + // + // Configure a default queue so that requests that are not + // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto + // other queues get dispatched here. + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, + WdfIoQueueDispatchSequential); + + ioQueueConfig.EvtIoRead = FileEvtIoRead; + ioQueueConfig.EvtIoWrite = FileEvtIoWrite; + ioQueueConfig.EvtIoDeviceControl = FileEvtIoDeviceControl; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + // + // Since we are using Zw function set execution level to passive so that + // framework ensures that our Io callbacks called at only passive-level + // even if the request came in at DISPATCH_LEVEL from another driver. + // + //attributes.ExecutionLevel = WdfExecutionLevelPassive; + + // + // By default, Static Driver Verifier (SDV) displays a warning if it + // doesn't find the EvtIoStop callback on a power-managed queue. + // The 'assume' below causes SDV to suppress this warning. If the driver + // has not explicitly set PowerManaged to WdfFalse, the framework creates + // power-managed queues when the device is not a filter driver. Normally + // the EvtIoStop is required for power-managed queues, but for this driver + // it is not needed b/c the driver doesn't hold on to the requests or + // forward them to other drivers. This driver completes the requests + // directly in the queue's handlers. If the EvtIoStop callback is not + // implemented, the framework waits for all driver-owned requests to be + // done before moving in the Dx/sleep states or before removing the + // device, which is the correct behavior for this type of driver. + // If the requests were taking an indeterminate amount of time to complete, + // or if the driver forwarded the requests to a lower driver/another stack, + // the queue should have an EvtIoStop/EvtIoResume. + // + __analysis_assume(ioQueueConfig.EvtIoStop != 0); + status = WdfIoQueueCreate(controlDevice, + &ioQueueConfig, + &attributes, + &queue // pointer to default queue + ); + __analysis_assume(ioQueueConfig.EvtIoStop == 0); + if (!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed %!STATUS!", status); + goto End; + } + + // + // Control devices must notify WDF when they are done initializing. I/O is + // rejected until this call is made. + // + WdfControlFinishInitializing(controlDevice); + +End: + // + // If the device is created successfully, framework would clear the + // DeviceInit value. Otherwise device create must have failed so we + // should free the memory ourself. + // + if (DeviceInit != NULL) { + WdfDeviceInitFree(DeviceInit); + } + + return status; + +} + +VOID +NonPnpEvtDriverContextCleanup( + IN WDFOBJECT Driver + ) +/*++ +Routine Description: + + Called when the driver object is deleted during driver unload. + You can free all the resources created in DriverEntry that are + not automatically freed by the framework. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + +Return Value: + + NTSTATUS + +--*/ +{ + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, + "Entered NonPnpEvtDriverContextCleanup\n"); + + PAGED_CODE(); + + // + // No need to free the controldevice object explicitly because it will + // be deleted when the Driver object is deleted due to the default parent + // child relationship between Driver and ControlDevice. + // + WPP_CLEANUP( WdfDriverWdmGetDriverObject( (WDFDRIVER)Driver ) ); + +} + + + +VOID +NonPnpEvtDeviceFileCreate ( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + IN WDFFILEOBJECT FileObject + ) +/*++ + +Routine Description: + + The framework calls a driver's EvtDeviceFileCreate callback + when it receives an IRP_MJ_CREATE request. + The system sends this request when a user application opens the + device to perform an I/O operation, such as reading or writing a file. + This callback is called synchronously, in the context of the thread + that created the IRP_MJ_CREATE request. + +Arguments: + + Device - Handle to a framework device object. + FileObject - Pointer to fileobject that represents the open handle. + CreateParams - Parameters of IO_STACK_LOCATION for create + +Return Value: + + NT status code + +--*/ +{ + PUNICODE_STRING fileName; + UNICODE_STRING absFileName, directory; + OBJECT_ATTRIBUTES fileAttributes; + IO_STATUS_BLOCK ioStatus; + PCONTROL_DEVICE_EXTENSION devExt; + NTSTATUS status; + USHORT length = 0; + + + UNREFERENCED_PARAMETER( FileObject ); + + PAGED_CODE (); + + devExt = ControlGetData(Device); + + // + // Assume the directory is a temp directory under %windir% + // + RtlInitUnicodeString(&directory, L"\\SystemRoot\\temp"); + + // + // Parsed filename has "\" in the begining. The object manager strips + // of all "\", except one, after the device name. + // + fileName = WdfFileObjectGetFileName(FileObject); + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpEvtDeviceFileCreate %wZ%wZ", + &directory, fileName); + + // + // Find the total length of the directory + filename + // + length = directory.Length + fileName->Length; + + absFileName.Buffer = ExAllocatePoolWithTag(PagedPool, length, POOL_TAG); + if(absFileName.Buffer == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed"); + goto End; + } + absFileName.Length = 0; + absFileName.MaximumLength = length; + + status = RtlAppendUnicodeStringToString(&absFileName, &directory); + if (!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, + "RtlAppendUnicodeStringToString failed with status %!STATUS!", + status); + goto End; + } + + status = RtlAppendUnicodeStringToString(&absFileName, fileName); + if (!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, + "RtlAppendUnicodeStringToString failed with status %!STATUS!", + status); + goto End; + } + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "Absolute Filename %wZ", &absFileName); + + InitializeObjectAttributes( &fileAttributes, + &absFileName, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, // RootDirectory + NULL // SecurityDescriptor + ); + + status = ZwCreateFile ( + &devExt->FileHandle, + SYNCHRONIZE | GENERIC_WRITE | GENERIC_READ, + &fileAttributes, + &ioStatus, + NULL,// alloc size = none + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OPEN_IF, + FILE_SYNCHRONOUS_IO_NONALERT |FILE_NON_DIRECTORY_FILE, + NULL,// eabuffer + 0// ealength + ); + + if (!NT_SUCCESS(status)) { + + TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, + "ZwCreateFile failed with status %!STATUS!", status); + devExt->FileHandle = NULL; + } + +End: + if(absFileName.Buffer != NULL) { + ExFreePool(absFileName.Buffer); + } + + WdfRequestComplete(Request, status); + + return; +} + + +VOID +NonPnpEvtFileClose ( + IN WDFFILEOBJECT FileObject + ) + +/*++ + +Routine Description: + + EvtFileClose is called when all the handles represented by the FileObject + is closed and all the references to FileObject is removed. This callback + may get called in an arbitrary thread context instead of the thread that + called CloseHandle. If you want to delete any per FileObject context that + must be done in the context of the user thread that made the Create call, + you should do that in the EvtDeviceCleanp callback. + +Arguments: + + FileObject - Pointer to fileobject that represents the open handle. + +Return Value: + + VOID + +--*/ +{ + PCONTROL_DEVICE_EXTENSION devExt; + + PAGED_CODE (); + + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpEvtFileClose\n"); + + devExt = ControlGetData(WdfFileObjectGetDevice(FileObject)); + + if(devExt->FileHandle) { + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, + "Closing File Handle %p", devExt->FileHandle); + ZwClose(devExt->FileHandle); + } + + return; +} + + +VOID +FileEvtIoRead( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t Length + ) +/*++ + +Routine Description: + + This event is called when the framework receives IRP_MJ_READ requests. + We will just read the file. + +Arguments: + + Queue - Handle to the framework queue object that is associated with the + I/O request. + Request - Handle to a framework request object. + + Length - number of bytes to be read. + Queue is by default configured to fail zero length read & write requests. + +Return Value: + + None. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PVOID outBuf; + IO_STATUS_BLOCK ioStatus; + PCONTROL_DEVICE_EXTENSION devExt; + FILE_POSITION_INFORMATION position; + ULONG_PTR bytesRead = 0; + size_t bufLength; + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_RW, "FileEvtIoRead: Request: 0x%p, Queue: 0x%p\n", + Request, Queue); + + PAGED_CODE (); + + // + // Get the request buffer. Since the device is set to do buffered + // I/O, this function will retrieve Irp->AssociatedIrp.SystemBuffer. + // + status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufLength); + if(!NT_SUCCESS(status)) { + WdfRequestComplete(Request, status); + return; + + } + + devExt = ControlGetData(WdfIoQueueGetDevice(Queue)); + + if(devExt->FileHandle) { + + // + // Set the file position to the beginning of the file. + // + position.CurrentByteOffset.QuadPart = 0; + status = ZwSetInformationFile(devExt->FileHandle, + &ioStatus, + &position, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (NT_SUCCESS(status)) { + + status = ZwReadFile (devExt->FileHandle, + NULL,// Event, + NULL,// PIO_APC_ROUTINE ApcRoutine + NULL,// PVOID ApcContext + &ioStatus, + outBuf, + (ULONG)Length, + 0, // ByteOffset + NULL // Key + ); + + if (!NT_SUCCESS(status)) { + + TraceEvents(TRACE_LEVEL_ERROR, DBG_RW, + "ZwReadFile failed with status 0x%x", + status); + } + + status = ioStatus.Status; + bytesRead = ioStatus.Information; + } + } + + WdfRequestCompleteWithInformation(Request, status, bytesRead); + +} + + + +VOID +FileEvtIoWrite( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t Length + ) +/*++ + +Routine Description: + + This event is called when the framework receives IRP_MJ_WRITE requests. + +Arguments: + + Queue - Handle to the framework queue object that is associated with the + I/O request. + Request - Handle to a framework request object. + + Length - number of bytes to be written. + Queue is by default configured to fail zero length read & write requests. + + +Return Value: + + None +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PVOID inBuf; + IO_STATUS_BLOCK ioStatus; + PCONTROL_DEVICE_EXTENSION devExt; + FILE_POSITION_INFORMATION position; + ULONG_PTR bytesWritten = 0; + size_t bufLength; + + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_RW, "FileEvtIoWrite: Request: 0x%p, Queue: 0x%p\n", + Request, Queue); + PAGED_CODE (); + + // + // Get the request buffer. Since the device is set to do buffered + // I/O, this function will retrieve Irp->AssociatedIrp.SystemBuffer. + // + status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufLength); + if(!NT_SUCCESS(status)) { + WdfRequestComplete(Request, status); + return; + + } + + devExt = ControlGetData(WdfIoQueueGetDevice(Queue)); + + if(devExt->FileHandle) { + + // + // Set the file position to the beginning of the file. + // + position.CurrentByteOffset.QuadPart = 0; + + status = ZwSetInformationFile(devExt->FileHandle, + &ioStatus, + &position, + sizeof(FILE_POSITION_INFORMATION), + FilePositionInformation); + if (NT_SUCCESS(status)) + { + + status = ZwWriteFile(devExt->FileHandle, + NULL,// Event, + NULL,// PIO_APC_ROUTINE ApcRoutine + NULL,// PVOID ApcContext + &ioStatus, + inBuf, + (ULONG)Length, + 0, // ByteOffset + NULL // Key + ); + if (!NT_SUCCESS(status)) + { + TraceEvents(TRACE_LEVEL_ERROR, DBG_RW, + "ZwWriteFile failed with status 0x%x", + status); + } + + status = ioStatus.Status; + bytesWritten = ioStatus.Information; + } + } + + WdfRequestCompleteWithInformation(Request, status, bytesWritten); + +} + +VOID +FileEvtIoDeviceControl( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) +/*++ +Routine Description: + + This event is called when the framework receives IRP_MJ_DEVICE_CONTROL + requests from the system. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + Request - Handle to a framework request object. + + OutputBufferLength - length of the request's output buffer, + if an output buffer is available. + InputBufferLength - length of the request's input buffer, + if an input buffer is available. + + IoControlCode - the driver-defined or system-defined I/O control code + (IOCTL) that is associated with the request. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS;// Assume success + PCHAR inBuf = NULL, outBuf = NULL; // pointer to Input and output buffer + PCHAR data = "this String is from Device Driver !!!"; + ULONG datalen = (ULONG) strlen(data)+1;//Length of data including null + PCHAR buffer = NULL; + PREQUEST_CONTEXT reqContext = NULL; + size_t bufSize; + + UNREFERENCED_PARAMETER( Queue ); + + PAGED_CODE(); + + if(!OutputBufferLength || !InputBufferLength) + { + WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); + return; + } + + // + // Determine which I/O control code was specified. + // + + switch (IoControlCode) + { + case IOCTL_NONPNP_METHOD_BUFFERED: + + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_BUFFERED\n"); + + // + // For bufffered ioctls WdfRequestRetrieveInputBuffer & + // WdfRequestRetrieveOutputBuffer return the same buffer + // pointer (Irp->AssociatedIrp.SystemBuffer), so read the + // content of the buffer before writing to it. + // + status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); + if(!NT_SUCCESS(status)) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + ASSERT(bufSize == InputBufferLength); + + // + // Read the input buffer content. + // We are using the following function to print characters instead + // TraceEvents with %s format because the string we get may or + // may not be null terminated. The buffer may contain non-printable + // characters also. + // + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", + log_xstr(inBuf, (USHORT)InputBufferLength))); + PrintChars(inBuf, InputBufferLength ); + + + status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize); + if(!NT_SUCCESS(status)) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + ASSERT(bufSize == OutputBufferLength); + + // + // Writing to the buffer over-writes the input buffer content + // + + RtlCopyMemory(outBuf, data, OutputBufferLength); + + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", + log_xstr(outBuf, (USHORT)datalen))); + PrintChars(outBuf, datalen ); + + // + // Assign the length of the data copied to IoStatus.Information + // of the request and complete the request. + // + WdfRequestSetInformation(Request, + OutputBufferLength < datalen? OutputBufferLength:datalen); + + // + // When the request is completed the content of the SystemBuffer + // is copied to the User output buffer and the SystemBuffer is + // is freed. + // + + break; + + + case IOCTL_NONPNP_METHOD_IN_DIRECT: + + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_IN_DIRECT\n"); + + // + // Get the Input buffer. WdfRequestRetrieveInputBuffer returns + // Irp->AssociatedIrp.SystemBuffer. + // + status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); + if(!NT_SUCCESS(status)) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + ASSERT(bufSize == InputBufferLength); + + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", + log_xstr(inBuf, (USHORT)InputBufferLength))); + PrintChars(inBuf, InputBufferLength); + + // + // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe + // on the Irp->MdlAddress and returns the system address. + // Oddity: For this method, this buffer is intended for transfering data + // from the application to the driver. + // + + status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize); + if(!NT_SUCCESS(status)) { + break; + } + + ASSERT(bufSize == OutputBufferLength); + + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User in OutputBuffer: %!HEXDUMP!\n", + log_xstr(buffer, (USHORT)OutputBufferLength))); + PrintChars(buffer, OutputBufferLength); + + // + // Return total bytes read from the output buffer. + // Note OutputBufferLength = MmGetMdlByteCount(Irp->MdlAddress) + // + + WdfRequestSetInformation(Request, OutputBufferLength); + + // + // NOTE: Changes made to the SystemBuffer are not copied + // to the user input buffer by the I/O manager + // + + break; + + case IOCTL_NONPNP_METHOD_OUT_DIRECT: + + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_OUT_DIRECT\n"); + + // + // Get the Input buffer. WdfRequestRetrieveInputBuffer returns + // Irp->AssociatedIrp.SystemBuffer. + // + status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize); + if(!NT_SUCCESS(status)) { + status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + ASSERT(bufSize == InputBufferLength); + + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", + log_xstr(inBuf, (USHORT)InputBufferLength))); + PrintChars(inBuf, InputBufferLength); + + // + // Get the output buffer. Framework calls MmGetSystemAddressForMdlSafe + // on the Irp->MdlAddress and returns the system address. + // For this method, this buffer is intended for transfering data from the + // driver to the application. + // + status = WdfRequestRetrieveOutputBuffer(Request, 0, &buffer, &bufSize); + if(!NT_SUCCESS(status)) { + break; + } + + ASSERT(bufSize == OutputBufferLength); + + // + // Write data to be sent to the user in this buffer + // + RtlCopyMemory(buffer, data, OutputBufferLength); + + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", + log_xstr(buffer, (USHORT)datalen))); + PrintChars(buffer, datalen); + + WdfRequestSetInformation(Request, + OutputBufferLength < datalen? OutputBufferLength: datalen); + + // + // NOTE: Changes made to the SystemBuffer are not copied + // to the user input buffer by the I/O manager + // + + break; + + case IOCTL_NONPNP_METHOD_NEITHER: + { + size_t inBufLength, outBufLength; + + // + // The NonPnpEvtDeviceIoInCallerContext has already probe and locked the + // pages and mapped the user buffer into system address space and + // stored memory buffer pointers in the request context. We can get the + // buffer pointer by calling WdfMemoryGetBuffer. + // + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Called IOCTL_NONPNP_METHOD_NEITHER\n"); + + reqContext = GetRequestContext(Request); + + inBuf = WdfMemoryGetBuffer(reqContext->InputMemoryBuffer, &inBufLength); + outBuf = WdfMemoryGetBuffer(reqContext->OutputMemoryBuffer, &outBufLength); + + if(inBuf == NULL || outBuf == NULL) { + status = STATUS_INVALID_PARAMETER; + } + + ASSERT(inBufLength == InputBufferLength); + ASSERT(outBufLength == OutputBufferLength); + + // + // Now you can safely read the data from the buffer in any arbitrary + // context. + // + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data from User : %!HEXDUMP!\n", + log_xstr(inBuf, (USHORT)inBufLength))); + PrintChars(inBuf, inBufLength); + + // + // Write to the buffer in any arbitrary context. + // + RtlCopyMemory(outBuf, data, outBufLength); + + Hexdump((TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Data to User : %!HEXDUMP!\n", + log_xstr(outBuf, (USHORT)datalen))); + PrintChars(outBuf, datalen); + + // + // Assign the length of the data copied to IoStatus.Information + // of the Irp and complete the Irp. + // + WdfRequestSetInformation(Request, + outBufLength < datalen? outBufLength:datalen); + + break; + } + default: + + // + // The specified I/O control code is unrecognized by this driver. + // + status = STATUS_INVALID_DEVICE_REQUEST; + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "ERROR: unrecognized IOCTL %x\n", IoControlCode); + break; + } + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Completing Request %p with status %X", + Request, status ); + + WdfRequestComplete( Request, status); + +} + +VOID +NonPnpEvtDeviceIoInCallerContext( + IN WDFDEVICE Device, + IN WDFREQUEST Request + ) +/*++ +Routine Description: + + This I/O in-process callback is called in the calling threads context/address + space before the request is subjected to any framework locking or queueing + scheme based on the device pnp/power or locking attributes set by the + driver. The process context of the calling app is guaranteed as long as + this driver is a top-level driver and no other filter driver is attached + to it. + + This callback is only required if you are handling method-neither IOCTLs, + or want to process requests in the context of the calling process. + + Driver developers should avoid defining neither IOCTLs and access user + buffers, and use much safer I/O tranfer methods such as buffered I/O + or direct I/O. + +Arguments: + + Device - Handle to a framework device object. + + Request - Handle to a framework request object. Framework calls + PreProcess callback only for Read/Write/ioctls and internal + ioctl requests. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PREQUEST_CONTEXT reqContext = NULL; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_REQUEST_PARAMETERS params; + size_t inBufLen, outBufLen; + PVOID inBuf, outBuf; + + PAGED_CODE(); + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + + WdfRequestGetParameters(Request, ¶ms ); + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Entered NonPnpEvtDeviceIoInCallerContext %p \n", + Request); + + // + // Check to see whether we have recevied a METHOD_NEITHER IOCTL. if not + // just send the request back to framework because we aren't doing + // any pre-processing in the context of the calling thread process. + // + if(!(params.Type == WdfRequestTypeDeviceControl && + params.Parameters.DeviceIoControl.IoControlCode == + IOCTL_NONPNP_METHOD_NEITHER)) { + // + // Forward it for processing by the I/O package + // + status = WdfDeviceEnqueueRequest(Device, Request); + if( !NT_SUCCESS(status) ) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error forwarding Request 0x%x", status); + goto End; + } + + return; + } + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess: received METHOD_NEITHER ioctl \n"); + + // + // In this type of transfer, the I/O manager assigns the user input + // to Type3InputBuffer and the output buffer to UserBuffer of the Irp. + // The I/O manager doesn't copy or map the buffers to the kernel + // buffers. + // + status = WdfRequestRetrieveUnsafeUserInputBuffer(Request, 0, &inBuf, &inBufLen); + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error WdfRequestRetrieveUnsafeUserInputBuffer failed 0x%x", status); + goto End; + } + + status = WdfRequestRetrieveUnsafeUserOutputBuffer(Request, 0, &outBuf, &outBufLen); + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error WdfRequestRetrieveUnsafeUserOutputBuffer failed 0x%x", status); + goto End; + } + + // + // Allocate a context for this request so that we can store the memory + // objects created for input and output buffer. + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); + + status = WdfObjectAllocateContext(Request, &attributes, &reqContext); + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error WdfObjectAllocateContext failed 0x%x", status); + goto End; + } + + // + // WdfRequestProbleAndLockForRead/Write function checks to see + // whether the caller in the right thread context, creates an MDL, + // probe and locks the pages, and map the MDL to system address + // space and finally creates a WDFMEMORY object representing this + // system buffer address. This memory object is associated with the + // request. So it will be freed when the request is completed. If we + // are accessing this memory buffer else where, we should store these + // pointers in the request context. + // + + #pragma prefast(suppress:6387, "If inBuf==NULL at this point, then inBufLen==0") + status = WdfRequestProbeAndLockUserBufferForRead(Request, + inBuf, + inBufLen, + &reqContext->InputMemoryBuffer); + + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error WdfRequestProbeAndLockUserBufferForRead failed 0x%x", status); + goto End; + } + + #pragma prefast(suppress:6387, "If outBuf==NULL at this point, then outBufLen==0") + status = WdfRequestProbeAndLockUserBufferForWrite(Request, + outBuf, + outBufLen, + &reqContext->OutputMemoryBuffer); + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error WdfRequestProbeAndLockUserBufferForWrite failed 0x%x", status); + goto End; + } + + // + // Finally forward it for processing by the I/O package + // + status = WdfDeviceEnqueueRequest(Device, Request); + if(!NT_SUCCESS(status)) { + TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, + "Error WdfDeviceEnqueueRequest failed 0x%x", status); + goto End; + } + + return; + +End: + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess failed %x \n", status); + WdfRequestComplete(Request, status); + return; +} + +VOID +NonPnpShutdown( + WDFDEVICE Device + ) +/*++ + +Routine Description: + Callback invoked when the machine is shutting down. If you register for + a last chance shutdown notification you cannot do the following: + o Call any pageable routines + o Access pageable memory + o Perform any file I/O operations + + If you register for a normal shutdown notification, all of these are + available to you. + + This function implementation does nothing, but if you had any outstanding + file handles open, this is where you would close them. + +Arguments: + Device - The device which registered the notification during init + +Return Value: + None + + --*/ + +{ + UNREFERENCED_PARAMETER(Device); + return; +} + + +VOID +NonPnpEvtDriverUnload( + IN WDFDRIVER Driver + ) +/*++ +Routine Description: + + Called by the I/O subsystem just before unloading the driver. + You can free the resources created in the DriverEntry either + in this routine or in the EvtDriverContextCleanup callback. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + +Return Value: + + NTSTATUS + +--*/ +{ + UNREFERENCED_PARAMETER(Driver); + + PAGED_CODE(); + + TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "Entered NonPnpDriverUnload\n"); + + return; +} + +VOID +PrintChars( + _In_reads_(CountChars) PCHAR BufferAddress, + _In_ size_t CountChars + ) +{ + if (CountChars) { + + while (CountChars--) { + + if (*BufferAddress > 31 + && *BufferAddress != 127) { + + KdPrint (( "%c", *BufferAddress) ); + + } else { + + KdPrint(( ".") ); + + } + BufferAddress++; + } + KdPrint (("\n")); + } + return; +} + diff --git a/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.h b/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.h new file mode 100644 index 000000000..c874e79d2 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.h @@ -0,0 +1,90 @@ +/*++ + +Copyright (c) 1997 Microsoft Corporation + +Module Name: + + nonpnp.h + +Abstract: + + Contains function prototypes and includes other neccessary header files. + +Environment: + + Kernel mode only. + +--*/ + +#include +#include + +#define NTSTRSAFE_LIB +#include +#include // for SDDLs +#include "public.h" // contains IOCTL definitions +#include "Trace.h" // contains macros for WPP tracing + +#define NTDEVICE_NAME_STRING L"\\Device\\NONPNP" +#define SYMBOLIC_NAME_STRING L"\\DosDevices\\NONPNP" +#define POOL_TAG 'ELIF' + +typedef struct _CONTROL_DEVICE_EXTENSION { + + HANDLE FileHandle; // Store your control data here + +} CONTROL_DEVICE_EXTENSION, *PCONTROL_DEVICE_EXTENSION; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CONTROL_DEVICE_EXTENSION, + ControlGetData) + +// +// Following request context is used only for the method-neither ioctl case. +// +typedef struct _REQUEST_CONTEXT { + + WDFMEMORY InputMemoryBuffer; + WDFMEMORY OutputMemoryBuffer; + +} REQUEST_CONTEXT, *PREQUEST_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, GetRequestContext) + +// +// Device driver routine declarations. +// + +DRIVER_INITIALIZE DriverEntry; + +// +// Don't use EVT_WDF_DRIVER_DEVICE_ADD for NonPnpDeviceAdd even though +// the signature is same because this is not an event called by the +// framework. +// +NTSTATUS +NonPnpDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ); + +EVT_WDF_DRIVER_UNLOAD NonPnpEvtDriverUnload; + +EVT_WDF_DEVICE_CONTEXT_CLEANUP NonPnpEvtDriverContextCleanup; +EVT_WDF_DEVICE_SHUTDOWN_NOTIFICATION NonPnpShutdown; + +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL FileEvtIoDeviceControl; +EVT_WDF_IO_QUEUE_IO_READ FileEvtIoRead; +EVT_WDF_IO_QUEUE_IO_WRITE FileEvtIoWrite; + +EVT_WDF_IO_IN_CALLER_CONTEXT NonPnpEvtDeviceIoInCallerContext; +EVT_WDF_DEVICE_FILE_CREATE NonPnpEvtDeviceFileCreate; +EVT_WDF_FILE_CLOSE NonPnpEvtFileClose; + +VOID +PrintChars( + _In_reads_(CountChars) PCHAR BufferAddress, + _In_ size_t CountChars + ); + +#pragma warning(disable:4127) + diff --git a/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.rc b/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.rc new file mode 100644 index 000000000..cac68f7b2 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/driver/nonpnp.rc @@ -0,0 +1,10 @@ +#include + +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Sample Non-PNP Driver using WDF" +#define VER_INTERNALNAME_STR "NONPNP.sys" + +#include "common.ver" diff --git a/tests/projects/windows/driver/kmdf/ioctl/driver/trace.h b/tests/projects/windows/driver/kmdf/ioctl/driver/trace.h new file mode 100644 index 000000000..089f213f0 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/driver/trace.h @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + TRACE.h + +Abstract: + + Header file for the debug tracing related function defintions and macros. + +Environment: + + Kernel mode + +--*/ + +// +// If software tracing is defined in the sources file.. +// WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver. +// *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID *** +// WPP_DEFINE_BIT allows setting debug bit masks to selectively print. +// The names defined in the WPP_DEFINE_BIT call define the actual names +// that are used to control the level of tracing for the control guid +// specified. +// +// {71ae54db-0862-41bf-a24f-5330cec3c7f6} +// +#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( FileIoTraceGuid, \ + (71ae54db,0862,41bf,a24f,5330cec3c7f6), \ + WPP_DEFINE_BIT(DBG_INIT) \ + WPP_DEFINE_BIT(DBG_RW) \ + WPP_DEFINE_BIT(DBG_IOCTL) \ + ) + +#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) +#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) + +#pragma warning(disable:4204) // C4204 nonstandard extension used : non-constant aggregate initializer + +// +// Define the 'xstr' structure for logging buffer and length pairs +// and the 'log_xstr' function which returns it to create one in-place. +// this enables logging of complex data types. +// +typedef struct xstr { char * _buf; short _len; } xstr_t; +__inline xstr_t log_xstr(void * p, short l) { xstr_t xs = {(char*)p,l}; return xs; } + +#pragma warning(default:4204) + +// +// Define the macro required for a hexdump use as: +// +// Hexdump((FLAG,"%!HEXDUMP!\n", log_xstr(buffersize,(char *)buffer) )); +// +// +#define WPP_LOGHEXDUMP(x) WPP_LOGPAIR(2, &((x)._len)) WPP_LOGPAIR((x)._len, (x)._buf) + + diff --git a/tests/projects/windows/driver/kmdf/ioctl/exe/install.c b/tests/projects/windows/driver/kmdf/ioctl/exe/install.c new file mode 100644 index 000000000..53d1f7678 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/exe/install.c @@ -0,0 +1,812 @@ +/*++ +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + install.c + +Abstract: + + Win32 routines to dynamically load and unload a Windows NT kernel-mode + driver using the Service Control Manager APIs. + +Environment: + + User mode only + +--*/ + + +#include +_Analysis_mode_(_Analysis_code_type_user_code_) + +#include +#include +#include +#include +#include +#include "public.h" + +#include + +#define ARRAY_SIZE(x) (sizeof(x) /sizeof(x[0])) + +extern +PCHAR +GetCoinstallerVersion( + VOID + ) ; + +BOOLEAN +InstallDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName, + IN LPCTSTR ServiceExe + ); + + +BOOLEAN +RemoveDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName + ); + +BOOLEAN +StartDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName + ); + +BOOLEAN +StopDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName + ); + +#define SYSTEM32_DRIVERS "\\System32\\Drivers\\" +#define NONPNP_INF_FILENAME L"\\nonpnp.inf" +#define WDF_SECTION_NAME L"nonpnp.NT.Wdf" + +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +PFN_WDFPREDEVICEINSTALLEX pfnWdfPreDeviceInstallEx; +PFN_WDFPOSTDEVICEINSTALL pfnWdfPostDeviceInstall; +PFN_WDFPREDEVICEREMOVE pfnWdfPreDeviceRemove; +PFN_WDFPOSTDEVICEREMOVE pfnWdfPostDeviceRemove; + +//----------------------------------------------------------------------------- +// 4127 -- Conditional Expression is Constant warning +//----------------------------------------------------------------------------- +#define WHILE(a) \ +__pragma(warning(suppress:4127)) while(a) + +LONG +GetPathToInf( + _Out_writes_(InfFilePathSize) PWCHAR InfFilePath, + IN ULONG InfFilePathSize + ) +{ + LONG error = ERROR_SUCCESS; + + if (GetCurrentDirectoryW(InfFilePathSize, InfFilePath) == 0) { + error = GetLastError(); + printf("InstallDriver failed! Error = %d \n", error); + return error; + } + if (FAILED( StringCchCatW(InfFilePath, + InfFilePathSize, + NONPNP_INF_FILENAME) )) { + error = ERROR_BUFFER_OVERFLOW; + return error; + } + return error; + +} + +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +BOOLEAN +InstallDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName, + IN LPCTSTR ServiceExe + ) +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ +{ + SC_HANDLE schService; + DWORD err; + WCHAR infPath[MAX_PATH]; + WDF_COINSTALLER_INSTALL_OPTIONS clientOptions; + + WDF_COINSTALLER_INSTALL_OPTIONS_INIT(&clientOptions); + + // + // NOTE: This creates an entry for a standalone driver. If this + // is modified for use with a driver that requires a Tag, + // Group, and/or Dependencies, it may be necessary to + // query the registry for existing driver information + // (in order to determine a unique Tag, etc.). + // + // + // PRE-INSTALL for WDF support + // + err = GetPathToInf(infPath, ARRAY_SIZE(infPath) ); + if (err != ERROR_SUCCESS) { + return FALSE; + } + err = pfnWdfPreDeviceInstallEx(infPath, WDF_SECTION_NAME, &clientOptions); + + if (err != ERROR_SUCCESS) { + if (err == ERROR_SUCCESS_REBOOT_REQUIRED) { + printf("System needs to be rebooted, before the driver installation can proceed.\n"); + } + + return FALSE; + } + + // + // Create a new a service object. + // + + schService = CreateService(SchSCManager, // handle of service control manager database + DriverName, // address of name of service to start + DriverName, // address of display name + SERVICE_ALL_ACCESS, // type of access to service + SERVICE_KERNEL_DRIVER, // type of service + SERVICE_DEMAND_START, // when to start service + SERVICE_ERROR_NORMAL, // severity if service fails to start + ServiceExe, // address of name of binary file + NULL, // service does not belong to a group + NULL, // no tag requested + NULL, // no dependency names + NULL, // use LocalSystem account + NULL // no password for service account + ); + + if (schService == NULL) { + + err = GetLastError(); + + if (err == ERROR_SERVICE_EXISTS) { + + // + // Ignore this error. + // + + return TRUE; + + } else { + + printf("CreateService failed! Error = %d \n", err ); + + // + // Indicate an error. + // + + return FALSE; + } + } + + // + // Close the service object. + // + CloseServiceHandle(schService); + + // + // POST-INSTALL for WDF support + // + err = pfnWdfPostDeviceInstall( infPath, WDF_SECTION_NAME ); + + if (err != ERROR_SUCCESS) { + return FALSE; + } + + // + // Indicate success. + // + + return TRUE; + +} // InstallDriver + +BOOLEAN +ManageDriver( + IN LPCTSTR DriverName, + IN LPCTSTR ServiceName, + IN USHORT Function + ) +{ + + SC_HANDLE schSCManager; + + BOOLEAN rCode = TRUE; + + // + // Insure (somewhat) that the driver and service names are valid. + // + + if (!DriverName || !ServiceName) { + + printf("Invalid Driver or Service provided to ManageDriver() \n"); + + return FALSE; + } + + // + // Connect to the Service Control Manager and open the Services database. + // + + schSCManager = OpenSCManager(NULL, // local machine + NULL, // local database + SC_MANAGER_ALL_ACCESS // access required + ); + + if (!schSCManager) { + + printf("Open SC Manager failed! Error = %d \n", GetLastError()); + + return FALSE; + } + + // + // Do the requested function. + // + + switch( Function ) { + + case DRIVER_FUNC_INSTALL: + + // + // Install the driver service. + // + + if (InstallDriver(schSCManager, + DriverName, + ServiceName + )) { + + // + // Start the driver service (i.e. start the driver). + // + + rCode = StartDriver(schSCManager, + DriverName + ); + + } else { + + // + // Indicate an error. + // + + rCode = FALSE; + } + + break; + + case DRIVER_FUNC_REMOVE: + + // + // Stop the driver. + // + + StopDriver(schSCManager, + DriverName + ); + + // + // Remove the driver service. + // + + RemoveDriver(schSCManager, + DriverName + ); + + // + // Ignore all errors. + // + + rCode = TRUE; + + break; + + default: + + printf("Unknown ManageDriver() function. \n"); + + rCode = FALSE; + + break; + } + + // + // Close handle to service control manager. + // + CloseServiceHandle(schSCManager); + + return rCode; + +} // ManageDriver + + +BOOLEAN +RemoveDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName + ) +{ + SC_HANDLE schService; + BOOLEAN rCode; + DWORD err; + WCHAR infPath[MAX_PATH]; + + err = GetPathToInf(infPath, ARRAY_SIZE(infPath) ); + if (err != ERROR_SUCCESS) { + return FALSE; + } + + // + // PRE-REMOVE of WDF support + // + err = pfnWdfPreDeviceRemove( infPath, WDF_SECTION_NAME ); + + if (err != ERROR_SUCCESS) { + return FALSE; + } + + // + // Open the handle to the existing service. + // + + schService = OpenService(SchSCManager, + DriverName, + SERVICE_ALL_ACCESS + ); + + if (schService == NULL) { + + printf("OpenService failed! Error = %d \n", GetLastError()); + + // + // Indicate error. + // + + return FALSE; + } + + // + // Mark the service for deletion from the service control manager database. + // + + if (DeleteService(schService)) { + + // + // Indicate success. + // + + rCode = TRUE; + + } else { + + printf("DeleteService failed! Error = %d \n", GetLastError()); + + // + // Indicate failure. Fall through to properly close the service handle. + // + + rCode = FALSE; + } + + // + // Close the service object. + // + CloseServiceHandle(schService); + + // + // POST-REMOVE of WDF support + // + err = pfnWdfPostDeviceRemove(infPath, WDF_SECTION_NAME ); + + if (err != ERROR_SUCCESS) { + rCode = FALSE; + } + + return rCode; + +} // RemoveDriver + + + +BOOLEAN +StartDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName + ) +{ + SC_HANDLE schService; + DWORD err; + BOOL ok; + + // + // Open the handle to the existing service. + // + schService = OpenService(SchSCManager, + DriverName, + SERVICE_ALL_ACCESS + ); + + if (schService == NULL) { + // + // Indicate failure. + // + printf("OpenService failed! Error = %d\n", GetLastError()); + return FALSE; + } + + // + // Start the execution of the service (i.e. start the driver). + // + ok = StartService( schService, 0, NULL ); + + if (!ok) { + + err = GetLastError(); + + if (err == ERROR_SERVICE_ALREADY_RUNNING) { + // + // Ignore this error. + // + return TRUE; + + } else { + // + // Indicate failure. + // Fall through to properly close the service handle. + // + printf("StartService failure! Error = %d\n", err ); + return FALSE; + } + } + + // + // Close the service object. + // + CloseServiceHandle(schService); + + return TRUE; + +} // StartDriver + + + +BOOLEAN +StopDriver( + IN SC_HANDLE SchSCManager, + IN LPCTSTR DriverName + ) +{ + BOOLEAN rCode = TRUE; + SC_HANDLE schService; + SERVICE_STATUS serviceStatus; + + // + // Open the handle to the existing service. + // + + schService = OpenService(SchSCManager, + DriverName, + SERVICE_ALL_ACCESS + ); + + if (schService == NULL) { + + printf("OpenService failed! Error = %d \n", GetLastError()); + + return FALSE; + } + + // + // Request that the service stop. + // + + if (ControlService(schService, + SERVICE_CONTROL_STOP, + &serviceStatus + )) { + + // + // Indicate success. + // + + rCode = TRUE; + + } else { + + printf("ControlService failed! Error = %d \n", GetLastError() ); + + // + // Indicate failure. Fall through to properly close the service handle. + // + + rCode = FALSE; + } + + // + // Close the service object. + // + CloseServiceHandle (schService); + + return rCode; + +} // StopDriver + + +// +// Caller must free returned pathname string. +// +PCHAR +BuildDriversDirPath( + _In_ PSTR DriverName + ) +{ + size_t remain; + size_t len; + PCHAR dir; + + if (!DriverName || strlen(DriverName) == 0) { + return NULL; + } + + remain = MAX_PATH; + + // + // Allocate string space + // + dir = (PCHAR) malloc( remain + 1 ); + + if (!dir) { + return NULL; + } + + // + // Get the base windows directory path. + // + len = GetWindowsDirectory( dir, (UINT) remain ); + + if (len == 0 || + (remain - len) < sizeof(SYSTEM32_DRIVERS)) { + free(dir); + return NULL; + } + remain -= len; + + // + // Build dir to have "%windir%\System32\Drivers\". + // + if (FAILED( StringCchCat(dir, remain, SYSTEM32_DRIVERS) )) { + free(dir); + return NULL; + } + + remain -= sizeof(SYSTEM32_DRIVERS); + len += sizeof(SYSTEM32_DRIVERS); + len += strlen(DriverName); + + if (remain < len) { + free(dir); + return NULL; + } + + if (FAILED( StringCchCat(dir, remain, DriverName) )) { + free(dir); + return NULL; + } + + dir[len] = '\0'; // keeps prefast happy + + return dir; +} + + +BOOLEAN +SetupDriverName( + _Inout_updates_all_(BufferLength) PCHAR DriverLocation, + _In_ ULONG BufferLength + ) +{ + HANDLE fileHandle; + DWORD driverLocLen = 0; + BOOL ok; + PCHAR driversDir; + + // + // Setup path name to driver file. + // + driverLocLen = + GetCurrentDirectory(BufferLength, DriverLocation); + + if (!driverLocLen) { + + printf("GetCurrentDirectory failed! Error = %d \n", + GetLastError()); + + return FALSE; + } + + if (FAILED( StringCchCat(DriverLocation, BufferLength, "\\" DRIVER_NAME ".sys") )) { + return FALSE; + } + + // + // Insure driver file is in the specified directory. + // + fileHandle = CreateFile( DriverLocation, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + + if (fileHandle == INVALID_HANDLE_VALUE) { + // + // Indicate failure. + // + printf("Driver: %s.SYS is not in the %s directory. \n", + DRIVER_NAME, DriverLocation ); + return FALSE; + } + + // + // Build %windir%\System32\Drivers\ path. + // Copy the driver to %windir%\system32\drivers + // + driversDir = BuildDriversDirPath( DRIVER_NAME ".sys" ); + + if (!driversDir) { + printf("BuildDriversDirPath failed!\n"); + return FALSE; + } + + ok = CopyFile( DriverLocation, driversDir, FALSE ); + + if(!ok) { + printf("CopyFile failed: error(%d) - \"%s\"\n", + GetLastError(), driversDir ); + free(driversDir); + return FALSE; + } + + if (FAILED( StringCchCopy(DriverLocation, BufferLength, driversDir) )) { + free(driversDir); + return FALSE; + } + + free(driversDir); + + // + // Close open file handle. + // + if (fileHandle) { + CloseHandle(fileHandle); + } + + // + // Indicate success. + // + return TRUE; + +} // SetupDriverName + + +HMODULE +LoadWdfCoInstaller( + VOID + ) +{ + HMODULE library = NULL; + DWORD error = ERROR_SUCCESS; + CHAR szCurDir[MAX_PATH]; + CHAR tempCoinstallerName[MAX_PATH]; + PCHAR coinstallerVersion; + + do { + + if (GetCurrentDirectory(MAX_PATH, szCurDir) == 0) { + + printf("GetCurrentDirectory failed! Error = %d \n", GetLastError()); + break; + } + coinstallerVersion = GetCoinstallerVersion(); + if (FAILED( StringCchPrintf(tempCoinstallerName, + MAX_PATH, + "\\WdfCoInstaller%s.dll", + coinstallerVersion) )) { + break; + } + if (FAILED( StringCchCat(szCurDir, MAX_PATH, tempCoinstallerName) )) { + break; + } + + library = LoadLibrary(szCurDir); + + if (library == NULL) { + error = GetLastError(); + printf("LoadLibrary(%s) failed: %d\n", szCurDir, error); + break; + } + + pfnWdfPreDeviceInstallEx = + (PFN_WDFPREDEVICEINSTALLEX) GetProcAddress( library, "WdfPreDeviceInstallEx" ); + + if (pfnWdfPreDeviceInstallEx == NULL) { + error = GetLastError(); + printf("GetProcAddress(\"WdfPreDeviceInstallEx\") failed: %d\n", error); + return NULL; + } + + pfnWdfPostDeviceInstall = + (PFN_WDFPOSTDEVICEINSTALL) GetProcAddress( library, "WdfPostDeviceInstall" ); + + if (pfnWdfPostDeviceInstall == NULL) { + error = GetLastError(); + printf("GetProcAddress(\"WdfPostDeviceInstall\") failed: %d\n", error); + return NULL; + } + + pfnWdfPreDeviceRemove = + (PFN_WDFPREDEVICEREMOVE) GetProcAddress( library, "WdfPreDeviceRemove" ); + + if (pfnWdfPreDeviceRemove == NULL) { + error = GetLastError(); + printf("GetProcAddress(\"WdfPreDeviceRemove\") failed: %d\n", error); + return NULL; + } + + pfnWdfPostDeviceRemove = + (PFN_WDFPREDEVICEREMOVE) GetProcAddress( library, "WdfPostDeviceRemove" ); + + if (pfnWdfPostDeviceRemove == NULL) { + error = GetLastError(); + printf("GetProcAddress(\"WdfPostDeviceRemove\") failed: %d\n", error); + return NULL; + } + + } WHILE (0); + + if (error != ERROR_SUCCESS) { + if (library) { + FreeLibrary( library ); + } + library = NULL; + } + + return library; +} + + +VOID +UnloadWdfCoInstaller( + HMODULE Library + ) +{ + if (Library) { + FreeLibrary( Library ); + } +} + diff --git a/tests/projects/windows/driver/kmdf/ioctl/exe/nonpnp.inf b/tests/projects/windows/driver/kmdf/ioctl/exe/nonpnp.inf new file mode 100644 index 000000000..b20a58b48 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/exe/nonpnp.inf @@ -0,0 +1,8 @@ +[Version] +Signature="$WINDOWS NT$" + +[nonpnp.NT.Wdf] +KmdfService = nonpnp, nonpnp_Service_kmdfInst + +[nonpnp_Service_kmdfInst] +KmdfLibraryVersion = 1.11 diff --git a/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c b/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c new file mode 100644 index 000000000..c12f26073 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c @@ -0,0 +1,643 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + + +Module Name: + + testapp.c + +Abstract: + + Purpose of this app to test the NONPNP sample driver. The app + makes four different ioctl calls to test all the buffer types, write + some random buffer content to a file created by the driver in \SystemRoot\Temp + directory, and reads the same file and matches the content. + If -l option is specified, it does the write and read operation in a loop + until the app is terminated by pressing ^C. + + Make sure you have the \SystemRoot\Temp directory exists before you run the test. + +Environment: + + Win32 console application. + +--*/ + + +#include +_Analysis_mode_(_Analysis_code_type_user_code_) + +#include + +#pragma warning(disable:4201) // nameless struct/union +#include +#pragma warning(default:4201) + +#include +#include +#include +#include +#include +#include "public.h" + + +BOOLEAN +ManageDriver( + IN LPCTSTR DriverName, + IN LPCTSTR ServiceName, + IN USHORT Function + ); + +HMODULE +LoadWdfCoInstaller( + VOID + ); + +VOID +UnloadWdfCoInstaller( + HMODULE Library + ); + +BOOLEAN +SetupDriverName( + _Inout_updates_all_(BufferLength) PCHAR DriverLocation, + _In_ ULONG BufferLength + ); + +BOOLEAN +DoFileReadWrite( + HANDLE HDevice + ); + +VOID +DoIoctls( + HANDLE hDevice + ); + +// for example, WDF 1.9 is "01009". the size 6 includes the ending NULL marker +// +#define MAX_VERSION_SIZE 6 + +CHAR G_coInstallerVersion[MAX_VERSION_SIZE] = {0}; +BOOLEAN G_fLoop = FALSE; +BOOL G_versionSpecified = FALSE; + + + +//----------------------------------------------------------------------------- +// 4127 -- Conditional Expression is Constant warning +//----------------------------------------------------------------------------- +#define WHILE(constant) \ +__pragma(warning(disable: 4127)) while(constant); __pragma(warning(default: 4127)) + + +#define USAGE \ +"Usage: nonpnpapp <-V version> <-l> \n" \ + " -V version {if no version is specified the version specified in the build environment will be used.}\n" \ + " The version is the version of the KMDF coinstaller to use \n" \ + " The format of version is MMmmm where MM -- major #, mmm - serial# \n" \ + " -l { option to continuously read & write to the file} \n" + +BOOL +ValidateCoinstallerVersion( + _In_ PSTR Version + ) +{ BOOL ok = FALSE; + INT i; + + for(i= 0; i 1 ) {// give usage if invoked with no parms + error = Parse(argc, argv); + if (error != ERROR_SUCCESS) { + return; + } + } + + if (!G_versionSpecified ) { + coinstallerVersion = GetCoinstallerVersion(); + + // + // if no version is specified or an invalid one is specified use default version + // + printf("No version specified. Using default version:%s\n", + coinstallerVersion); + + } else { + coinstallerVersion = (PCHAR)&G_coInstallerVersion; + } + + // + // open the device + // + hDevice = CreateFile(DEVICE_NAME, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if(hDevice == INVALID_HANDLE_VALUE) { + + errNum = GetLastError(); + + if (!(errNum == ERROR_FILE_NOT_FOUND || + errNum == ERROR_PATH_NOT_FOUND)) { + + printf("CreateFile failed! ERROR_FILE_NOT_FOUND = %d\n", + errNum); + return ; + } + + // + // Load WdfCoInstaller.dll. + // + library = LoadWdfCoInstaller(); + + if (library == NULL) { + printf("The WdfCoInstaller%s.dll library needs to be " + "in same directory as nonpnpapp.exe\n", coinstallerVersion); + return; + } + + // + // The driver is not started yet so let us the install the driver. + // First setup full path to driver name. + // + ok = SetupDriverName( driverLocation, MAX_PATH ); + + if (!ok) { + return ; + } + + ok = ManageDriver( DRIVER_NAME, + driverLocation, + DRIVER_FUNC_INSTALL ); + + if (!ok) { + + printf("Unable to install driver. \n"); + + // + // Error - remove driver. + // + ManageDriver( DRIVER_NAME, + driverLocation, + DRIVER_FUNC_REMOVE ); + return; + } + + hDevice = CreateFile( DEVICE_NAME, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL ); + + if (hDevice == INVALID_HANDLE_VALUE) { + printf ( "Error: CreatFile Failed : %d\n", GetLastError()); + return; + } + } + + DoIoctls(hDevice); + + do { + + if(!DoFileReadWrite(hDevice)) { + break; + } + + if(!G_fLoop) { + break; + } + Sleep(1000); // sleep for 1 sec. + + } WHILE (TRUE); + + // + // Close the handle to the device before unloading the driver. + // + CloseHandle ( hDevice ); + + // + // Unload the driver. Ignore any errors. + // + ManageDriver( DRIVER_NAME, + driverLocation, + DRIVER_FUNC_REMOVE ); + + // + // Unload WdfCoInstaller.dll + // + if ( library ) { + UnloadWdfCoInstaller( library ); + } + return; +} + + +VOID +DoIoctls( + HANDLE hDevice + ) +{ + char OutputBuffer[100]; + char InputBuffer[200]; + BOOL bRc; + ULONG bytesReturned; + + // + // Printing Input & Output buffer pointers and size + // + + printf("InputBuffer Pointer = %p, BufLength = %Id\n", InputBuffer, + sizeof(InputBuffer)); + printf("OutputBuffer Pointer = %p BufLength = %Id\n", OutputBuffer, + sizeof(OutputBuffer)); + // + // Performing METHOD_BUFFERED + // + + if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), + "this String is from User Application; using METHOD_BUFFERED"))){ + return; + } + + printf("\nCalling DeviceIoControl METHOD_BUFFERED:\n"); + + memset(OutputBuffer, 0, sizeof(OutputBuffer)); + + bRc = DeviceIoControl ( hDevice, + (DWORD) IOCTL_NONPNP_METHOD_BUFFERED, + InputBuffer, + (DWORD) strlen( InputBuffer )+1, + OutputBuffer, + sizeof( OutputBuffer), + &bytesReturned, + NULL + ); + + if ( !bRc ) + { + printf ( "Error in DeviceIoControl : %d", GetLastError()); + return; + + } + printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer); + + + // + // Performing METHOD_NIETHER + // + + printf("\nCalling DeviceIoControl METHOD_NEITHER\n"); + + if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), + "this String is from User Application; using METHOD_NEITHER"))) { + return; + } + + memset(OutputBuffer, 0, sizeof(OutputBuffer)); + + bRc = DeviceIoControl ( hDevice, + (DWORD) IOCTL_NONPNP_METHOD_NEITHER, + InputBuffer, + (DWORD) strlen( InputBuffer )+1, + OutputBuffer, + sizeof( OutputBuffer), + &bytesReturned, + NULL + ); + + if ( !bRc ) + { + printf ( "Error in DeviceIoControl : %d\n", GetLastError()); + return; + + } + + printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer); + + // + // Performing METHOD_IN_DIRECT + // + + printf("\nCalling DeviceIoControl METHOD_IN_DIRECT\n"); + + if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), + "this String is from User Application; using METHOD_IN_DIRECT"))) { + return; + } + + if(FAILED(StringCchCopy(OutputBuffer, sizeof(OutputBuffer), + "This String is from User Application in OutBuffer; using METHOD_IN_DIRECT"))) { + return; + } + + bRc = DeviceIoControl ( hDevice, + (DWORD) IOCTL_NONPNP_METHOD_IN_DIRECT, + InputBuffer, + (DWORD) strlen( InputBuffer )+1, + OutputBuffer, + sizeof( OutputBuffer), + &bytesReturned, + NULL + ); + + if ( !bRc ) + { + printf ( "Error in DeviceIoControl : : %d", GetLastError()); + return; + } + + printf(" Number of bytes transfered from OutBuffer: %d\n", + bytesReturned); + + // + // Performing METHOD_OUT_DIRECT + // + + printf("\nCalling DeviceIoControl METHOD_OUT_DIRECT\n"); + if(FAILED(StringCchCopy(InputBuffer, sizeof(InputBuffer), + "this String is from User Application; using METHOD_OUT_DIRECT"))){ + return; + } + + memset(OutputBuffer, 0, sizeof(OutputBuffer)); + + bRc = DeviceIoControl ( hDevice, + (DWORD) IOCTL_NONPNP_METHOD_OUT_DIRECT, + InputBuffer, + (DWORD) strlen( InputBuffer )+1, + OutputBuffer, + sizeof( OutputBuffer), + &bytesReturned, + NULL + ); + + if ( !bRc ) + { + printf ( "Error in DeviceIoControl : : %d", GetLastError()); + return; + } + + printf(" OutBuffer (%d): %s\n", bytesReturned, OutputBuffer); + + return; + +} + + +BOOLEAN +DoFileReadWrite( + HANDLE HDevice + ) +{ + ULONG bufLength, index; + PUCHAR readBuf = NULL; + PUCHAR writeBuf = NULL; + BOOLEAN ret; + ULONG bytesWritten, bytesRead; + + // + // Seed the random-number generator with current time so that + // the numbers will be different every time we run. + // + srand( (unsigned)time( NULL ) ); + + // + // rand function returns a pseudorandom integer in the range 0 to RAND_MAX + // (0x7fff) + // + bufLength = rand(); + // + // Try until the bufLength is not zero. + // + while(bufLength == 0) { + bufLength = rand(); + } + + // + // Allocate a buffer of that size to use for write operation. + // + writeBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufLength); + if(!writeBuf) { + ret = FALSE; + goto End; + } + // + // Fill the buffer with randon number less than UCHAR_MAX. + // + index = bufLength; + while(index){ + writeBuf[index-1] = (UCHAR) rand() % UCHAR_MAX; + index--; + } + + printf("Write %d bytes to file\n", bufLength); + + // + // Tell the driver to write the buffer content to the file from the + // begining of the file. + // + + if (!WriteFile(HDevice, + writeBuf, + bufLength, + &bytesWritten, + NULL)) { + + printf("ReadFile failed with error 0x%x\n", GetLastError()); + + ret = FALSE; + goto End; + + } + + // + // Allocate another buffer of same size. + // + readBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufLength); + if(!readBuf) { + + ret = FALSE; + goto End; + } + + printf("Read %d bytes from the same file\n", bufLength); + + // + // Tell the driver to read the file from the begining. + // + if (!ReadFile(HDevice, + readBuf, + bufLength, + &bytesRead, + NULL)) { + + printf("Error: ReadFile failed with error 0x%x\n", GetLastError()); + + ret = FALSE; + goto End; + + } + + // + // Now compare the readBuf and writeBuf content. They should be the same. + // + + if(bytesRead != bytesWritten) { + printf("bytesRead(%d) != bytesWritten(%d)\n", bytesRead, bytesWritten); + ret = FALSE; + goto End; + } + + if(memcmp(readBuf, writeBuf, bufLength) != 0){ + printf("Error: ReadBuf and WriteBuf contents are not the same\n"); + ret = FALSE; + goto End; + } + + ret = TRUE; + +End: + + if(readBuf){ + HeapFree (GetProcessHeap(), 0, readBuf); + } + + if(writeBuf){ + HeapFree (GetProcessHeap(), 0, writeBuf); + } + + return ret; + + +} + + diff --git a/tests/projects/windows/driver/kmdf/ioctl/localwpp.ini b/tests/projects/windows/driver/kmdf/ioctl/localwpp.ini new file mode 100644 index 000000000..c290070a7 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/localwpp.ini @@ -0,0 +1,17 @@ +// +// This defines how to log a len/buffer pair. +// This function should be in trace.h +// + +DEFINE_CPLX_TYPE(HEXDUMP, WPP_LOGHEXDUMP, xstr_t, ItemHEXDump,"s", _HEX_, 0,2); + +// DEFINE_CPLX_TYPE( +// name, // i.e. HEXDUMP // %!HEXDUMP! +// macro, // i.e. WPP_LOGHEXDUMP // Marshalling macro, defined in trace.h +// structure, // i.e. xstr_t // Argument type (structure to be created by above macro) +// item type, // i.e. ItemHEXDump // MOF type that TracePrt can understand +// format specifier, // i.e. "s" // a format specifier that TracePrt can understand +// ???? // i.e. _HEX_ // Type signature (becomes a part of function name) +// ???? // i.e. 0 // Weight (0 is variable data length) +// ???? // i.e. 2 // Slots used by this entry (optional, 1 default) +// ) diff --git a/tests/projects/windows/driver/kmdf/ioctl/public.h b/tests/projects/windows/driver/kmdf/ioctl/public.h new file mode 100644 index 000000000..02e24be2e --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/public.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + + +Module Name: + + PUBLIC.H + +Abstract: + + + Defines the IOCTL codes that will be used by this driver. The IOCTL code + contains a command identifier, plus other information about the device, + the type of access with which the file must have been opened, + and the type of buffering. + +Environment: + + Kernel mode only. + +--*/ + +// +// Device type -- in the "User Defined" range." +// +#define FILEIO_TYPE 40001 +// +// The IOCTL function codes from 0x800 to 0xFFF are for customer use. +// +#define IOCTL_NONPNP_METHOD_IN_DIRECT \ + CTL_CODE( FILEIO_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS ) + +#define IOCTL_NONPNP_METHOD_OUT_DIRECT \ + CTL_CODE( FILEIO_TYPE, 0x901, METHOD_OUT_DIRECT , FILE_ANY_ACCESS ) + +#define IOCTL_NONPNP_METHOD_BUFFERED \ + CTL_CODE( FILEIO_TYPE, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS ) + +#define IOCTL_NONPNP_METHOD_NEITHER \ + CTL_CODE( FILEIO_TYPE, 0x903, METHOD_NEITHER , FILE_ANY_ACCESS ) + + +#define DRIVER_FUNC_INSTALL 0x01 +#define DRIVER_FUNC_REMOVE 0x02 + +#define DRIVER_NAME "NONPNP" +#define DEVICE_NAME "\\\\.\\NONPNP\\nonpnpsamp.log" diff --git a/tests/projects/windows/driver/kmdf/ioctl/xmake.lua b/tests/projects/windows/driver/kmdf/ioctl/xmake.lua new file mode 100644 index 000000000..9cbaf0b5f --- /dev/null +++ b/tests/projects/windows/driver/kmdf/ioctl/xmake.lua @@ -0,0 +1,15 @@ +add_rules("mode.debug", "mode.release") + +add_includedirs(".") + +target("nonpnp") + add_rules("wdk.env.kmdf", "wdk.driver") + add_values("wdk.tracewpp.flags", "-func:TraceEvents(LEVEL,FLAGS,MSG,...)", "-func:Hexdump((LEVEL,FLAGS,MSG,...))") + add_files("driver/*.c", {rule = "wdk.tracewpp"}) + add_files("driver/*.rc") + +target("app") + add_rules("wdk.env.kmdf", "wdk.binary") + add_files("exe/*.c") + add_files("exe/*.inf") + diff --git a/tests/projects/windows/driver/kmdf/serial/error.c b/tests/projects/windows/driver/kmdf/serial/error.c new file mode 100644 index 000000000..904e54b05 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/error.c @@ -0,0 +1,67 @@ +/*++ +Copyright (c) Microsoft Corporation + +Module Name: + + error.c + +Abstract: + + This module contains the code that is very specific to error + operations in the serial driver + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "error.tmh" +#endif + + +VOID +SerialCommError( + IN WDFDPC Dpc + ) +/*++ + +Routine Description: + + This routine is invoked at dpc level to in response to + a comm error. All comm errors complete all read and writes + +Arguments: + + +Return Value: + + None. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, + ">SerialCommError(%p)\n", Extension); + + SerialFlushRequests( + Extension->WriteQueue, + &Extension->CurrentWriteRequest + ); + + SerialFlushRequests( + Extension->ReadQueue, + &Extension->CurrentReadRequest + ); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, + "SerialFlush(%p, %p)\n", Device, Irp); + + PAGED_CODE(); + + WdfIoQueueStopSynchronously(extension->WriteQueue); + // + // Flush is done - restart the queue + // + WdfIoQueueStart(extension->WriteQueue); + + Irp->IoStatus.Information = 0L; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "CurrentImmediateRequest); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, ">SerialStartImmediate(%p)\n", + Extension); + + UseATimer = FALSE; + reqContext->Status = STATUS_PENDING; + + // + // Calculate the timeout value needed for the + // request. Note that the values stored in the + // timeout record are in milliseconds. Note that + // if the timeout values are zero then we won't start + // the timer. + // + + Timeouts = Extension->Timeouts; + + if (Timeouts.WriteTotalTimeoutConstant || + Timeouts.WriteTotalTimeoutMultiplier) { + + UseATimer = TRUE; + + // + // We have some timer values to calculate. + // + + TotalTime.QuadPart + = (LONGLONG)((ULONG)Timeouts.WriteTotalTimeoutMultiplier); + + TotalTime.QuadPart += Timeouts.WriteTotalTimeoutConstant; + + TotalTime.QuadPart *= -10000; + + } + + // + // As the request might be going to the isr, this is a good time + // to initialize the reference count. + // + + SERIAL_INIT_REFERENCE(reqContext); + + // + // We give the request to to the isr to write out. + // We set a cancel routine that knows how to + // grab the current write away from the isr. + // + SerialSetCancelRoutine(Extension->CurrentImmediateRequest, + SerialCancelImmediate); + + if (UseATimer) { + BOOLEAN result; + + result = SerialSetTimer( + Extension->ImmediateTotalTimer, + TotalTime + ); + + if(result == FALSE) { + // + // Since the timer knows about the request we increment + // the reference count. + // + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_TOTAL_TIMER + ); + } + } + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGiveImmediateToIsr, + Extension + ); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "SerialCompleteImmediate(%p)\n", + Extension); + + SerialTryToCompleteCurrent( + Extension, + NULL, + STATUS_SUCCESS, + &Extension->CurrentImmediateRequest, + NULL, + NULL, + Extension->ImmediateTotalTimer, + NULL, + SerialGetNextImmediate, + SERIAL_REF_ISR + ); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "SerialTimeoutImmediate(%p)\n", + Extension); + + SerialTryToCompleteCurrent( + Extension, + SerialGrabImmediateFromIsr, + STATUS_TIMEOUT, + &Extension->CurrentImmediateRequest, + NULL, + NULL, + Extension->ImmediateTotalTimer, + NULL, + SerialGetNextImmediate, + SERIAL_REF_TOTAL_TIMER + ); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "TotalCharsQueued >= 1); + Extension->TotalCharsQueued--; + + *CurrentOpRequest = NULL; + *NewRequest = NULL; + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialProcessEmptyTransmit, + Extension + ); + + SerialCompleteRequest(oldRequest, reqContext->Status, reqContext->Information); +} + +VOID +SerialCancelImmediate( + IN WDFREQUEST Request + ) + +/*++ + +Routine Description: + + This routine is used to cancel a request that is waiting on + a comm event. + +Arguments: + + Request - Pointer to the WDFREQUEST for the current request + +Return Value: + + None. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = NULL; + WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); + + UNREFERENCED_PARAMETER(Request); + + Extension = SerialGetDeviceExtension(device); + + SerialTryToCompleteCurrent( + Extension, + SerialGrabImmediateFromIsr, + STATUS_CANCELLED, + &Extension->CurrentImmediateRequest, + NULL, + NULL, + Extension->ImmediateTotalTimer, + NULL, + SerialGetNextImmediate, + SERIAL_REF_CANCEL + ); + +} + +BOOLEAN +SerialGiveImmediateToIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) +/*++ + +Routine Description: + + Try to start off the write by slipping it in behind + a transmit immediate char, or if that isn't available + and the transmit holding register is empty, "tickle" + the UART into interrupting with a transmit buffer + empty. + + NOTE: This routine is called by WdfInterruptSynchronize. + + NOTE: This routine assumes that it is called with the + cancel spin lock held. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION Extension = Context; + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentImmediateRequest); + + Extension->TransmitImmediate = TRUE; + Extension->ImmediateChar = *((UCHAR *) (reqContext->SystemBuffer)); + + // + // The isr now has a reference to the request. + // + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + // + // Check first to see if a write is going on. If + // there is then we'll just slip in during the write. + // + + if (!Extension->WriteLength) { + + // + // If there is no normal write transmitting then we + // will "re-enable" the transmit holding register empty + // interrupt. The 8250 family of devices will always + // signal a transmit holding register empty interrupt + // *ANY* time this bit is set to one. By doing things + // this way we can simply use the normal interrupt code + // to start off this write. + // + // We've been keeping track of whether the transmit holding + // register is empty so it we only need to do this + // if the register is empty. + // + + if (Extension->HoldingEmpty) { + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + + } + + } + + return FALSE; + +} + +BOOLEAN +SerialGrabImmediateFromIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + + This routine is used to grab the current request, which could be timing + out or canceling, from the ISR + + NOTE: This routine is being called from WdfInterruptSynchronize. + + NOTE: This routine assumes that the cancel spin lock is held + when this routine is called. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + Always false. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = Context; + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentImmediateRequest); + + if (Extension->TransmitImmediate) { + + Extension->TransmitImmediate = FALSE; + + // + // Since the isr no longer references this request, we can + // decrement it's reference count. + // + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + } + + return FALSE; + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/initunlo.c b/tests/projects/windows/driver/kmdf/serial/initunlo.c new file mode 100644 index 000000000..07e7fb003 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/initunlo.c @@ -0,0 +1,197 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + initunlo.c + +Abstract: + + This module contains the code that is very specific to initialization + and unload operations in the serial driver + + WDF Version of serial sample doesn't support: + 1) Multiport Serial devices. + 2) Enumeration of Non PNP serial devices that are not detected by BIOS + (IO address range 0x2F0-0x2F7 using IRQ 9) +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "initunlo.tmh" +#endif + +static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; + +// +// We use this to query into the registry as to whether we +// should break at driver entry. +// + +SERIAL_FIRMWARE_DATA driverDefaults; + +// +// This is exported from the kernel. It is used to point +// to the address that the kernel debugger is using. +// +extern PUCHAR *KdComPortInUse; +// +// INIT - only needed during init and then can be disposed +// PAGESRP0 - always paged / never locked +// PAGESER - must be locked when a device is open, else paged +// +// +// INIT is used for DriverEntry() specific code +// +// PAGESRP0 is used for code that is not often called and has nothing +// to do with I/O performance. An example, passive-level PNP +// support functions +// +// PAGESER is used for code that needs to be locked after an open for both +// performance and IRQL reasons. +// + +ULONG DebugLevel = TRACE_LEVEL_INFORMATION; +ULONG DebugFlag = 0xf;//0x46;//0x4FF; //0x00000006; + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, SerialEvtDriverContextCleanup) +#endif + + + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + The entry point that the system point calls to initialize + any driver. + +Arguments: + + DriverObject - Just what it says, really of little use + to the driver itself, it is something that the IO system + cares more about. + + PathToRegistry - points to the entry for this driver + in the current control set of the registry. + +Return Value: + + Always STATUS_SUCCESS + +--*/ + +{ + WDF_DRIVER_CONFIG config; + WDFDRIVER hDriver; + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES attributes; + + // + // Initialize WPP Tracing + // + WPP_INIT_TRACING( DriverObject, RegistryPath ); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, + "Serial Sample (WDF Version)\n"); + // + // Register a cleanup callback so that we can call WPP_CLEANUP when + // the framework driver object is deleted during driver unload. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = SerialEvtDriverContextCleanup; + + WDF_DRIVER_CONFIG_INIT(&config, SerialEvtDeviceAdd); + + status = WdfDriverCreate(DriverObject, + RegistryPath, + &attributes, + &config, + &hDriver); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_INIT, + "WdfDriverCreate failed with status 0x%x\n", + status); + // + // Cleanup tracing here because DriverContextCleanup will not be called + // as we have failed to create WDFDRIVER object itself. + // Please note that if your return failure from DriverEntry after the + // WDFDRIVER object is created successfully, you don't have to + // call WPP cleanup because in those cases DriverContextCleanup + // will be executed when the framework deletes the DriverObject. + // + WPP_CLEANUP(DriverObject); + return status; + } + + // + // Call to find out default values to use for all the devices that the + // driver controls, including whether or not to break on entry. + // + + SerialGetConfigDefaults(&driverDefaults, hDriver); + + // + // Break on entry if requested via registry + // + if (driverDefaults.ShouldBreakOnEntry) { + DbgBreakPoint(); + } + + + return status; +} + + +_Use_decl_annotations_ +VOID +SerialEvtDriverContextCleanup( + WDFOBJECT Driver + ) +/*++ +Routine Description: + + Free all the resources allocated in DriverEntry. + +Arguments: + + Driver - handle to a WDF Driver object. + +Return Value: + + VOID. + +--*/ +{ + UNREFERENCED_PARAMETER(Driver); + + PAGED_CODE (); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, + "--> SerialEvtDriverContextCleanup\n"); + + // + // Stop WPP Tracing + // + WPP_CLEANUP( WdfDriverWdmGetDriverObject(Driver) ); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, + "<-- SerialEvtDriverContextCleanup\n"); + +} + + + diff --git a/tests/projects/windows/driver/kmdf/serial/ioctl.c b/tests/projects/windows/driver/kmdf/serial/ioctl.c new file mode 100644 index 000000000..07ff2b147 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/ioctl.c @@ -0,0 +1,2187 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + ioctl.c + +Abstract: + + This module contains the ioctl dispatcher as well as a couple + of routines that are generally just called in response to + ioctl calls. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "ioctl.tmh" +#endif + +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetModemUpdate; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetCommStatus; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetEscapeChar; + +PCHAR +SerialGetIoctlName( + IN ULONG IoControlCode + ) +/*++ + +Routine Description: + SerialGetIoctlName returns the name of the ioctl + +--*/ +{ + switch (IoControlCode) + { + case IOCTL_SERIAL_SET_BAUD_RATE : return "IOCTL_SERIAL_SET_BAUD_RATE"; + case IOCTL_SERIAL_GET_BAUD_RATE: return "IOCTL_SERIAL_GET_BAUD_RATE"; + case IOCTL_SERIAL_GET_MODEM_CONTROL: return "IOCTL_SERIAL_GET_MODEM_CONTROL"; + case IOCTL_SERIAL_SET_MODEM_CONTROL: return "IOCTL_SERIAL_SET_MODEM_CONTROL"; + case IOCTL_SERIAL_SET_FIFO_CONTROL: return "IOCTL_SERIAL_SET_FIFO_CONTROL"; + case IOCTL_SERIAL_SET_LINE_CONTROL: return "IOCTL_SERIAL_SET_LINE_CONTROL"; + case IOCTL_SERIAL_GET_LINE_CONTROL: return "IOCTL_SERIAL_GET_LINE_CONTROL"; + case IOCTL_SERIAL_SET_TIMEOUTS: return "IOCTL_SERIAL_SET_TIMEOUTS"; + case IOCTL_SERIAL_GET_TIMEOUTS: return "IOCTL_SERIAL_GET_TIMEOUTS"; + case IOCTL_SERIAL_SET_CHARS: return "IOCTL_SERIAL_SET_CHARS"; + case IOCTL_SERIAL_GET_CHARS: return "IOCTL_SERIAL_GET_CHARS"; + case IOCTL_SERIAL_SET_DTR: return "IOCTL_SERIAL_SET_DTR"; + case IOCTL_SERIAL_CLR_DTR: return "IOCTL_SERIAL_SET_DTR"; + case IOCTL_SERIAL_RESET_DEVICE: return "IOCTL_SERIAL_RESET_DEVICE"; + case IOCTL_SERIAL_SET_RTS: return "IOCTL_SERIAL_SET_RTS"; + case IOCTL_SERIAL_CLR_RTS: return "IOCTL_SERIAL_CLR_RTS"; + case IOCTL_SERIAL_SET_XOFF: return "IOCTL_SERIAL_SET_XOFF"; + case IOCTL_SERIAL_SET_XON: return "IOCTL_SERIAL_SET_XON"; + case IOCTL_SERIAL_SET_BREAK_ON: return "IOCTL_SERIAL_SET_BREAK_ON"; + case IOCTL_SERIAL_SET_BREAK_OFF: return "IOCTL_SERIAL_SET_BREAK_OFF"; + case IOCTL_SERIAL_SET_QUEUE_SIZE: return "IOCTL_SERIAL_SET_QUEUE_SIZE"; + case IOCTL_SERIAL_GET_WAIT_MASK: return "IOCTL_SERIAL_GET_WAIT_MASK"; + case IOCTL_SERIAL_SET_WAIT_MASK: return "IOCTL_SERIAL_SET_WAIT_MASK"; + case IOCTL_SERIAL_WAIT_ON_MASK: return "IOCTL_SERIAL_WAIT_ON_MASK"; + case IOCTL_SERIAL_IMMEDIATE_CHAR: return "IOCTL_SERIAL_IMMEDIATE_CHAR"; + case IOCTL_SERIAL_PURGE: return "IOCTL_SERIAL_PURGE"; + case IOCTL_SERIAL_GET_HANDFLOW: return "IOCTL_SERIAL_GET_HANDFLOW"; + case IOCTL_SERIAL_SET_HANDFLOW: return "IOCTL_SERIAL_SET_HANDFLOW"; + case IOCTL_SERIAL_GET_MODEMSTATUS: return "IOCTL_SERIAL_GET_MODEMSTATUS"; + case IOCTL_SERIAL_GET_DTRRTS: return "IOCTL_SERIAL_GET_DTRRTS"; + case IOCTL_SERIAL_GET_COMMSTATUS: return "IOCTL_SERIAL_GET_COMMSTATUS"; + case IOCTL_SERIAL_GET_PROPERTIES: return "IOCTL_SERIAL_GET_PROPERTIES"; + case IOCTL_SERIAL_XOFF_COUNTER: return "IOCTL_SERIAL_XOFF_COUNTER"; + case IOCTL_SERIAL_LSRMST_INSERT: return "IOCTL_SERIAL_LSRMST_INSERT"; + case IOCTL_SERIAL_CONFIG_SIZE: return "IOCTL_SERIAL_CONFIG_SIZE"; + case IOCTL_SERIAL_GET_STATS: return "IOCTL_SERIAL_GET_STATS"; + case IOCTL_SERIAL_CLEAR_STATS: return "IOCTL_SERIAL_CLEAR_STATS"; + default: return "UnKnown ioctl"; + } +} + + + +BOOLEAN +SerialGetStats( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + In sync with the interrpt service routine (which sets the perf stats) + return the perf stats to the caller. + + +Arguments: + + Context - Pointer to a the request. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PREQUEST_CONTEXT reqContext = (PREQUEST_CONTEXT)Context; + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(WdfInterruptGetDevice(Interrupt)); + PSERIALPERF_STATS sp = reqContext->SystemBuffer; + + UNREFERENCED_PARAMETER(Interrupt); + + *sp = extension->PerfStats; + return FALSE; + +} + + +BOOLEAN +SerialClearStats( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + In sync with the interrpt service routine (which sets the perf stats) + clear the perf stats. + + +Arguments: + + Context - Pointer to a the extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + UNREFERENCED_PARAMETER(Interrupt); + + RtlZeroMemory( + &((PSERIAL_DEVICE_EXTENSION)Context)->PerfStats, + sizeof(SERIALPERF_STATS) + ); + + RtlZeroMemory(&((PSERIAL_DEVICE_EXTENSION)Context)->WmiPerfData, + sizeof(SERIAL_WMI_PERF_DATA)); + + return FALSE; +} + + + +BOOLEAN +SerialSetChars( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to set the special characters for the + driver. + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a special characters + structure. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + UNREFERENCED_PARAMETER(Interrupt); + + ((PSERIAL_IOCTL_SYNC)Context)->Extension->SpecialChars = + *((PSERIAL_CHARS)(((PSERIAL_IOCTL_SYNC)Context)->Data)); + + return FALSE; +} + + +BOOLEAN +SerialSetBaud( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to set the baud rate of the device. + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and what should be the current + baud rate. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; + USHORT Appropriate = PtrToUshort(((PSERIAL_IOCTL_SYNC)Context)->Data); + + UNREFERENCED_PARAMETER(Interrupt); + + WRITE_DIVISOR_LATCH( + Extension, + Extension->Controller, + Appropriate + ); + + return FALSE; +} + + +BOOLEAN +SerialSetLineControl( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to set the buad rate of the device. + +Arguments: + + Context - Pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + WRITE_LINE_CONTROL(Extension, + Extension->Controller, + Extension->LineControl + ); + + return FALSE; +} + + +BOOLEAN +SerialGetModemUpdate( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is simply used to call the interrupt level routine + that handles modem status update. + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a ulong. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; + ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); + + UNREFERENCED_PARAMETER(Interrupt); + + *Result = SerialHandleModemUpdate( + Extension, + FALSE + ); + + return FALSE; +} + + + +BOOLEAN +SerialSetMCRContents( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) +/*++ + +Routine Description: + + This routine is simply used to set the contents of the MCR + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a ulong. + +Return Value: + + This routine always returns FALSE. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; + ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); + + UNREFERENCED_PARAMETER(Interrupt); + + // + // This is severe casting abuse!!! + // + WRITE_MODEM_CONTROL(Extension, Extension->Controller, (UCHAR)PtrToUlong(Result)); + + return FALSE; +} + + + + +BOOLEAN +SerialGetMCRContents( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is simply used to get the contents of the MCR + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a ulong. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; + ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); + + UNREFERENCED_PARAMETER(Interrupt); + + *Result = READ_MODEM_CONTROL(Extension, Extension->Controller); + + return FALSE; +} + + + + +BOOLEAN +SerialSetFCRContents( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) +/*++ + +Routine Description: + + This routine is simply used to set the contents of the FCR + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a ulong. + +Return Value: + + This routine always returns FALSE. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; + ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data); + + UNREFERENCED_PARAMETER(Interrupt); + + // + // This is severe casting abuse!!! + // + WRITE_FIFO_CONTROL(Extension, Extension->Controller, (UCHAR)*Result); + + return FALSE; +} + + + +BOOLEAN +SerialGetCommStatus( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This is used to get the current state of the serial driver. + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a serial status + record. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension; + PSERIAL_STATUS Stat = ((PSERIAL_IOCTL_SYNC)Context)->Data; + + UNREFERENCED_PARAMETER(Interrupt); + + Stat->Errors = Extension->ErrorWord; + Extension->ErrorWord = 0; + + // + // Eof isn't supported in binary mode + // + Stat->EofReceived = FALSE; + + Stat->AmountInInQueue = Extension->CharsInInterruptBuffer; + + Stat->AmountInOutQueue = Extension->TotalCharsQueued; + + if (Extension->WriteLength) { + + // + // By definition if we have a writelength the we have + // a current write request. + // + PREQUEST_CONTEXT reqContext = NULL; + + ASSERT(Extension->CurrentWriteRequest); + ASSERT(Stat->AmountInOutQueue >= Extension->WriteLength); + + reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); + Stat->AmountInOutQueue -= reqContext->Length - (Extension->WriteLength); + + } + + Stat->WaitForImmediate = Extension->TransmitImmediate; + + Stat->HoldReasons = 0; + if (Extension->TXHolding) { + + if (Extension->TXHolding & SERIAL_TX_CTS) { + + Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS; + + } + + if (Extension->TXHolding & SERIAL_TX_DSR) { + + Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR; + + } + + if (Extension->TXHolding & SERIAL_TX_DCD) { + + Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD; + + } + + if (Extension->TXHolding & SERIAL_TX_XOFF) { + + Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_XON; + + } + + if (Extension->TXHolding & SERIAL_TX_BREAK) { + + Stat->HoldReasons |= SERIAL_TX_WAITING_ON_BREAK; + + } + + } + + if (Extension->RXHolding & SERIAL_RX_DSR) { + + Stat->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR; + + } + + if (Extension->RXHolding & SERIAL_RX_XOFF) { + + Stat->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT; + + } + + return FALSE; +} + + +BOOLEAN +SerialSetEscapeChar( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This is used to set the character that will be used to escape + line status and modem status information when the application + has set up that line status and modem status should be passed + back in the data stream. + +Arguments: + + Context - Pointer to the request that is specify the escape character. + Implicitly - An escape character of 0 means no escaping + will occur. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PREQUEST_CONTEXT reqContext = (PREQUEST_CONTEXT)Context; + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(WdfInterruptGetDevice(Interrupt)); + + UNREFERENCED_PARAMETER(Interrupt); + + extension->EscapeChar = *(PUCHAR)reqContext->SystemBuffer; + + return FALSE; +} + +VOID +SerialEvtIoDeviceControl( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode + ) + +/*++ + +Routine Description: + + This routine provides the initial processing for all of the + Ioctrls for the serial device. + +Arguments: + + Request - Pointer to the WDFREQUEST for the current request + +Return Value: + + The function value is the final status of the call + +--*/ + +{ + // + // The status that gets returned to the caller and + // set in the Request. + // + NTSTATUS Status; + + // + // Just what it says. This is the serial specific device + // extension of the device object create for the serial driver. + // + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + PVOID buffer; + PREQUEST_CONTEXT reqContext; + size_t bufSize; + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + reqContext = SerialGetRequestContext(Request); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "%s for: %p\n", + SerialGetIoctlName(IoControlCode), Request); + + Extension = SerialGetDeviceExtension(WdfIoQueueGetDevice(Queue)); + + // + // We expect to be open so all our pages are locked down. This is, after + // all, an IO operation, so the device should be open first. + // + + if (Extension->DeviceIsOpened != TRUE) { + SerialCompleteRequest(Request, STATUS_INVALID_DEVICE_REQUEST, 0); + return; + } + + + if (SerialCompleteIfError(Extension, Request) != STATUS_SUCCESS) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, + "Information = 0; + reqContext->Status = STATUS_SUCCESS; + reqContext->MajorFunction = IRP_MJ_DEVICE_CONTROL; + + + Status = STATUS_SUCCESS; + + switch (IoControlCode) { + + case IOCTL_SERIAL_SET_BAUD_RATE : { + + ULONG BaudRate; + // + // Will hold the value of the appropriate divisor for + // the requested baud rate. If the baudrate is invalid + // (because the device won't support that baud rate) then + // this value is undefined. + // + // Note: in one sense the concept of a valid baud rate + // is cloudy. We could allow the user to request any + // baud rate. We could then calculate the divisor needed + // for that baud rate. As long as the divisor wasn't less + // than one we would be "ok". (The percentage difference + // between the "true" divisor and the "rounded" value given + // to the hardware might make it unusable, but... ) It would + // really be up to the user to "Know" whether the baud rate + // is suitable. So much for theory, *We* only support a given + // set of baud rates. + // + SHORT AppropriateDivisor; + + Status = WdfRequestRetrieveInputBuffer (Request, sizeof(SERIAL_BAUD_RATE), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + BaudRate = ((PSERIAL_BAUD_RATE)(buffer))->BaudRate; + + + // + // Get the baud rate from the request. We pass it + // to a routine which will set the correct divisor. + // + + Status = SerialGetDivisorFromBaud( + Extension->ClockRate, + BaudRate, + &AppropriateDivisor + ); + + + if (NT_SUCCESS(Status)) { + + SERIAL_IOCTL_SYNC S; + + + Extension->CurrentBaud = BaudRate; + Extension->WmiCommData.BaudRate = BaudRate; + + S.Extension = Extension; + S.Data = (PVOID) (ULONG_PTR) AppropriateDivisor; + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetBaud, + &S + ); + + } + + break; + } + + case IOCTL_SERIAL_GET_BAUD_RATE: { + + PSERIAL_BAUD_RATE Br; + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_BAUD_RATE), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + Br = (PSERIAL_BAUD_RATE)buffer; + + Br->BaudRate = Extension->CurrentBaud; + + reqContext->Information = sizeof(SERIAL_BAUD_RATE); + + break; + + } + + case IOCTL_SERIAL_GET_MODEM_CONTROL: { + SERIAL_IOCTL_SYNC S; + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->Information = sizeof(ULONG); + + S.Extension = Extension; + S.Data = buffer; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGetMCRContents, + &S + ); + + break; + } + case IOCTL_SERIAL_SET_MODEM_CONTROL: { + SERIAL_IOCTL_SYNC S; + + Status = WdfRequestRetrieveInputBuffer (Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + S.Extension = Extension; + S.Data = buffer; + + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetMCRContents, + &S + ); + + break; + } + case IOCTL_SERIAL_SET_FIFO_CONTROL: { + SERIAL_IOCTL_SYNC S; + + Status = WdfRequestRetrieveInputBuffer (Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + S.Extension = Extension; + S.Data = buffer; + + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetFCRContents, + &S + ); + + break; + } + case IOCTL_SERIAL_SET_LINE_CONTROL: { + + PSERIAL_LINE_CONTROL Lc; + UCHAR LData; + UCHAR LStop; + UCHAR LParity; + UCHAR Mask = 0xff; + + Status = WdfRequestRetrieveInputBuffer (Request, sizeof(SERIAL_LINE_CONTROL), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + // + // Points to the line control record in the Request. + // + Lc = (PSERIAL_LINE_CONTROL)buffer; + + switch (Lc->WordLength) { + case 5: { + + LData = SERIAL_5_DATA; + Mask = 0x1f; + break; + + } + case 6: { + + LData = SERIAL_6_DATA; + Mask = 0x3f; + break; + + } + case 7: { + + LData = SERIAL_7_DATA; + Mask = 0x7f; + break; + + } + case 8: { + + LData = SERIAL_8_DATA; + break; + + } + default: { + + Status = STATUS_INVALID_PARAMETER; + goto DoneWithIoctl; + + } + + } + + Extension->WmiCommData.BitsPerByte = Lc->WordLength; + + switch (Lc->Parity) { + + case NO_PARITY: { + Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE; + LParity = SERIAL_NONE_PARITY; + break; + + } + case EVEN_PARITY: { + Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN; + LParity = SERIAL_EVEN_PARITY; + break; + + } + case ODD_PARITY: { + Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD; + LParity = SERIAL_ODD_PARITY; + break; + + } + case SPACE_PARITY: { + Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE; + LParity = SERIAL_SPACE_PARITY; + break; + + } + case MARK_PARITY: { + Extension->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK; + LParity = SERIAL_MARK_PARITY; + break; + + } + default: { + + Status = STATUS_INVALID_PARAMETER; + goto DoneWithIoctl; + break; + } + + } + + switch (Lc->StopBits) { + + case STOP_BIT_1: { + Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1; + LStop = SERIAL_1_STOP; + break; + } + case STOP_BITS_1_5: { + + if (LData != SERIAL_5_DATA) { + + Status = STATUS_INVALID_PARAMETER; + goto DoneWithIoctl; + } + Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_1_5; + LStop = SERIAL_1_5_STOP; + break; + + } + case STOP_BITS_2: { + + if (LData == SERIAL_5_DATA) { + + Status = STATUS_INVALID_PARAMETER; + goto DoneWithIoctl; + } + Extension->WmiCommData.StopBits = SERIAL_WMI_STOP_2; + LStop = SERIAL_2_STOP; + break; + + } + default: { + + Status = STATUS_INVALID_PARAMETER; + goto DoneWithIoctl; + } + + } + + Extension->LineControl = + (UCHAR)((Extension->LineControl & SERIAL_LCR_BREAK) | + (LData | LParity | LStop)); + Extension->ValidDataMask = Mask; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetLineControl, + Extension + ); + + break; + } + case IOCTL_SERIAL_GET_LINE_CONTROL: { + + PSERIAL_LINE_CONTROL Lc; + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_LINE_CONTROL), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + Lc = (PSERIAL_LINE_CONTROL)buffer; + + RtlZeroMemory(buffer, OutputBufferLength); + + if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) { + Lc->WordLength = 5; + } else if ((Extension->LineControl & SERIAL_DATA_MASK) + == SERIAL_6_DATA) { + Lc->WordLength = 6; + } else if ((Extension->LineControl & SERIAL_DATA_MASK) + == SERIAL_7_DATA) { + Lc->WordLength = 7; + } else if ((Extension->LineControl & SERIAL_DATA_MASK) + == SERIAL_8_DATA) { + Lc->WordLength = 8; + } + + if ((Extension->LineControl & SERIAL_PARITY_MASK) + == SERIAL_NONE_PARITY) { + Lc->Parity = NO_PARITY; + } else if ((Extension->LineControl & SERIAL_PARITY_MASK) + == SERIAL_ODD_PARITY) { + Lc->Parity = ODD_PARITY; + } else if ((Extension->LineControl & SERIAL_PARITY_MASK) + == SERIAL_EVEN_PARITY) { + Lc->Parity = EVEN_PARITY; + } else if ((Extension->LineControl & SERIAL_PARITY_MASK) + == SERIAL_MARK_PARITY) { + Lc->Parity = MARK_PARITY; + } else if ((Extension->LineControl & SERIAL_PARITY_MASK) + == SERIAL_SPACE_PARITY) { + Lc->Parity = SPACE_PARITY; + } + + if (Extension->LineControl & SERIAL_2_STOP) { + if (Lc->WordLength == 5) { + Lc->StopBits = STOP_BITS_1_5; + } else { + Lc->StopBits = STOP_BITS_2; + } + } else { + Lc->StopBits = STOP_BIT_1; + } + + reqContext->Information = sizeof(SERIAL_LINE_CONTROL); + + break; + } + case IOCTL_SERIAL_SET_TIMEOUTS: { + + PSERIAL_TIMEOUTS NewTimeouts; + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_TIMEOUTS), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + NewTimeouts =(PSERIAL_TIMEOUTS)buffer; + + if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) && + (NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) && + (NewTimeouts->ReadTotalTimeoutConstant == MAXULONG)) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + + Extension->Timeouts.ReadIntervalTimeout = + NewTimeouts->ReadIntervalTimeout; + + Extension->Timeouts.ReadTotalTimeoutMultiplier = + NewTimeouts->ReadTotalTimeoutMultiplier; + + Extension->Timeouts.ReadTotalTimeoutConstant = + NewTimeouts->ReadTotalTimeoutConstant; + + Extension->Timeouts.WriteTotalTimeoutMultiplier = + NewTimeouts->WriteTotalTimeoutMultiplier; + + Extension->Timeouts.WriteTotalTimeoutConstant = + NewTimeouts->WriteTotalTimeoutConstant; + + break; + } + case IOCTL_SERIAL_GET_TIMEOUTS: { + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_TIMEOUTS), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + *((PSERIAL_TIMEOUTS)buffer) = Extension->Timeouts; + reqContext->Information = sizeof(SERIAL_TIMEOUTS); + + break; + } + case IOCTL_SERIAL_SET_CHARS: { + + SERIAL_IOCTL_SYNC S; + PSERIAL_CHARS NewChars; + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_CHARS), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + NewChars = (PSERIAL_CHARS)buffer; + + // + // The only thing that can be wrong with the chars + // is that the xon and xoff characters are the + // same. + // +#if 0 + if (NewChars->XonChar == NewChars->XoffChar) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } +#endif + + // + // We acquire the control lock so that only + // one request can GET or SET the characters + // at a time. The sets could be synchronized + // by the interrupt spinlock, but that wouldn't + // prevent multiple gets at the same time. + // + + S.Extension = Extension; + S.Data = NewChars; + + // + // Under the protection of the lock, make sure that + // the xon and xoff characters aren't the same as + // the escape character. + // + + if (Extension->EscapeChar) { + + if ((Extension->EscapeChar == NewChars->XonChar) || + (Extension->EscapeChar == NewChars->XoffChar)) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + } + + Extension->WmiCommData.XonCharacter = NewChars->XonChar; + Extension->WmiCommData.XoffCharacter = NewChars->XoffChar; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetChars, + &S + ); + + + break; + + } + case IOCTL_SERIAL_GET_CHARS: { + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_CHARS), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + *((PSERIAL_CHARS)buffer) = Extension->SpecialChars; + reqContext->Information = sizeof(SERIAL_CHARS); + + + break; + } + case IOCTL_SERIAL_SET_DTR: + case IOCTL_SERIAL_CLR_DTR: { + + + // + // We acquire the lock so that we can check whether + // automatic dtr flow control is enabled. If it is + // then we return an error since the app is not allowed + // to touch this if it is automatic. + // + + if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) + == SERIAL_DTR_HANDSHAKE) { + + Status = STATUS_INVALID_PARAMETER; + + } else { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + ((IoControlCode == + IOCTL_SERIAL_SET_DTR)? + (SerialSetDTR):(SerialClrDTR)), + Extension + ); + + } + + break; + } + case IOCTL_SERIAL_RESET_DEVICE: { + + break; + } + case IOCTL_SERIAL_SET_RTS: + case IOCTL_SERIAL_CLR_RTS: { + + // + // We acquire the lock so that we can check whether + // automatic rts flow control or transmit toggleing + // is enabled. If it is then we return an error since + // the app is not allowed to touch this if it is automatic + // or toggling. + // + + if (((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) + == SERIAL_RTS_HANDSHAKE) || + ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) + == SERIAL_TRANSMIT_TOGGLE)) { + + Status = STATUS_INVALID_PARAMETER; + + } else { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + ((IoControlCode == + IOCTL_SERIAL_SET_RTS)? + (SerialSetRTS):(SerialClrRTS)), + Extension + ); + + } + + break; + + } + case IOCTL_SERIAL_SET_XOFF: { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialPretendXoff, + Extension + ); + + break; + + } + case IOCTL_SERIAL_SET_XON: { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialPretendXon, + Extension + ); + + break; + + } + case IOCTL_SERIAL_SET_BREAK_ON: { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialTurnOnBreak, + Extension + ); + + break; + } + case IOCTL_SERIAL_SET_BREAK_OFF: { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialTurnOffBreak, + Extension + ); + + break; + } + case IOCTL_SERIAL_SET_QUEUE_SIZE: { + + // + // Type ahead buffer is fixed, so we just validate + // the the users request is not bigger that our + // own internal buffer size. + // + + PSERIAL_QUEUE_SIZE Rs; + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_QUEUE_SIZE), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + ASSERT(Extension->InterruptReadBuffer); + + Rs = (PSERIAL_QUEUE_SIZE)buffer; + + reqContext->SystemBuffer = buffer; + + // + // We have to allocate the memory for the new + // buffer while we're still in the context of the + // caller. We don't even try to protect this + // with a lock because the value could be stale + // as soon as we release the lock - The only time + // we will know for sure is when we actually try + // to do the resize. + // + + if (Rs->InSize <= Extension->BufferSize) { + + Status = STATUS_SUCCESS; + break; + + } + + reqContext->Type3InputBuffer = + ExAllocatePoolWithQuotaTag( + NonPagedPoolNx | POOL_QUOTA_FAIL_INSTEAD_OF_RAISE, + Rs->InSize, + POOL_TAG + ); + + if (!reqContext->Type3InputBuffer) { + + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + + } + + // + // Well the data passed was big enough. Do the request. + // + // There are two reason we place it in the read queue: + // + // 1) We want to serialize these resize requests so that + // they don't contend with each other. + // + // 2) We want to serialize these requests with reads since + // we don't want reads and resizes contending over the + // read buffer. + // + + + SerialStartOrQueue( + Extension, + Request, + Extension->ReadQueue, + &Extension->CurrentReadRequest, + SerialStartRead + ); + + return; + } + case IOCTL_SERIAL_GET_WAIT_MASK: { + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + // + // Simple scalar read. No reason to acquire a lock. + // + + reqContext->Information = sizeof(ULONG); + + *((ULONG *)buffer) = Extension->IsrWaitMask; + + break; + + } + case IOCTL_SERIAL_SET_WAIT_MASK: { + + ULONG NewMask; + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "In Ioctl processing for set mask\n"); + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + NewMask = *((ULONG *)buffer); + reqContext->SystemBuffer = buffer; + + // + // Make sure that the mask only contains valid + // waitable events. + // + + if (NewMask & ~(SERIAL_EV_RXCHAR | + SERIAL_EV_RXFLAG | + SERIAL_EV_TXEMPTY | + SERIAL_EV_CTS | + SERIAL_EV_DSR | + SERIAL_EV_RLSD | + SERIAL_EV_BREAK | + SERIAL_EV_ERR | + SERIAL_EV_RING | + SERIAL_EV_PERR | + SERIAL_EV_RX80FULL | + SERIAL_EV_EVENT1 | + SERIAL_EV_EVENT2)) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Unknown mask %x\n", NewMask); + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + // + // Either start this request or put it on the + // queue. + // + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Starting or queuing set mask request %p" + "\n", Request); + + SerialStartOrQueue(Extension, Request, Extension->MaskQueue, + &Extension->CurrentMaskRequest, + SerialStartMask); + return; + + } + case IOCTL_SERIAL_WAIT_ON_MASK: { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "In Ioctl processing for wait mask\n"); + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->SystemBuffer = buffer; + + // + // Either start this request or put it on the + // queue. + // + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Starting or queuing wait mask request" + "%p\n", Request); + + SerialStartOrQueue( + Extension, + Request, + Extension->MaskQueue, + &Extension->CurrentMaskRequest, + SerialStartMask + ); + return; + } + case IOCTL_SERIAL_IMMEDIATE_CHAR: { + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(UCHAR), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->SystemBuffer = buffer; + + if (Extension->CurrentImmediateRequest) { + + Status = STATUS_INVALID_PARAMETER; + + } else { + + // + // We can queue the char. We need to set + // a cancel routine because flow control could + // keep the char from transmitting. Make sure + // that the request hasn't already been canceled. + // + + Extension->CurrentImmediateRequest = Request; + Extension->TotalCharsQueued++; + SerialStartImmediate(Extension); + return; + + } + + break; + + } + case IOCTL_SERIAL_PURGE: { + + ULONG Mask; + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + // + // Check to make sure that the mask only has + // 0 or the other appropriate values. + // + + Mask = *((ULONG *)(buffer)); + + if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT | + SERIAL_PURGE_RXABORT | + SERIAL_PURGE_TXCLEAR | + SERIAL_PURGE_RXCLEAR + ) + ) + )) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + reqContext->SystemBuffer = buffer; + + // + // Either start this request or put it on the + // queue. + // + + SerialStartOrQueue( + Extension, + Request, + Extension->PurgeQueue, + &Extension->CurrentPurgeRequest, + SerialStartPurge + ); + return; + } + case IOCTL_SERIAL_GET_HANDFLOW: { + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_HANDFLOW), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->Information = sizeof(SERIAL_HANDFLOW); + + *((PSERIAL_HANDFLOW)buffer) = Extension->HandFlow; + + break; + + } + case IOCTL_SERIAL_SET_HANDFLOW: { + + SERIAL_IOCTL_SYNC S; + PSERIAL_HANDFLOW HandFlow; + + // + // Make sure that the hand shake and control is the + // right size. + // + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_HANDFLOW), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + HandFlow = (PSERIAL_HANDFLOW)buffer; + + // + // Make sure that there are no invalid bits set in + // the control and handshake. + // + + if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + // + // Make sure that the app hasn't set an invlid DTR mode. + // + + if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) == + SERIAL_DTR_MASK) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + // + // Make sure that haven't set totally invalid xon/xoff + // limits. + // + + if ((HandFlow->XonLimit < 0) || + ((ULONG)HandFlow->XonLimit > Extension->BufferSize)) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + if ((HandFlow->XoffLimit < 0) || + ((ULONG)HandFlow->XoffLimit > Extension->BufferSize)) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + S.Extension = Extension; + S.Data = HandFlow; + + // + // Under the protection of the lock, make sure that + // we aren't turning on error replacement when we + // are doing line status/modem status insertion. + // + + if (Extension->EscapeChar) { + + if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + + } + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetHandFlow, + &S + ); + + break; + + } + case IOCTL_SERIAL_GET_MODEMSTATUS: { + + SERIAL_IOCTL_SYNC S; + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->Information = sizeof(ULONG); + + S.Extension = Extension; + S.Data = buffer; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGetModemUpdate, + &S + ); + + break; + + } + case IOCTL_SERIAL_GET_DTRRTS: { + + ULONG ModemControl; + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->Information = sizeof(ULONG); + reqContext->Status = STATUS_SUCCESS; + + // + // Reading this hardware has no effect on the device. + // + + ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); + + ModemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE; + + *(PULONG)buffer = ModemControl; + + break; + + } + case IOCTL_SERIAL_GET_COMMSTATUS: { + + SERIAL_IOCTL_SYNC S; + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_STATUS), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->Information = sizeof(SERIAL_STATUS); + + S.Extension = Extension; + S.Data = buffer; + + // + // Acquire the cancel spin lock so nothing much + // changes while were getting the state. + // + + //IoAcquireCancelSpinLock(&OldIrql); + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGetCommStatus, + &S + ); + + //IoReleaseCancelSpinLock(OldIrql); + + break; + + } + case IOCTL_SERIAL_GET_PROPERTIES: { + + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_COMMPROP), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + // + // No synchronization is required since this information + // is "static". + // + + SerialGetProperties( + Extension, + buffer + ); + + reqContext->Information = sizeof(SERIAL_COMMPROP); + reqContext->Status = STATUS_SUCCESS; + + break; + } + case IOCTL_SERIAL_XOFF_COUNTER: { + + PSERIAL_XOFF_COUNTER Xc; + + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_XOFF_COUNTER), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + Xc = (PSERIAL_XOFF_COUNTER)buffer; + + if (Xc->Counter <= 0) { + + Status = STATUS_INVALID_PARAMETER; + break; + + } + reqContext->SystemBuffer = buffer; + + // + // There is no output, so make that clear now + // + + reqContext->Information = 0; + + // + // So far so good. Put the request onto the write queue. + // + + SerialStartOrQueue( + Extension, + Request, + Extension->WriteQueue, + &Extension->CurrentWriteRequest, + SerialStartWrite + ); + return; + + } + case IOCTL_SERIAL_LSRMST_INSERT: { + + PUCHAR escapeChar; + SERIAL_IOCTL_SYNC S; + + // + // Make sure we get a byte. + // + Status = WdfRequestRetrieveInputBuffer ( Request, sizeof(UCHAR), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->SystemBuffer = buffer; + + escapeChar = (PUCHAR)buffer; + + if (*escapeChar) { + + // + // We've got some escape work to do. We will make sure that + // the character is not the same as the Xon or Xoff character, + // or that we are already doing error replacement. + // + + if ((*escapeChar == Extension->SpecialChars.XoffChar) || + (*escapeChar == Extension->SpecialChars.XonChar) || + (Extension->HandFlow.FlowReplace & SERIAL_ERROR_CHAR)) { + + Status = STATUS_INVALID_PARAMETER; + + break; + + } + + } + + S.Extension = Extension; + S.Data = buffer; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialSetEscapeChar, + reqContext + ); + + break; + + } + case IOCTL_SERIAL_CONFIG_SIZE: { + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(ULONG), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->Information = sizeof(ULONG); + reqContext->Status = STATUS_SUCCESS; + + *(PULONG)buffer = 0; + + break; + } + case IOCTL_SERIAL_GET_STATS: { + + Status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIALPERF_STATS), &buffer, &bufSize ); + if( !NT_SUCCESS(Status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", Status); + break; + } + + reqContext->SystemBuffer = buffer; + + reqContext->Information = sizeof(SERIALPERF_STATS); + reqContext->Status = STATUS_SUCCESS; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGetStats, + reqContext + ); + + break; + } + case IOCTL_SERIAL_CLEAR_STATS: { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialClearStats, + Extension + ); + break; + } + default: { + + Status = STATUS_INVALID_PARAMETER; + break; + } + } + +DoneWithIoctl:; + + reqContext->Status = Status; + + SerialCompleteRequest(Request, Status, reqContext->Information); + + return; + +} + + +VOID +SerialGetProperties( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN PSERIAL_COMMPROP Properties + ) + +/*++ + +Routine Description: + + This function returns the capabilities of this particular + serial device. + +Arguments: + + Extension - The serial device extension. + + Properties - The structure used to return the properties + +Return Value: + + None. + +--*/ + +{ + + + RtlZeroMemory( + Properties, + sizeof(SERIAL_COMMPROP) + ); + + Properties->PacketLength = sizeof(SERIAL_COMMPROP); + Properties->PacketVersion = 2; + Properties->ServiceMask = SERIAL_SP_SERIALCOMM; + Properties->MaxTxQueue = 0; + Properties->MaxRxQueue = 0; + + Properties->MaxBaud = SERIAL_BAUD_USER; + Properties->SettableBaud = Extension->SupportedBauds; + + Properties->ProvSubType = SERIAL_SP_RS232; + Properties->ProvCapabilities = SERIAL_PCF_DTRDSR | + SERIAL_PCF_RTSCTS | + SERIAL_PCF_CD | + SERIAL_PCF_PARITY_CHECK | + SERIAL_PCF_XONXOFF | + SERIAL_PCF_SETXCHAR | + SERIAL_PCF_TOTALTIMEOUTS | + SERIAL_PCF_INTTIMEOUTS; + Properties->SettableParams = SERIAL_SP_PARITY | + SERIAL_SP_BAUD | + SERIAL_SP_DATABITS | + SERIAL_SP_STOPBITS | + SERIAL_SP_HANDSHAKING | + SERIAL_SP_PARITY_CHECK | + SERIAL_SP_CARRIER_DETECT; + + + Properties->SettableData = SERIAL_DATABITS_5 | + SERIAL_DATABITS_6 | + SERIAL_DATABITS_7 | + SERIAL_DATABITS_8; + Properties->SettableStopParity = SERIAL_STOPBITS_10 | + SERIAL_STOPBITS_15 | + SERIAL_STOPBITS_20 | + SERIAL_PARITY_NONE | + SERIAL_PARITY_ODD | + SERIAL_PARITY_EVEN | + SERIAL_PARITY_MARK | + SERIAL_PARITY_SPACE; + Properties->CurrentTxQueue = 0; + Properties->CurrentRxQueue = Extension->BufferSize; + +} + +VOID +SerialEvtIoInternalDeviceControl( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t OutputBufferLength, + IN size_t InputBufferLength, + IN ULONG IoControlCode +) +/*++ + +Routine Description: + + This routine provides the initial processing for all of the + internal Ioctrls for the serial device. + +Arguments: + + PDevObj - Pointer to the device object for this device + + PIrp - Pointer to the WDFREQUEST for the current request + +Return Value: + + The function value is the final status of the call + +--*/ + +{ + NTSTATUS status; + PSERIAL_DEVICE_EXTENSION pDevExt = NULL; + PVOID buffer; + PREQUEST_CONTEXT reqContext; + WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings; + size_t bufSize; + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "SerialEvtIoInternalDeviceControl for: %p\n", Request); + + pDevExt = SerialGetDeviceExtension(WdfIoQueueGetDevice(Queue)); + + if (SerialCompleteIfError(pDevExt, Request) != STATUS_SUCCESS) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Information = 0; + reqContext->Status = STATUS_SUCCESS; + reqContext->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + + switch (IoControlCode) { + + case IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE: + // + // Init wait-wake policy structure. + // + WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings); + // + // Override the default settings from allow user control to do not allow. + // + wakeSettings.UserControlOfWakeSettings = IdleDoNotAllowUserControl; + status = WdfDeviceAssignSxWakeSettings(pDevExt->WdfDevice, &wakeSettings); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceAssignSxWakeSettings failed %x \n", status); + break; + } + + pDevExt->IsWakeEnabled = TRUE; + status = STATUS_SUCCESS; + break; + + case IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE: + + WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS_INIT(&wakeSettings); + // + // Override the default settings. + // + wakeSettings.Enabled = WdfFalse; // Disables wait-wake + wakeSettings.UserControlOfWakeSettings = IdleDoNotAllowUserControl; + status = WdfDeviceAssignSxWakeSettings(pDevExt->WdfDevice, &wakeSettings); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDeviceAssignSxWakeSettings failed %x \n", status); + break; + } + + pDevExt->IsWakeEnabled = FALSE; + status = STATUS_SUCCESS; + break; + + + // + // Put the serial port in a "filter-driver" appropriate state + // + // WARNING: This code assumes it is being called by a trusted kernel + // entity and no checking is done on the validity of the settings + // passed to IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS + // + // If validity checking is desired, the regular ioctl's should be used + // + + case IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS: + case IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS: { + + SERIAL_BASIC_SETTINGS basic; + PSERIAL_BASIC_SETTINGS pBasic; + SERIAL_IOCTL_SYNC S; + + if (IoControlCode == IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS) { + + + // + // Check the buffer size + // + status = WdfRequestRetrieveOutputBuffer ( Request, sizeof(SERIAL_BASIC_SETTINGS), &buffer, &bufSize ); + if( !NT_SUCCESS(status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", status); + break; + } + + reqContext->SystemBuffer = buffer; + + // + // Everything is 0 -- timeouts and flow control and fifos. If + // We add additional features, this zero memory method + // may not work. + // + + RtlZeroMemory(&basic, sizeof(SERIAL_BASIC_SETTINGS)); + + basic.TxFifo = 1; + basic.RxFifo = SERIAL_1_BYTE_HIGH_WATER; + + reqContext->Information = sizeof(SERIAL_BASIC_SETTINGS); + pBasic = (PSERIAL_BASIC_SETTINGS)buffer; + + // + // Save off the old settings + // + + RtlCopyMemory(&pBasic->Timeouts, &pDevExt->Timeouts, + sizeof(SERIAL_TIMEOUTS)); + + RtlCopyMemory(&pBasic->HandFlow, &pDevExt->HandFlow, + sizeof(SERIAL_HANDFLOW)); + + pBasic->RxFifo = pDevExt->RxFifoTrigger; + pBasic->TxFifo = pDevExt->TxFifoAmount; + + // + // Point to our new settings + // + + pBasic = &basic; + } else { // restoring settings + + status = WdfRequestRetrieveInputBuffer ( Request, sizeof(SERIAL_BASIC_SETTINGS), &buffer, &bufSize ); + if( !NT_SUCCESS(status) ) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_IOCTLS, "Could not get request memory buffer %X\n", status); + break; + } + + pBasic = (PSERIAL_BASIC_SETTINGS)buffer; + } + + // + // Set the timeouts + // + + RtlCopyMemory(&pDevExt->Timeouts, &pBasic->Timeouts, + sizeof(SERIAL_TIMEOUTS)); + + // + // Set flowcontrol + // + + S.Extension = pDevExt; + S.Data = &pBasic->HandFlow; + WdfInterruptSynchronize(pDevExt->WdfInterrupt, SerialSetHandFlow, &S); + + if (pDevExt->FifoPresent) { + pDevExt->TxFifoAmount = pBasic->TxFifo; + pDevExt->RxFifoTrigger = (UCHAR)pBasic->RxFifo; + + WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, (UCHAR)0); + READ_RECEIVE_BUFFER(pDevExt, pDevExt->Controller); + WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, + (UCHAR)(SERIAL_FCR_ENABLE | pDevExt->RxFifoTrigger + | SERIAL_FCR_RCVR_RESET + | SERIAL_FCR_TXMT_RESET)); + } else { + pDevExt->TxFifoAmount = pDevExt->RxFifoTrigger = 0; + WRITE_FIFO_CONTROL(pDevExt, pDevExt->Controller, (UCHAR)0); + } + + + break; + } + + default: + status = STATUS_INVALID_PARAMETER; + break; + + } + + reqContext->Status = status; + + SerialCompleteRequest(Request, reqContext->Status, reqContext->Information); + + return; +} + + + diff --git a/tests/projects/windows/driver/kmdf/serial/isr.c b/tests/projects/windows/driver/kmdf/serial/isr.c new file mode 100644 index 000000000..806164a61 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/isr.c @@ -0,0 +1,1517 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + isr.c + +Abstract: + + This module contains the interrupt service routine for the + serial driver. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "isr.tmh" +#endif + + +NTSTATUS +SerialEvtInterruptEnable( + IN WDFINTERRUPT Interrupt, + IN WDFDEVICE AssociatedDevice + ) +/*++ + +Routine Description: + + This event is called when the Framework moves the device to D0, and after + EvtDeviceD0Entry. The driver should enable its interrupt here. + + This function will be called at the device's assigned interrupt + IRQL (DIRQL.) + +Arguments: + + Interrupt - Handle to a Framework interrupt object. + + AssociatedDevice - Handle to a Framework device object. + +Return Value: + + BOOLEAN - TRUE indicates that the interrupt was successfully enabled. + +--*/ +{ + UNREFERENCED_PARAMETER(Interrupt); + UNREFERENCED_PARAMETER(AssociatedDevice); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "--> SerialEvtInterruptEnable\n"); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- SerialEvtInterruptEnable\n"); + + return STATUS_SUCCESS; +} + +NTSTATUS +SerialEvtInterruptDisable( + IN WDFINTERRUPT Interrupt, + IN WDFDEVICE AssociatedDevice + ) +/*++ + +Routine Description: + + This event is called before the Framework moves the device to D1, D2 or D3 + and before EvtDeviceD0Exit. The driver should disable its interrupt here. + + This function will be called at the device's assigned interrupt + IRQL (DIRQL.) + +Arguments: + + Interrupt - Handle to a Framework interrupt object. + + AssociatedDevice - Handle to a Framework device object. + +Return Value: + + BOOLEAN - TRUE indicates that the interrupt was successfully disabled. + +--*/ +{ + UNREFERENCED_PARAMETER(Interrupt); + UNREFERENCED_PARAMETER(AssociatedDevice); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "--> SerialEvtInterruptDisable\n"); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "<-- SerialEvtInterruptDisable\n"); + + return STATUS_SUCCESS; +} + +BOOLEAN +SerialISR( + IN WDFINTERRUPT Interrupt, + IN ULONG MessageID + ) + +/*++ + +Routine Description: + + This is the interrupt service routine for the serial port driver. + It will determine whether the serial port is the source of this + interrupt. If it is, then this routine will do the minimum of + processing to quiet the interrupt. It will store any information + necessary for later processing. + +Arguments: + + InterruptObject - Points to the interrupt object declared for this + device. We *do not* use this parameter. + + +Return Value: + + This function will return TRUE if the serial port is the source + of this interrupt, FALSE otherwise. + +--*/ + +{ + // + // Holds the information specific to handling this device. + // + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + // + // Holds the contents of the interrupt identification record. + // A low bit of zero in this register indicates that there is + // an interrupt pending on this device. + // + UCHAR InterruptIdReg; + + // + // Will hold whether we've serviced any interrupt causes in this + // routine. + // + BOOLEAN ServicedAnInterrupt; + + UCHAR tempLSR; + PREQUEST_CONTEXT reqContext = NULL; + + UNREFERENCED_PARAMETER(MessageID); + + Extension = SerialGetDeviceExtension(WdfInterruptGetDevice(Interrupt)); + + // + // Make sure we have an interrupt pending. If we do then + // we need to make sure that the device is open. If the + // device isn't open or powered down then quiet the device. Note that + // if the device isn't opened when we enter this routine + // it can't open while we're in it. + // + + InterruptIdReg = READ_INTERRUPT_ID_REG(Extension, Extension->Controller); + + if ((InterruptIdReg & SERIAL_IIR_NO_INTERRUPT_PENDING)) { + + ServicedAnInterrupt = FALSE; + + } else if (!Extension->DeviceIsOpened/* + || (Extension->PowerState != PowerDeviceD0)*/) { + + + // + // We got an interrupt with the device being closed or when the + // device is supposed to be powered down. This + // is not unlikely with a serial device. We just quietly + // keep servicing the causes until it calms down. + // + + ServicedAnInterrupt = TRUE; + do { + + InterruptIdReg &= (~SERIAL_IIR_FIFOS_ENABLED); + switch (InterruptIdReg) { + + case SERIAL_IIR_RLS: { + + READ_LINE_STATUS(Extension, Extension->Controller); + + break; + + } + + case SERIAL_IIR_RDA: + case SERIAL_IIR_CTI: { + + READ_RECEIVE_BUFFER(Extension, Extension->Controller); + + break; + + } + + case SERIAL_IIR_THR: { + + // + // Alread clear from reading the iir. + // + // We want to keep close track of whether + // the holding register is empty. + // + + Extension->HoldingEmpty = TRUE; + break; + + } + + case SERIAL_IIR_MS: { + + READ_MODEM_STATUS(Extension, Extension->Controller); + break; + + } + + default: { + + ASSERT(FALSE); + break; + + } + + } + + } while (!((InterruptIdReg = + READ_INTERRUPT_ID_REG(Extension, Extension->Controller)) + & SERIAL_IIR_NO_INTERRUPT_PENDING)); + + } else { + + ServicedAnInterrupt = TRUE; + do { + + // + // We only care about bits that can denote an interrupt. + // + + InterruptIdReg &= SERIAL_IIR_RLS | SERIAL_IIR_RDA | + SERIAL_IIR_CTI | SERIAL_IIR_THR | + SERIAL_IIR_MS; + + // + // We have an interrupt. We look for interrupt causes + // in priority order. The presence of a higher interrupt + // will mask out causes of a lower priority. When we service + // and quiet a higher priority interrupt we then need to check + // the interrupt causes to see if a new interrupt cause is + // present. + // + + switch (InterruptIdReg) { + + case SERIAL_IIR_RLS: { + + SerialProcessLSR(Extension); + + break; + + } + + case SERIAL_IIR_RDA: + case SERIAL_IIR_CTI: + + { + + // + // Reading the receive buffer will quiet this interrupt. + // + // It may also reveal a new interrupt cause. + // + UCHAR ReceivedChar; + + do { + + ReceivedChar = + READ_RECEIVE_BUFFER(Extension, Extension->Controller); + Extension->PerfStats.ReceivedCount++; + Extension->WmiPerfData.ReceivedCount++; + + ReceivedChar &= Extension->ValidDataMask; + + if (!ReceivedChar && + (Extension->HandFlow.FlowReplace & + SERIAL_NULL_STRIPPING)) { + + // + // If what we got is a null character + // and we're doing null stripping, then + // we simply act as if we didn't see it. + // + + goto ReceiveDoLineStatus; + + } + + if ((Extension->HandFlow.FlowReplace & + SERIAL_AUTO_TRANSMIT) && + ((ReceivedChar == + Extension->SpecialChars.XonChar) || + (ReceivedChar == + Extension->SpecialChars.XoffChar))) { + + // + // No matter what happens this character + // will never get seen by the app. + // + + if (ReceivedChar == + Extension->SpecialChars.XoffChar) { + + Extension->TXHolding |= SERIAL_TX_XOFF; + + if ((Extension->HandFlow.FlowReplace & + SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } + + + } else { + + if (Extension->TXHolding & SERIAL_TX_XOFF) { + + // + // We got the xon char **AND*** we + // were being held up on transmission + // by xoff. Clear that we are holding + // due to xoff. Transmission will + // automatically restart because of + // the code outside the main loop that + // catches problems chips like the + // SMC and the Winbond. + // + + Extension->TXHolding &= ~SERIAL_TX_XOFF; + + } + + } + + goto ReceiveDoLineStatus; + + } + + // + // Check to see if we should note + // the receive character or special + // character event. + // + + if (Extension->IsrWaitMask) { + + if (Extension->IsrWaitMask & + SERIAL_EV_RXCHAR) { + + Extension->HistoryMask |= SERIAL_EV_RXCHAR; + + } + + if ((Extension->IsrWaitMask & + SERIAL_EV_RXFLAG) && + (Extension->SpecialChars.EventChar == + ReceivedChar)) { + + Extension->HistoryMask |= SERIAL_EV_RXFLAG; + + } + + if (Extension->IrpMaskLocation && + Extension->HistoryMask) { + + *Extension->IrpMaskLocation = + Extension->HistoryMask; + Extension->IrpMaskLocation = NULL; + Extension->HistoryMask = 0; + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + reqContext->Information = sizeof(ULONG); + SerialInsertQueueDpc( + Extension->CommWaitDpc + ); + + } + + } + + SerialPutChar( + Extension, + ReceivedChar + ); + + // + // If we're doing line status and modem + // status insertion then we need to insert + // a zero following the character we just + // placed into the buffer to mark that this + // was reception of what we are using to + // escape. + // + + if (Extension->EscapeChar && + (Extension->EscapeChar == + ReceivedChar)) { + + SerialPutChar( + Extension, + SERIAL_LSRMST_ESCAPE + ); + + } + + +ReceiveDoLineStatus: ; + // + // This reads the interrupt ID register and detemines if bits are 0 + // If either of the reserved bits are 1, we stop servicing interrupts + // Since this detection method is not guarenteed this is enabled via + // a registry entry "UartDetectRemoval" and intialized on DriverEntry. + // This is disabled by default and will only be enabled on Stratus systems + // that allow hot replacement of serial cards + // + if(Extension->UartRemovalDetect) + { + UCHAR DetectRemoval; + + DetectRemoval = READ_INTERRUPT_ID_REG(Extension, Extension->Controller); + + if(DetectRemoval & SERIAL_IIR_MUST_BE_ZERO) + { + // break out of this loop and stop processing interrupts + break; + } + } + + if (!((tempLSR = SerialProcessLSR(Extension)) & + SERIAL_LSR_DR)) { + + // + // No more characters, get out of the + // loop. + // + + break; + + } + + if ((tempLSR & ~(SERIAL_LSR_THRE | SERIAL_LSR_TEMT | + SERIAL_LSR_DR)) && + Extension->EscapeChar) { + + // + // An error was indicated and inserted into the + // stream, get out of the loop. + // + + break; + } + + } WHILE (TRUE); + + break; + + } + + case SERIAL_IIR_THR: { + +doTrasmitStuff:; + Extension->HoldingEmpty = TRUE; + + if (Extension->WriteLength || + Extension->TransmitImmediate || + Extension->SendXoffChar || + Extension->SendXonChar) { + + // + // Even though all of the characters being + // sent haven't all been sent, this variable + // will be checked when the transmit queue is + // empty. If it is still true and there is a + // wait on the transmit queue being empty then + // we know we finished transmitting all characters + // following the initiation of the wait since + // the code that initiates the wait will set + // this variable to false. + // + // One reason it could be false is that + // the writes were cancelled before they + // actually started, or that the writes + // failed due to timeouts. This variable + // basically says a character was written + // by the isr at some point following the + // initiation of the wait. + // + + Extension->EmptiedTransmit = TRUE; + + // + // If we have output flow control based on + // the modem status lines, then we have to do + // all the modem work before we output each + // character. (Otherwise we might miss a + // status line change.) + // + + if (Extension->HandFlow.ControlHandShake & + SERIAL_OUT_HANDSHAKEMASK) { + + SerialHandleModemUpdate( + Extension, + TRUE + ); + + } + + // + // We can only send the xon character if + // the only reason we are holding is because + // of the xoff. (Hardware flow control or + // sending break preclude putting a new character + // on the wire.) + // + + if (Extension->SendXonChar && + !(Extension->TXHolding & ~SERIAL_TX_XOFF)) { + + if ((Extension->HandFlow.FlowReplace & + SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + // + // We have to raise if we're sending + // this character. + // + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + + WRITE_TRANSMIT_HOLDING(Extension, Extension->Controller, + Extension->SpecialChars.XonChar); + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + + } else { + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + Extension->SpecialChars.XonChar); + } + + + Extension->SendXonChar = FALSE; + Extension->HoldingEmpty = FALSE; + + // + // If we send an xon, by definition we + // can't be holding by Xoff. + // + + Extension->TXHolding &= ~SERIAL_TX_XOFF; + + // + // If we are sending an xon char then + // by definition we can't be "holding" + // up reception by Xoff. + // + + Extension->RXHolding &= ~SERIAL_RX_XOFF; + + } else if (Extension->SendXoffChar && + !Extension->TXHolding) { + + if ((Extension->HandFlow.FlowReplace & + SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + // + // We have to raise if we're sending + // this character. + // + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + Extension->SpecialChars.XoffChar); + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } else { + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + Extension->SpecialChars.XoffChar); + + } + + // + // We can't be sending an Xoff character + // if the transmission is already held + // up because of Xoff. Therefore, if we + // are holding then we can't send the char. + // + + // + // If the application has set xoff continue + // mode then we don't actually stop sending + // characters if we send an xoff to the other + // side. + // + + if (!(Extension->HandFlow.FlowReplace & + SERIAL_XOFF_CONTINUE)) { + + Extension->TXHolding |= SERIAL_TX_XOFF; + + if ((Extension->HandFlow.FlowReplace & + SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } + + } + + Extension->SendXoffChar = FALSE; + Extension->HoldingEmpty = FALSE; + + // + // Even if transmission is being held + // up, we should still transmit an immediate + // character if all that is holding us + // up is xon/xoff (OS/2 rules). + // + + } else if (Extension->TransmitImmediate && + (!Extension->TXHolding || + (Extension->TXHolding == SERIAL_TX_XOFF) + )) { + + Extension->TransmitImmediate = FALSE; + + if ((Extension->HandFlow.FlowReplace & + SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + // + // We have to raise if we're sending + // this character. + // + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + Extension->ImmediateChar); + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } else { + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + Extension->ImmediateChar); + + } + + Extension->HoldingEmpty = FALSE; + + SerialInsertQueueDpc( + Extension->CompleteImmediateDpc + ); + + } else if (!Extension->TXHolding) { + + ULONG amountToWrite; + + if (Extension->FifoPresent) { + + amountToWrite = (Extension->TxFifoAmount < + Extension->WriteLength)? + Extension->TxFifoAmount: + Extension->WriteLength; + + } else { + + amountToWrite = 1; + + } + if ((Extension->HandFlow.FlowReplace & + SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + // + // We have to raise if we're sending + // this character. + // + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + if (amountToWrite == 1) { + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + *(Extension->WriteCurrentChar)); + + } else { + + Extension->PerfStats.TransmittedCount += + amountToWrite; + Extension->WmiPerfData.TransmittedCount += + amountToWrite; + WRITE_TRANSMIT_FIFO_HOLDING(Extension, + Extension->Controller, + Extension->WriteCurrentChar, + amountToWrite); + } + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } else { + + if (amountToWrite == 1) { + + Extension->PerfStats.TransmittedCount++; + Extension->WmiPerfData.TransmittedCount++; + WRITE_TRANSMIT_HOLDING(Extension, + Extension->Controller, + *(Extension->WriteCurrentChar)); + + } else { + + Extension->PerfStats.TransmittedCount += + amountToWrite; + Extension->WmiPerfData.TransmittedCount += + amountToWrite; + WRITE_TRANSMIT_FIFO_HOLDING(Extension, + Extension->Controller, + Extension->WriteCurrentChar, + amountToWrite); + + } + + } + + Extension->HoldingEmpty = FALSE; + Extension->WriteCurrentChar += amountToWrite; + Extension->WriteLength -= amountToWrite; + + if (!Extension->WriteLength) { + + // + // No More characters left. This + // write is complete. Take care + // when updating the information field, + // we could have an xoff counter masquerading + // as a write request. + // + reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); + + reqContext->Information = + (reqContext->MajorFunction == IRP_MJ_WRITE)? + (reqContext->Length): (1); + + SerialInsertQueueDpc( + Extension->CompleteWriteDpc + ); + + } + + } + + } + + break; + + } + + case SERIAL_IIR_MS: { + + SerialHandleModemUpdate( + Extension, + FALSE + ); + + break; + + } + + } + + } while (!((InterruptIdReg = + READ_INTERRUPT_ID_REG(Extension, Extension->Controller)) + & SERIAL_IIR_NO_INTERRUPT_PENDING)); + + // + // Besides catching the WINBOND and SMC chip problems this + // will also cause transmission to restart incase of an xon + // char being received. Don't remove. + // + + if (SerialProcessLSR(Extension) & SERIAL_LSR_THRE) { + + if (!Extension->TXHolding && + (Extension->WriteLength || + Extension->TransmitImmediate)) { + + goto doTrasmitStuff; + + } + + } + + } + + return ServicedAnInterrupt; + +} + +VOID +SerialPutChar( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN UCHAR CharToPut + ) + +/*++ + +Routine Description: + + This routine, which only runs at device level, takes care of + placing a character into the typeahead (receive) buffer. + +Arguments: + + Extension - The serial device extension. + +Return Value: + + None. + +--*/ + +{ + PREQUEST_CONTEXT reqContext = NULL; + + // + // If we have dsr sensitivity enabled then + // we need to check the modem status register + // to see if it has changed. + // + + if (Extension->HandFlow.ControlHandShake & + SERIAL_DSR_SENSITIVITY) { + + SerialHandleModemUpdate( + Extension, + FALSE + ); + + if (Extension->RXHolding & SERIAL_RX_DSR) { + + // + // We simply act as if we haven't + // seen the character if we have dsr + // sensitivity and the dsr line is low. + // + + return; + + } + + } + + // + // If the xoff counter is non-zero then decrement it. + // If the counter then goes to zero, complete that request. + // + + if (Extension->CountSinceXoff) { + + Extension->CountSinceXoff--; + + if (!Extension->CountSinceXoff) { + reqContext = SerialGetRequestContext(Extension->CurrentXoffRequest); + reqContext->Status = STATUS_SUCCESS; + reqContext->Information = 0; + SerialInsertQueueDpc( + Extension->XoffCountCompleteDpc + ); + + } + + } + + // + // Check to see if we are copying into the + // users buffer or into the interrupt buffer. + // + // If we are copying into the user buffer + // then we know there is always room for one more. + // (We know this because if there wasn't room + // then that read would have completed and we + // would be using the interrupt buffer.) + // + // If we are copying into the interrupt buffer + // then we will need to check if we have enough + // room. + // + + if (Extension->ReadBufferBase != + Extension->InterruptReadBuffer) { + + // + // Increment the following value so + // that the interval timer (if one exists + // for this read) can know that a character + // has been read. + // + + Extension->ReadByIsr++; + + // + // We are in the user buffer. Place the + // character into the buffer. See if the + // read is complete. + // + + *Extension->CurrentCharSlot = CharToPut; + + if (Extension->CurrentCharSlot == + Extension->LastCharSlot) { + + // + // We've filled up the users buffer. + // Switch back to the interrupt buffer + // and send off a DPC to Complete the read. + // + // It is inherent that when we were using + // a user buffer that the interrupt buffer + // was empty. + // + + Extension->ReadBufferBase = + Extension->InterruptReadBuffer; + Extension->CurrentCharSlot = + Extension->InterruptReadBuffer; + Extension->FirstReadableChar = + Extension->InterruptReadBuffer; + Extension->LastCharSlot = + Extension->InterruptReadBuffer + + (Extension->BufferSize - 1); + Extension->CharsInInterruptBuffer = 0; + reqContext = SerialGetRequestContext(Extension->CurrentReadRequest); + reqContext->Information = reqContext->Length; + + SerialInsertQueueDpc( + Extension->CompleteReadDpc + ); + + } else { + + // + // Not done with the users read. + // + + Extension->CurrentCharSlot++; + + } + + } else { + + // + // We need to see if we reached our flow + // control threshold. If we have then + // we turn on whatever flow control the + // owner has specified. If no flow + // control was specified, well..., we keep + // trying to receive characters and hope that + // we have enough room. Note that no matter + // what flow control protocol we are using, it + // will not prevent us from reading whatever + // characters are available. + // + + if ((Extension->HandFlow.ControlHandShake + & SERIAL_DTR_MASK) == + SERIAL_DTR_HANDSHAKE) { + + // + // If we are already doing a + // dtr hold then we don't have + // to do anything else. + // + + if (!(Extension->RXHolding & + SERIAL_RX_DTR)) { + + if ((Extension->BufferSize - + Extension->HandFlow.XoffLimit) + <= (Extension->CharsInInterruptBuffer+1)) { + + Extension->RXHolding |= SERIAL_RX_DTR; + + SerialClrDTR(Extension->WdfInterrupt, Extension); + + } + + } + + } + + if ((Extension->HandFlow.FlowReplace + & SERIAL_RTS_MASK) == + SERIAL_RTS_HANDSHAKE) { + + // + // If we are already doing a + // rts hold then we don't have + // to do anything else. + // + + if (!(Extension->RXHolding & + SERIAL_RX_RTS)) { + + if ((Extension->BufferSize - + Extension->HandFlow.XoffLimit) + <= (Extension->CharsInInterruptBuffer+1)) { + + Extension->RXHolding |= SERIAL_RX_RTS; + + SerialClrRTS(Extension->WdfInterrupt, Extension); + + } + + } + + } + + if (Extension->HandFlow.FlowReplace & + SERIAL_AUTO_RECEIVE) { + + // + // If we are already doing a + // xoff hold then we don't have + // to do anything else. + // + + if (!(Extension->RXHolding & + SERIAL_RX_XOFF)) { + + if ((Extension->BufferSize - + Extension->HandFlow.XoffLimit) + <= (Extension->CharsInInterruptBuffer+1)) { + + Extension->RXHolding |= SERIAL_RX_XOFF; + + // + // If necessary cause an + // off to be sent. + // + + SerialProdXonXoff( + Extension, + FALSE + ); + + } + + } + + } + + if (Extension->CharsInInterruptBuffer < + Extension->BufferSize) { + + *Extension->CurrentCharSlot = CharToPut; + Extension->CharsInInterruptBuffer++; + + // + // If we've become 80% full on this character + // and this is an interesting event, note it. + // + + if (Extension->CharsInInterruptBuffer == + Extension->BufferSizePt8) { + + if (Extension->IsrWaitMask & + SERIAL_EV_RX80FULL) { + + Extension->HistoryMask |= SERIAL_EV_RX80FULL; + + if (Extension->IrpMaskLocation) { + + *Extension->IrpMaskLocation = + Extension->HistoryMask; + Extension->IrpMaskLocation = NULL; + Extension->HistoryMask = 0; + + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + reqContext->Information = sizeof(ULONG); + SerialInsertQueueDpc( + Extension->CommWaitDpc + ); + + } + + } + + } + + // + // Point to the next available space + // for a received character. Make sure + // that we wrap around to the beginning + // of the buffer if this last character + // received was placed at the last slot + // in the buffer. + // + + if (Extension->CurrentCharSlot == + Extension->LastCharSlot) { + + Extension->CurrentCharSlot = + Extension->InterruptReadBuffer; + + } else { + + Extension->CurrentCharSlot++; + + } + + } else { + + // + // We have a new character but no room for it. + // + + Extension->PerfStats.BufferOverrunErrorCount++; + Extension->WmiPerfData.BufferOverrunErrorCount++; + Extension->ErrorWord |= SERIAL_ERROR_QUEUEOVERRUN; + + if (Extension->HandFlow.FlowReplace & + SERIAL_ERROR_CHAR) { + + // + // Place the error character into the last + // valid place for a character. Be careful!, + // that place might not be the previous location! + // + + if (Extension->CurrentCharSlot == + Extension->InterruptReadBuffer) { + + *(Extension->InterruptReadBuffer+ + (Extension->BufferSize-1)) = + Extension->SpecialChars.ErrorChar; + + } else { + + *(Extension->CurrentCharSlot-1) = + Extension->SpecialChars.ErrorChar; + + } + + } + + // + // If the application has requested it, abort all reads + // and writes on an error. + // + + if (Extension->HandFlow.ControlHandShake & + SERIAL_ERROR_ABORT) { + + SerialInsertQueueDpc( + Extension->CommErrorDpc + ); + + } + + } + + } + +} + +UCHAR +SerialProcessLSR( + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + This routine, which only runs at device level, reads the + ISR and totally processes everything that might have + changed. + +Arguments: + + Extension - The serial device extension. + +Return Value: + + The value of the line status register. + +--*/ + +{ + PREQUEST_CONTEXT reqContext = NULL; + + UCHAR LineStatus = READ_LINE_STATUS(Extension, Extension->Controller); + + + Extension->HoldingEmpty = (LineStatus & SERIAL_LSR_THRE) ? TRUE : FALSE; + + // + // If the line status register is just the fact that + // the trasmit registers are empty or a character is + // received then we want to reread the interrupt + // identification register so that we just pick up that. + // + + if (LineStatus & ~(SERIAL_LSR_THRE | SERIAL_LSR_TEMT + | SERIAL_LSR_DR)) { + + // + // We have some sort of data problem in the receive. + // For any of these errors we may abort all current + // reads and writes. + // + // + // If we are inserting the value of the line status + // into the data stream then we should put the escape + // character in now. + // + + if (Extension->EscapeChar) { + + SerialPutChar( + Extension, + Extension->EscapeChar + ); + + SerialPutChar( + Extension, + (UCHAR)((LineStatus & SERIAL_LSR_DR)? + (SERIAL_LSRMST_LSR_DATA):(SERIAL_LSRMST_LSR_NODATA)) + ); + + SerialPutChar( + Extension, + LineStatus + ); + + if (LineStatus & SERIAL_LSR_DR) { + + Extension->PerfStats.ReceivedCount++; + Extension->WmiPerfData.ReceivedCount++; + SerialPutChar( + Extension, + READ_RECEIVE_BUFFER(Extension, Extension->Controller) + ); + + } + + } + + if (LineStatus & SERIAL_LSR_OE) { + + Extension->PerfStats.SerialOverrunErrorCount++; + Extension->WmiPerfData.SerialOverrunErrorCount++; + Extension->ErrorWord |= SERIAL_ERROR_OVERRUN; + + if (Extension->HandFlow.FlowReplace & + SERIAL_ERROR_CHAR) { + + SerialPutChar( + Extension, + Extension->SpecialChars.ErrorChar + ); + + if (LineStatus & SERIAL_LSR_DR) { + + Extension->PerfStats.ReceivedCount++; + Extension->WmiPerfData.ReceivedCount++; + READ_RECEIVE_BUFFER(Extension, Extension->Controller); + + } + + } else { + + if (LineStatus & SERIAL_LSR_DR) { + + Extension->PerfStats.ReceivedCount++; + Extension->WmiPerfData.ReceivedCount++; + SerialPutChar( + Extension, + READ_RECEIVE_BUFFER(Extension, + Extension->Controller + ) + ); + + } + + } + + } + + if (LineStatus & SERIAL_LSR_BI) { + + Extension->ErrorWord |= SERIAL_ERROR_BREAK; + + if (Extension->HandFlow.FlowReplace & + SERIAL_BREAK_CHAR) { + + SerialPutChar( + Extension, + Extension->SpecialChars.BreakChar + ); + + } + + } else { + + // + // Framing errors only count if they + // occur exclusive of a break being + // received. + // + + if (LineStatus & SERIAL_LSR_PE) { + + Extension->PerfStats.ParityErrorCount++; + Extension->WmiPerfData.ParityErrorCount++; + Extension->ErrorWord |= SERIAL_ERROR_PARITY; + + if (Extension->HandFlow.FlowReplace & + SERIAL_ERROR_CHAR) { + + SerialPutChar( + Extension, + Extension->SpecialChars.ErrorChar + ); + + if (LineStatus & SERIAL_LSR_DR) { + + Extension->PerfStats.ReceivedCount++; + Extension->WmiPerfData.ReceivedCount++; + READ_RECEIVE_BUFFER(Extension, Extension->Controller); + + } + + } + + } + + if (LineStatus & SERIAL_LSR_FE) { + + Extension->PerfStats.FrameErrorCount++; + Extension->WmiPerfData.FrameErrorCount++; + Extension->ErrorWord |= SERIAL_ERROR_FRAMING; + + if (Extension->HandFlow.FlowReplace & + SERIAL_ERROR_CHAR) { + + SerialPutChar( + Extension, + Extension->SpecialChars.ErrorChar + ); + if (LineStatus & SERIAL_LSR_DR) { + + Extension->PerfStats.ReceivedCount++; + Extension->WmiPerfData.ReceivedCount++; + READ_RECEIVE_BUFFER(Extension, Extension->Controller); + + } + + } + + } + + } + + // + // If the application has requested it, + // abort all the reads and writes + // on an error. + // + + if (Extension->HandFlow.ControlHandShake & + SERIAL_ERROR_ABORT) { + + SerialInsertQueueDpc( + Extension->CommErrorDpc + ); + + } + + // + // Check to see if we have a wait + // pending on the comm error events. If we + // do then we schedule a dpc to satisfy + // that wait. + // + + if (Extension->IsrWaitMask) { + + if ((Extension->IsrWaitMask & SERIAL_EV_ERR) && + (LineStatus & (SERIAL_LSR_OE | + SERIAL_LSR_PE | + SERIAL_LSR_FE))) { + + Extension->HistoryMask |= SERIAL_EV_ERR; + + } + + if ((Extension->IsrWaitMask & SERIAL_EV_BREAK) && + (LineStatus & SERIAL_LSR_BI)) { + + Extension->HistoryMask |= SERIAL_EV_BREAK; + + } + + if (Extension->IrpMaskLocation && + Extension->HistoryMask) { + + *Extension->IrpMaskLocation = + Extension->HistoryMask; + Extension->IrpMaskLocation = NULL; + Extension->HistoryMask = 0; + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + reqContext->Information = sizeof(ULONG); + SerialInsertQueueDpc( + Extension->CommWaitDpc + ); + + } + + } + + if (LineStatus & SERIAL_LSR_THRE) { + + // + // There is a hardware bug in some versions + // of the 16450 and 550. If THRE interrupt + // is pending, but a higher interrupt comes + // in it will only return the higher and + // *forget* about the THRE. + // + // A suitable workaround - whenever we + // are *all* done reading line status + // of the device we check to see if the + // transmit holding register is empty. If it is + // AND we are currently transmitting data + // enable the interrupts which should cause + // an interrupt indication which we quiet + // when we read the interrupt id register. + // + + if (Extension->WriteLength | + Extension->TransmitImmediate) { + + DISABLE_ALL_INTERRUPTS(Extension, + Extension->Controller + ); + ENABLE_ALL_INTERRUPTS(Extension, + Extension->Controller + ); + } + + } + + } + + return LineStatus; +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/log.c b/tests/projects/windows/driver/kmdf/serial/log.c new file mode 100644 index 000000000..285c8b2f8 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/log.c @@ -0,0 +1,97 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + log.c + +Abstract: + + Debug log Code for serial. + +Environment: + + kernel mode only + +--*/ + +#include "precomp.h" + +extern ULONG DebugLevel; +extern ULONG DebugFlag; + +#if !defined(EVENT_TRACING) + +VOID +SerialDbgPrintEx ( + IN ULONG TraceEventsLevel, + IN ULONG TraceEventsFlag, + IN PCCHAR DebugMessage, + ... + ) + +/*++ + +Routine Description: + + Debug print for the sample driver. + +Arguments: + + TraceEventsLevel - print level between 0 and 3, with 3 the most verbose + +Return Value: + + None. + + --*/ + { +#if DBG + +#define TEMP_BUFFER_SIZE 1024 + + va_list list; + CHAR debugMessageBuffer [TEMP_BUFFER_SIZE]; + NTSTATUS status; + + va_start(list, DebugMessage); + + if (DebugMessage) { + + // + // Using new safe string functions instead of _vsnprintf. + // This function takes care of NULL terminating if the message + // is longer than the buffer. + // + status = RtlStringCbVPrintfA( debugMessageBuffer, + sizeof(debugMessageBuffer), + DebugMessage, + list ); + if(!NT_SUCCESS(status)) { + + KdPrint((_DRIVER_NAME_": RtlStringCbVPrintfA failed %x\n", status)); + return; + } + if (TraceEventsLevel < TRACE_LEVEL_INFORMATION || + (TraceEventsLevel <= DebugLevel && + ((TraceEventsFlag & DebugFlag) == TraceEventsFlag))) { + + KdPrint((debugMessageBuffer)); + } + } + va_end(list); + + return; + +#else + + UNREFERENCED_PARAMETER(TraceEventsLevel); + UNREFERENCED_PARAMETER(TraceEventsFlag); + UNREFERENCED_PARAMETER(DebugMessage); + +#endif +} + +#endif + diff --git a/tests/projects/windows/driver/kmdf/serial/log.h b/tests/projects/windows/driver/kmdf/serial/log.h new file mode 100644 index 000000000..eedcd08f3 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/log.h @@ -0,0 +1,37 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation +:ts=4 + +Module Name: + + log.h + +Abstract: + + debug macros + +Environment: + + Kernel & user mode + +--*/ + +#ifndef __LOG_H__ +#define __LOG_H__ + +#if !defined(EVENT_TRACING) + +VOID +SerialDbgPrintEx ( + IN ULONG DebugPrintLevel, + IN ULONG DebugPrintFlag, + IN PCCHAR DebugMessage, + ... + ); + +#endif + +#endif // __LOG_H__ + + diff --git a/tests/projects/windows/driver/kmdf/serial/modmflow.c b/tests/projects/windows/driver/kmdf/serial/modmflow.c new file mode 100644 index 000000000..1c71ae3fd --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/modmflow.c @@ -0,0 +1,1714 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + modmflow.c + +Abstract: + + This module contains *MOST* of the code used to manipulate + the modem control and status registers. The vast majority + of the remainder of flow control is concentrated in the + Interrupt service routine. A very small amount resides + in the read code that pull characters out of the interrupt + buffer. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "modmflow.tmh" +#endif + + +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialDecrementRTSCounter; + +BOOLEAN +SerialSetDTR( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine which is only called at interrupt level is used + to set the DTR in the modem control register. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = Context; + UCHAR ModemControl; + + UNREFERENCED_PARAMETER(Interrupt); + + ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); + + ModemControl |= SERIAL_MCR_DTR; + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, + "Setting DTR for %p\n", Extension->Controller); + + WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); + + return FALSE; + +} + +BOOLEAN +SerialClrDTR( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine which is only called at interrupt level is used + to clear the DTR in the modem control register. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + UCHAR ModemControl; + + UNREFERENCED_PARAMETER(Interrupt); + + ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); + + ModemControl &= ~SERIAL_MCR_DTR; + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing DTR for %p\n", Extension->Controller); + + WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); + + return FALSE; + +} + +BOOLEAN +SerialSetRTS( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine which is only called at interrupt level is used + to set the RTS in the modem control register. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + UCHAR ModemControl; + + UNREFERENCED_PARAMETER(Interrupt); + + ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); + + ModemControl |= SERIAL_MCR_RTS; + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Setting Rts for %p\n", Extension->Controller); + + WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); + + return FALSE; + +} + +BOOLEAN +SerialClrRTS( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine which is only called at interrupt level is used + to clear the RTS in the modem control register. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + UCHAR ModemControl; + + UNREFERENCED_PARAMETER(Interrupt); + + ModemControl = READ_MODEM_CONTROL(Extension, Extension->Controller); + + ModemControl &= ~SERIAL_MCR_RTS; + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing Rts for %p\n", Extension->Controller); + + WRITE_MODEM_CONTROL(Extension, Extension->Controller, ModemControl); + + return FALSE; + +} + +BOOLEAN +SerialSetupNewHandFlow( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN PSERIAL_HANDFLOW NewHandFlow + ) + +/*++ + +Routine Description: + + This routine adjusts the flow control based on new + control flow. + +Arguments: + + Extension - A pointer to the serial device extension. + + NewHandFlow - A pointer to a serial handflow structure + that is to become the new setup for flow + control. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + SERIAL_HANDFLOW New = *NewHandFlow; + + // + // If the Extension->DeviceIsOpened is FALSE that means + // we are entering this routine in response to an open request. + // If that is so, then we always proceed with the work regardless + // of whether things have changed. + // + + // + // First we take care of the DTR flow control. We only + // do work if something has changed. + // + + if ((!Extension->DeviceIsOpened) || + ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) != + (New.ControlHandShake & SERIAL_DTR_MASK))) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Processing DTR flow for %p\n", + Extension->Controller); + + if (New.ControlHandShake & SERIAL_DTR_MASK) { + + // + // Well we might want to set DTR. + // + // Before we do, we need to check whether we are doing + // dtr flow control. If we are then we need to check + // if then number of characters in the interrupt buffer + // exceeds the XoffLimit. If it does then we don't + // enable DTR AND we set the RXHolding to record that + // we are holding because of the dtr. + // + + if ((New.ControlHandShake & SERIAL_DTR_MASK) + == SERIAL_DTR_HANDSHAKE) { + + if ((Extension->BufferSize - New.XoffLimit) > + Extension->CharsInInterruptBuffer) { + + // + // However if we are already holding we don't want + // to turn it back on unless we exceed the Xon + // limit. + // + + if (Extension->RXHolding & SERIAL_RX_DTR) { + + // + // We can assume that its DTR line is already low. + // + + if (Extension->CharsInInterruptBuffer > + (ULONG)New.XonLimit) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Removing DTR block on " + "reception for %p\n", + Extension->Controller); + + Extension->RXHolding &= ~SERIAL_RX_DTR; + SerialSetDTR(Extension->WdfInterrupt, Extension); + + } + + } else { + + SerialSetDTR(Extension->WdfInterrupt, Extension); + + } + + } else { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Setting DTR block on reception " + "for %p\n", Extension->Controller); + Extension->RXHolding |= SERIAL_RX_DTR; + SerialClrDTR(Extension->WdfInterrupt, Extension); + + } + + } else { + + // + // Note that if we aren't currently doing dtr flow control then + // we MIGHT have been. So even if we aren't currently doing + // DTR flow control, we should still check if RX is holding + // because of DTR. If it is, then we should clear the holding + // of this bit. + // + + if (Extension->RXHolding & SERIAL_RX_DTR) { + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Removing dtr block of reception " + "for %p\n", Extension->Controller); + Extension->RXHolding &= ~SERIAL_RX_DTR; + } + + SerialSetDTR(Extension->WdfInterrupt, Extension); + + } + + } else { + + // + // The end result here will be that DTR is cleared. + // + // We first need to check whether reception is being held + // up because of previous DTR flow control. If it is then + // we should clear that reason in the RXHolding mask. + // + + if (Extension->RXHolding & SERIAL_RX_DTR) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "removing dtr block of reception for" + " %p\n", Extension->Controller); + Extension->RXHolding &= ~SERIAL_RX_DTR; + + } + + SerialClrDTR(Extension->WdfInterrupt, Extension); + + } + + } + + // + // Time to take care of the RTS Flow control. + // + // First we only do work if something has changed. + // + + if ((!Extension->DeviceIsOpened) || + ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) != + (New.FlowReplace & SERIAL_RTS_MASK))) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Processing RTS flow %p\n", + Extension->Controller); + + if ((New.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_RTS_HANDSHAKE) { + + // + // Well we might want to set RTS. + // + // Before we do, we need to check whether we are doing + // rts flow control. If we are then we need to check + // if then number of characters in the interrupt buffer + // exceeds the XoffLimit. If it does then we don't + // enable RTS AND we set the RXHolding to record that + // we are holding because of the rts. + // + + if ((Extension->BufferSize - New.XoffLimit) > + Extension->CharsInInterruptBuffer) { + + // + // However if we are already holding we don't want + // to turn it back on unless we exceed the Xon + // limit. + // + + if (Extension->RXHolding & SERIAL_RX_RTS) { + + // + // We can assume that its RTS line is already low. + // + + if (Extension->CharsInInterruptBuffer > + (ULONG)New.XonLimit) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Removing rts block of " + "reception for %p\n", + Extension->Controller); + Extension->RXHolding &= ~SERIAL_RX_RTS; + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } + + } else { + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } + + } else { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Setting rts block of reception for " + "%p\n", Extension->Controller); + Extension->RXHolding |= SERIAL_RX_RTS; + SerialClrRTS(Extension->WdfInterrupt, Extension); + + } + + } else if ((New.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_RTS_CONTROL) { + + // + // Note that if we aren't currently doing rts flow control then + // we MIGHT have been. So even if we aren't currently doing + // RTS flow control, we should still check if RX is holding + // because of RTS. If it is, then we should clear the holding + // of this bit. + // + + if (Extension->RXHolding & SERIAL_RX_RTS) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing rts block of reception for " + "%p\n", Extension->Controller); + Extension->RXHolding &= ~SERIAL_RX_RTS; + + } + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } else if ((New.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + // + // We first need to check whether reception is being held + // up because of previous RTS flow control. If it is then + // we should clear that reason in the RXHolding mask. + // + + if (Extension->RXHolding & SERIAL_RX_RTS) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "TOGGLE Clearing rts block of " + "reception for %p\n", Extension->Controller); + Extension->RXHolding &= ~SERIAL_RX_RTS; + + } + + // + // We have to place the rts value into the Extension + // now so that the code that tests whether the + // rts line should be lowered will find that we + // are "still" doing transmit toggling. The code + // for lowering can be invoked later by a timer so + // it has to test whether it still needs to do its + // work. + // + + Extension->HandFlow.FlowReplace &= ~SERIAL_RTS_MASK; + Extension->HandFlow.FlowReplace |= SERIAL_TRANSMIT_TOGGLE; + + // + // The order of the tests is very important below. + // + // If there is a break then we should turn on the RTS. + // + // If there isn't a break but there are characters in + // the hardware, then turn on the RTS. + // + // If there are writes pending that aren't being held + // up, then turn on the RTS. + // + + if ((Extension->TXHolding & SERIAL_TX_BREAK) || + ((SerialProcessLSR(Extension) & (SERIAL_LSR_THRE | + SERIAL_LSR_TEMT)) != + (SERIAL_LSR_THRE | + SERIAL_LSR_TEMT)) || + (Extension->CurrentWriteRequest || Extension->TransmitImmediate || + (!IsQueueEmpty(Extension->WriteQueue)) && + (!Extension->TXHolding))) { + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } else { + + // + // This routine will check to see if it is time + // to lower the RTS because of transmit toggle + // being on. If it is ok to lower it, it will, + // if it isn't ok, it will schedule things so + // that it will get lowered later. + // + + Extension->CountOfTryingToLowerRTS++; + SerialPerhapsLowerRTS(Extension->WdfInterrupt, Extension); + + } + + } else { + + // + // The end result here will be that RTS is cleared. + // + // We first need to check whether reception is being held + // up because of previous RTS flow control. If it is then + // we should clear that reason in the RXHolding mask. + // + + if (Extension->RXHolding & SERIAL_RX_RTS) { + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Clearing rts block of reception for" + " %p\n", Extension->Controller); + Extension->RXHolding &= ~SERIAL_RX_RTS; + + } + + SerialClrRTS(Extension->WdfInterrupt, Extension); + + } + + } + + // + // We now take care of automatic receive flow control. + // We only do work if things have changed. + // + + if ((!Extension->DeviceIsOpened) || + ((Extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) != + (New.FlowReplace & SERIAL_AUTO_RECEIVE))) { + + if (New.FlowReplace & SERIAL_AUTO_RECEIVE) { + + // + // We wouldn't be here if it had been on before. + // + // We should check to see whether we exceed the turn + // off limits. + // + // Note that since we are following the OS/2 flow + // control rules we will never send an xon if + // when enabling xon/xoff flow control we discover that + // we could receive characters but we are held up do + // to a previous Xoff. + // + + if ((Extension->BufferSize - New.XoffLimit) <= + Extension->CharsInInterruptBuffer) { + + // + // Cause the Xoff to be sent. + // + + Extension->RXHolding |= SERIAL_RX_XOFF; + + SerialProdXonXoff( + Extension, + FALSE + ); + + } + + } else { + + // + // The app has disabled automatic receive flow control. + // + // If transmission was being held up because of + // an automatic receive Xoff, then we should + // cause an Xon to be sent. + // + + if (Extension->RXHolding & SERIAL_RX_XOFF) { + + Extension->RXHolding &= ~SERIAL_RX_XOFF; + + // + // Cause the Xon to be sent. + // + + SerialProdXonXoff( + Extension, + TRUE + ); + + } + + } + + } + + // + // We now take care of automatic transmit flow control. + // We only do work if things have changed. + // + + if ((!Extension->DeviceIsOpened) || + ((Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT) != + (New.FlowReplace & SERIAL_AUTO_TRANSMIT))) { + + if (New.FlowReplace & SERIAL_AUTO_TRANSMIT) { + + // + // We wouldn't be here if it had been on before. + // + // There is some belief that if autotransmit + // was just enabled, I should go look in what we + // already received, and if we find the xoff character + // then we should stop transmitting. I think this + // is an application bug. For now we just care about + // what we see in the future. + // + + ; + + } else { + + // + // The app has disabled automatic transmit flow control. + // + // If transmission was being held up because of + // an automatic transmit Xoff, then we should + // cause an Xon to be sent. + // + + if (Extension->TXHolding & SERIAL_TX_XOFF) { + + Extension->TXHolding &= ~SERIAL_TX_XOFF; + + // + // Cause the Xon to be sent. + // + + SerialProdXonXoff( + Extension, + TRUE + ); + + } + + } + + } + + // + // At this point we can simply make sure that entire + // handflow structure in the extension is updated. + // + + Extension->HandFlow = New; + + return FALSE; + +} + +BOOLEAN +SerialSetHandFlow( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to set the handshake and control + flow in the device extension. + +Arguments: + + Context - Pointer to a structure that contains a pointer to + the device extension and a pointer to a handflow + structure.. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_IOCTL_SYNC S = Context; + PSERIAL_DEVICE_EXTENSION Extension = S->Extension; + PSERIAL_HANDFLOW HandFlow = S->Data; + + UNREFERENCED_PARAMETER(Interrupt); + + SerialSetupNewHandFlow( + Extension, + HandFlow + ); + + SerialHandleModemUpdate( + Extension, + FALSE + ); + + return FALSE; + +} + +BOOLEAN +SerialTurnOnBreak( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine will turn on break in the hardware and + record the fact the break is on, in the extension variable + that holds reasons that transmission is stopped. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UCHAR OldLineControl; + + UNREFERENCED_PARAMETER(Interrupt); + + if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } + + OldLineControl = READ_LINE_CONTROL(Extension, Extension->Controller); + + OldLineControl |= SERIAL_LCR_BREAK; + + WRITE_LINE_CONTROL(Extension, + Extension->Controller, + OldLineControl + ); + + Extension->TXHolding |= SERIAL_TX_BREAK; + + return FALSE; + +} + +BOOLEAN +SerialTurnOffBreak( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine will turn off break in the hardware and + record the fact the break is off, in the extension variable + that holds reasons that transmission is stopped. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UCHAR OldLineControl; + + UNREFERENCED_PARAMETER(Interrupt); + + if (Extension->TXHolding & SERIAL_TX_BREAK) { + + // + // We actually have a good reason for testing if transmission + // is holding instead of blindly clearing the bit. + // + // If transmission actually was holding and the result of + // clearing the bit is that we should restart transmission + // then we will poke the interrupt enable bit, which will + // cause an actual interrupt and transmission will then + // restart on its own. + // + // If transmission wasn't holding and we poked the bit + // then we would interrupt before a character actually made + // it out and we could end up over writing a character in + // the transmission hardware. + + OldLineControl = READ_LINE_CONTROL(Extension, Extension->Controller); + + OldLineControl &= ~SERIAL_LCR_BREAK; + + WRITE_LINE_CONTROL(Extension, + Extension->Controller, + OldLineControl + ); + + Extension->TXHolding &= ~SERIAL_TX_BREAK; + + if (!Extension->TXHolding && + (Extension->TransmitImmediate || + Extension->WriteLength) && + Extension->HoldingEmpty) { + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + + } else { + + // + // The following routine will lower the rts if we + // are doing transmit toggleing and there is no + // reason to keep it up. + // + + Extension->CountOfTryingToLowerRTS++; + SerialPerhapsLowerRTS(Extension->WdfInterrupt, Extension); + + } + + } + + return FALSE; + +} + +BOOLEAN +SerialPretendXoff( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to process the Ioctl that request the + driver to act as if an Xoff was received. Even if the + driver does not have automatic Xoff/Xon flowcontrol - This + still will stop the transmission. This is the OS/2 behavior + and is not well specified for Windows. Therefore we adopt + the OS/2 behavior. + + Note: If the driver does not have automatic Xoff/Xon enabled + then the only way to restart transmission is for the + application to request we "act" as if we saw the xon. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + Extension->TXHolding |= SERIAL_TX_XOFF; + + if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } + + return FALSE; + +} + +BOOLEAN +SerialPretendXon( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to process the Ioctl that request the + driver to act as if an Xon was received. + + Note: If the driver does not have automatic Xoff/Xon enabled + then the only way to restart transmission is for the + application to request we "act" as if we saw the xon. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + if (Extension->TXHolding) { + + // + // We actually have a good reason for testing if transmission + // is holding instead of blindly clearing the bit. + // + // If transmission actually was holding and the result of + // clearing the bit is that we should restart transmission + // then we will poke the interrupt enable bit, which will + // cause an actual interrupt and transmission will then + // restart on its own. + // + // If transmission wasn't holding and we poked the bit + // then we would interrupt before a character actually made + // it out and we could end up over writing a character in + // the transmission hardware. + + Extension->TXHolding &= ~SERIAL_TX_XOFF; + + if (!Extension->TXHolding && + (Extension->TransmitImmediate || + Extension->WriteLength) && + Extension->HoldingEmpty) { + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + + } + + } + + return FALSE; + +} + +VOID +SerialHandleReducedIntBuffer( + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + This routine is called to handle a reduction in the number + of characters in the interrupt (typeahead) buffer. It + will check the current output flow control and re-enable transmission + as needed. + + NOTE: This routine assumes that it is working at interrupt level. + +Arguments: + + Extension - A pointer to the device extension. + +Return Value: + + None. + +--*/ + +{ + + + // + // If we are doing receive side flow control and we are + // currently "holding" then because we've emptied out + // some characters from the interrupt buffer we need to + // see if we can "re-enable" reception. + // + + if (Extension->RXHolding) { + + if (Extension->CharsInInterruptBuffer <= + (ULONG)Extension->HandFlow.XonLimit) { + + if (Extension->RXHolding & SERIAL_RX_DTR) { + + Extension->RXHolding &= ~SERIAL_RX_DTR; + SerialSetDTR(Extension->WdfInterrupt, Extension); + + } + + if (Extension->RXHolding & SERIAL_RX_RTS) { + + Extension->RXHolding &= ~SERIAL_RX_RTS; + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } + + if (Extension->RXHolding & SERIAL_RX_XOFF) { + + // + // Prod the transmit code to send xon. + // + + SerialProdXonXoff( + Extension, + TRUE + ); + + } + + } + + } + +} + +VOID +SerialProdXonXoff( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN BOOLEAN SendXon + ) + +/*++ + +Routine Description: + + This routine will set up the SendXxxxChar variables if + necessary and determine if we are going to be interrupting + because of current transmission state. It will cause an + interrupt to occur if neccessary, to send the xon/xoff char. + + NOTE: This routine assumes that it is called at interrupt + level. + +Arguments: + + Extension - A pointer to the serial device extension. + + SendXon - If a character is to be send, this indicates whether + it should be an Xon or an Xoff. + +Return Value: + + None. + +--*/ + +{ + + // + // We assume that if the prodding is called more than + // once that the last prod has set things up appropriately. + // + // We could get called before the character is sent out + // because the send of the character was blocked because + // of hardware flow control (or break). + // + + if (!Extension->SendXonChar && !Extension->SendXoffChar + && Extension->HoldingEmpty) { + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + + } + + if (SendXon) { + + Extension->SendXonChar = TRUE; + Extension->SendXoffChar = FALSE; + + } else { + + Extension->SendXonChar = FALSE; + Extension->SendXoffChar = TRUE; + + } + +} + +ULONG +SerialHandleModemUpdate( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN BOOLEAN DoingTX + ) + +/*++ + +Routine Description: + + This routine will be to check on the modem status, and + handle any appropriate event notification as well as + any flow control appropriate to modem status lines. + + NOTE: This routine assumes that it is called at interrupt + level. + +Arguments: + + Extension - A pointer to the serial device extension. + + DoingTX - This boolean is used to indicate that this call + came from the transmit processing code. If this + is true then there is no need to cause a new interrupt + since the code will be trying to send the next + character as soon as this call finishes. + +Return Value: + + This returns the old value of the modem status register + (extended into a ULONG). + +--*/ + +{ + + // + // We keep this local so that after we are done + // examining the modem status and we've updated + // the transmission holding value, we know whether + // we've changed from needing to hold up transmission + // to transmission being able to proceed. + // + ULONG OldTXHolding = Extension->TXHolding; + + // + // Holds the value in the mode status register. + // + UCHAR ModemStatus; + PREQUEST_CONTEXT reqContext; + + ModemStatus = + READ_MODEM_STATUS(Extension, Extension->Controller); + + + // + // If we are placeing the modem status into the data stream + // on every change, we should do it now. + // + + if (Extension->EscapeChar) { + + if (ModemStatus & (SERIAL_MSR_DCTS | + SERIAL_MSR_DDSR | + SERIAL_MSR_TERI | + SERIAL_MSR_DDCD)) { + + SerialPutChar( + Extension, + Extension->EscapeChar + ); + SerialPutChar( + Extension, + SERIAL_LSRMST_MST + ); + SerialPutChar( + Extension, + ModemStatus + ); + + } + + } + + + // + // Take care of input flow control based on sensitivity + // to the DSR. This is done so that the application won't + // see spurious data generated by odd devices. + // + // Basically, if we are doing dsr sensitivity then the + // driver should only accept data when the dsr bit is + // set. + // + + if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_SENSITIVITY) { + + if (ModemStatus & SERIAL_MSR_DSR) { + + // + // The line is high. Simply make sure that + // RXHolding does't have the DSR bit. + // + + Extension->RXHolding &= ~SERIAL_RX_DSR; + + } else { + + Extension->RXHolding |= SERIAL_RX_DSR; + + } + + } else { + + // + // We don't have sensitivity due to DSR. Make sure we + // arn't holding. (We might have been, but the app just + // asked that we don't hold for this reason any more.) + // + + Extension->RXHolding &= ~SERIAL_RX_DSR; + + } + + // + // Check to see if we have a wait + // pending on the modem status events. If we + // do then we schedule a dpc to satisfy + // that wait. + // + + if (Extension->IsrWaitMask) { + + if ((Extension->IsrWaitMask & SERIAL_EV_CTS) && + (ModemStatus & SERIAL_MSR_DCTS)) { + + Extension->HistoryMask |= SERIAL_EV_CTS; + + } + + if ((Extension->IsrWaitMask & SERIAL_EV_DSR) && + (ModemStatus & SERIAL_MSR_DDSR)) { + + Extension->HistoryMask |= SERIAL_EV_DSR; + + } + + if ((Extension->IsrWaitMask & SERIAL_EV_RING) && + (ModemStatus & SERIAL_MSR_TERI)) { + + Extension->HistoryMask |= SERIAL_EV_RING; + + } + + if ((Extension->IsrWaitMask & SERIAL_EV_RLSD) && + (ModemStatus & SERIAL_MSR_DDCD)) { + + Extension->HistoryMask |= SERIAL_EV_RLSD; + + } + + if (Extension->IrpMaskLocation && + Extension->HistoryMask) { + + *Extension->IrpMaskLocation = + Extension->HistoryMask; + Extension->IrpMaskLocation = NULL; + Extension->HistoryMask = 0; + + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + reqContext->Information = sizeof(ULONG); + SerialInsertQueueDpc( + Extension->CommWaitDpc + ); + + } + + } + + // + // If the app has modem line flow control then + // we check to see if we have to hold up transmission. + // + + if (Extension->HandFlow.ControlHandShake & + SERIAL_OUT_HANDSHAKEMASK) { + + if (Extension->HandFlow.ControlHandShake & + SERIAL_CTS_HANDSHAKE) { + + if (ModemStatus & SERIAL_MSR_CTS) { + + Extension->TXHolding &= ~SERIAL_TX_CTS; + + } else { + + Extension->TXHolding |= SERIAL_TX_CTS; + + } + + } else { + + Extension->TXHolding &= ~SERIAL_TX_CTS; + + } + + if (Extension->HandFlow.ControlHandShake & + SERIAL_DSR_HANDSHAKE) { + + if (ModemStatus & SERIAL_MSR_DSR) { + + Extension->TXHolding &= ~SERIAL_TX_DSR; + + } else { + + Extension->TXHolding |= SERIAL_TX_DSR; + + } + + } else { + + Extension->TXHolding &= ~SERIAL_TX_DSR; + + } + + if (Extension->HandFlow.ControlHandShake & + SERIAL_DCD_HANDSHAKE) { + + if (ModemStatus & SERIAL_MSR_DCD) { + + Extension->TXHolding &= ~SERIAL_TX_DCD; + + } else { + + Extension->TXHolding |= SERIAL_TX_DCD; + + } + + } else { + + Extension->TXHolding &= ~SERIAL_TX_DCD; + + } + + // + // If we hadn't been holding, and now we are then + // queue off a dpc that will lower the RTS line + // if we are doing transmit toggling. + // + + if (!OldTXHolding && Extension->TXHolding && + ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE)) { + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + } + + // + // We've done any adjusting that needed to be + // done to the holding mask given updates + // to the modem status. If the Holding mask + // is clear (and it wasn't clear to start) + // and we have "write" work to do set things + // up so that the transmission code gets invoked. + // + + if (!DoingTX && OldTXHolding && !Extension->TXHolding) { + + if (!Extension->TXHolding && + (Extension->TransmitImmediate || + Extension->WriteLength) && + Extension->HoldingEmpty) { + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + } + + } + + } else { + + // + // We need to check if transmission is holding + // up because of modem status lines. What + // could have occured is that for some strange + // reason, the app has asked that we no longer + // stop doing output flow control based on + // the modem status lines. If however, we + // *had* been held up because of the status lines + // then we need to clear up those reasons. + // + + if (Extension->TXHolding & (SERIAL_TX_DCD | + SERIAL_TX_DSR | + SERIAL_TX_CTS)) { + + Extension->TXHolding &= ~(SERIAL_TX_DCD | + SERIAL_TX_DSR | + SERIAL_TX_CTS); + + + if (!DoingTX && OldTXHolding && !Extension->TXHolding) { + + if (!Extension->TXHolding && + (Extension->TransmitImmediate || + Extension->WriteLength) && + Extension->HoldingEmpty) { + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + } + + } + + } + + } + + return ((ULONG)ModemStatus); +} + +BOOLEAN +SerialPerhapsLowerRTS( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine checks that the software reasons for lowering + the RTS lines are present. If so, it will then cause the + line status register to be read (and any needed processing + implied by the status register to be done), and if the + shift register is empty it will lower the line. If the + shift register isn't empty, this routine will queue off + a dpc that will start a timer, that will basically call + us back to try again. + + NOTE: This routine assumes that it is called at interrupt + level. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + // + // We first need to test if we are actually still doing + // transmit toggle flow control. If we aren't then + // we have no reason to try be here. + // + + if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + // + // The order of the tests is very important below. + // + // If there is a break then we should leave on the RTS, + // because when the break is turned off, it will submit + // the code to shut down the RTS. + // + // If there are writes pending that aren't being held + // up, then leave on the RTS, because the end of the write + // code will cause this code to be reinvoked. If the writes + // are being held up, its ok to lower the RTS because the + // upon trying to write the first character after transmission + // is restarted, we will raise the RTS line. + // + + if ((Extension->TXHolding & SERIAL_TX_BREAK) || + (Extension->CurrentWriteRequest || Extension->TransmitImmediate || + (!IsQueueEmpty(Extension->WriteQueue)) && + (!Extension->TXHolding))) { + + NOTHING; + + } else { + + // + // Looks good so far. Call the line status check and processing + // code, it will return the "current" line status value. If + // the holding and shift register are clear, lower the RTS line, + // if they aren't clear, queue of a dpc that will cause a timer + // to reinvoke us later. We do this code here because no one + // but this routine cares about the characters in the hardware, + // so no routine by this routine will bother invoking to test + // if the hardware is empty. + // + + if ((SerialProcessLSR(Extension) & + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) != + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { + + // + // Well it's not empty, try again later. + // + + SerialInsertQueueDpc( + Extension->StartTimerLowerRTSDpc + )?Extension->CountOfTryingToLowerRTS++:0; + + + } else { + + // + // Nothing in the hardware, Lower the RTS. + // + + SerialClrRTS(Extension->WdfInterrupt, Extension); + + + } + + } + + } + + // + // We decement the counter to indicate that we've reached + // the end of the execution path that is trying to push + // down the RTS line. + // + + Extension->CountOfTryingToLowerRTS--; + + return FALSE; +} + +VOID +SerialStartTimerLowerRTS( + IN WDFDPC Dpc + ) + +/*++ + +Routine Description: + + This routine starts a timer that when it expires will start + a dpc that will check if it can lower the rts line because + there are no characters in the hardware. + +Arguments: + + Dpc - Not Used. + + DeferredContext - Really points to the device extension. + + SystemContext1 - Not Used. + + SystemContext2 - Not Used. + +Return Value: + + None. + +--*/ + +{ + LARGE_INTEGER CharTime; + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); + + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, ">SerialStartTimerLowerRTS(%p)\n", + Extension); + + + // + // Since all the callbacks into the driver are serialized, we don't have + // synchronize the access to any of the Extension variables. + // + + CharTime = SerialGetCharTime(Extension); + + CharTime.QuadPart = -CharTime.QuadPart; + + if (SerialSetTimer( + Extension->LowerRTSTimer, + CharTime + )) { + + // + // The timer was already in the timer queue. This implies + // that one path of execution that was trying to lower + // the RTS has "died". Synchronize with the ISR so that + // we can lower the count. + // + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialDecrementRTSCounter, + Extension + ); + + } + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "WdfInterrupt, + SerialPerhapsLowerRTS, + Extension + ); + +} + +BOOLEAN +SerialDecrementRTSCounter( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine checks that the software reasons for lowering + the RTS lines are present. If so, it will then cause the + line status register to be read (and any needed processing + implied by the status register to be done), and if the + shift register is empty it will lower the line. If the + shift register isn't empty, this routine will queue off + a dpc that will start a timer, that will basically call + us back to try again. + + NOTE: This routine assumes that it is called at interrupt + level. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + Extension->CountOfTryingToLowerRTS--; + + return FALSE; + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/openclos.c b/tests/projects/windows/driver/kmdf/serial/openclos.c new file mode 100644 index 000000000..477f07ac1 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/openclos.c @@ -0,0 +1,850 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + openclos.c + +Abstract: + + This module contains the code that is very specific to + opening, closing, and cleaning up in the serial driver. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "openclos.tmh" +#endif + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGESER,SerialGetCharTime) +#pragma alloc_text(PAGESER,SerialEvtFileClose) +#pragma alloc_text(PAGESER,SerialDrainUART) +#pragma alloc_text(PAGESRP0,SerialEvtDeviceFileCreate) +#pragma alloc_text(PAGESRP0,SerialCreateTimersAndDpcs) +#endif // ALLOC_PRAGMA + + + +VOID +SerialEvtDeviceFileCreate ( + IN WDFDEVICE Device, + IN WDFREQUEST Request, + IN WDFFILEOBJECT FileObject + ) +/*++ + +Routine Description: + + The framework calls a driver's EvtDeviceFileCreate callback + when the framework receives an IRP_MJ_CREATE request. + The system sends this request when a user application opens the + device to perform an I/O operation, such as reading or writing a file. + This callback is called synchronously, in the context of the thread + that created the IRP_MJ_CREATE request. + +Arguments: + + Device - Handle to a framework device object. + FileObject - Pointer to fileobject that represents the open handle. + CreateParams - Copy of the Create IO_STACK_LOCATION + +Return Value: + + VOID. + +--*/ +{ + NTSTATUS status; + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); + + UNREFERENCED_PARAMETER(FileObject); + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, + "SerialEvtDeviceFileCreate %wZ\n", &extension->DeviceName); + + status = SerialDeviceFileCreateWorker(Device); + + // + // Complete the WDF request. + // + WdfRequestComplete(Request, status); + + return; + +} + + +NTSTATUS +SerialWdmDeviceFileCreate ( + IN WDFDEVICE Device, + IN PIRP Irp + ) +/*++ + +Routine Description: + + This is the dispatch routine for IRP_MJ_CREATE. The system sends this + request when a user application opens the device to perform an I/O + operation, such as reading or writing a file. + +Arguments: + + DeviceObject - Pointer to the device object for this device + Irp - Pointer to the IRP for the current request + +Return Value: + + NT status code + +--*/ +{ + NTSTATUS status; + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, + "SerialWdmDeviceFileCreate %wZ\n", &extension->DeviceName); + + status = SerialDeviceFileCreateWorker(Device); + + // + // Complete the WDM request. + // + Irp->IoStatus.Information = 0L; + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + + +NTSTATUS +SerialDeviceFileCreateWorker ( + IN WDFDEVICE Device + ) +{ + NTSTATUS status; + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); + + // + // Create a buffer for the RX data when no reads are outstanding. + // + + extension->InterruptReadBuffer = NULL; + extension->BufferSize = 0; + + switch (MmQuerySystemSize()) { + + case MmLargeSystem: { + + extension->BufferSize = 4096; + extension->InterruptReadBuffer = ExAllocatePoolWithTag( + NonPagedPoolNx, + extension->BufferSize, + POOL_TAG + ); + + if (extension->InterruptReadBuffer) { + break; + } + + } + + case MmMediumSystem: { + + extension->BufferSize = 1024; + extension->InterruptReadBuffer = ExAllocatePoolWithTag( + NonPagedPoolNx, + extension->BufferSize, + POOL_TAG + ); + + if (extension->InterruptReadBuffer) { + break; + } + + } + + case MmSmallSystem: { + + extension->BufferSize = 128; + extension->InterruptReadBuffer = ExAllocatePoolWithTag( + NonPagedPoolNx, + extension->BufferSize, + POOL_TAG + ); + + } + + } + + if (!extension->InterruptReadBuffer) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // By taking a power reference by calling WdfDeviceStopIdle, we prevent the + // framework from powering down our device due to idle timeout when there + // is an open handle. Power reference also moves the device to D0 if we are + // idled out. If you fail create anywhere later in this routine, do make sure + // drop the reference. + // + status = WdfDeviceStopIdle(Device, TRUE); + if (!NT_SUCCESS(status)) { + return status; + } + + // + // wakeup is not currently enabled + // + + extension->IsWakeEnabled = FALSE; + + // + // On a new open we "flush" the read queue by initializing the + // count of characters. + // + + extension->CharsInInterruptBuffer = 0; + extension->LastCharSlot = extension->InterruptReadBuffer + + (extension->BufferSize - 1); + + extension->ReadBufferBase = extension->InterruptReadBuffer; + extension->CurrentCharSlot = extension->InterruptReadBuffer; + extension->FirstReadableChar = extension->InterruptReadBuffer; + + extension->TotalCharsQueued = 0; + + // + // We set up the default xon/xoff limits. + // + + extension->HandFlow.XoffLimit = extension->BufferSize >> 3; + extension->HandFlow.XonLimit = extension->BufferSize >> 1; + + extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit; + extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit; + + extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+ + (extension->BufferSize>>4)); + + // + // Mark the device as busy for WMI + // + + extension->WmiCommData.IsBusy = TRUE; + + extension->IrpMaskLocation = NULL; + extension->HistoryMask = 0; + extension->IsrWaitMask = 0; + + extension->SendXonChar = FALSE; + extension->SendXoffChar = FALSE; + +#if !DBG + // + // Clear out the statistics. + // + + WdfInterruptSynchronize( + extension->WdfInterrupt, + SerialClearStats, + extension + ); +#endif + + // + // The escape char replacement must be reset upon every open. + // + + extension->EscapeChar = 0; + + // + // We don't want the device to be removed or stopped when there is an handle + // + // Note to anyone copying this sample as a starting point: + // + // This works in this driver simply because this driver supports exactly + // one open handle at a time. If it supported more, then it would need + // counting logic to determine when all the reasons for failing Stop/Remove + // were gone. + // + WdfDeviceSetStaticStopRemove(Device, FALSE); + + // + // Synchronize with the ISR and let it know that the device + // has been successfully opened. + // + + WdfInterruptSynchronize( + extension->WdfInterrupt, + SerialMarkOpen, + extension + ); + + return STATUS_SUCCESS; + +} + + +VOID +SerialEvtFileClose( + IN WDFFILEOBJECT FileObject + ) + +/*++ + + EvtFileClose is called when all the handles represented by the FileObject + is closed and all the references to FileObject is removed. This callback + may get called in an arbitrary thread context instead of the thread that + called CloseHandle. If you want to delete any per FileObject context that + must be done in the context of the user thread that made the Create call, + you should do that in the EvtDeviceCleanp callback. + +Arguments: + + FileObject - Pointer to fileobject that represents the open handle. + +Return Value: + + VOID + +--*/ + +{ + PAGED_CODE(); + + SerialFileCloseWorker(WdfFileObjectGetDevice(FileObject)); + return; +} + + +NTSTATUS +SerialWdmFileClose ( + IN WDFDEVICE Device, + IN PIRP Irp + ) +/*++ + +Routine Description: + + This is the dispatch routine for IRP_MJ_CLOSE. This is called when all the + handles represented by the FileObject is closed and all the references to + the FileObject is removed. + +Arguments: + + DeviceObject - Pointer to the device object for this device + Irp - Pointer to the IRP for the current request + +Return Value: + + NT status code + +--*/ +{ + SerialFileCloseWorker(Device); + + Irp->IoStatus.Information = 0L; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_SUCCESS; +} + + +VOID +SerialFileCloseWorker( + IN WDFDEVICE Device + ) +{ + ULONG flushCount; + + // + // This "timer value" is used to wait 10 character times + // after the hardware is empty before we actually "run down" + // all of the flow control/break junk. + // + LARGE_INTEGER tenCharDelay; + + // + // Holds a character time. + // + LARGE_INTEGER charTime; + + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(Device); + PSERIAL_INTERRUPT_CONTEXT interruptContext = SerialGetInterruptContext(extension->WdfInterrupt); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "In SerialEvtFileClose %wZ\n", + &extension->DeviceName); + + // + // Acquire the interrupt state lock. + // + WdfWaitLockAcquire(interruptContext->InterruptStateLock, NULL); + + // + // If the Interrupts are connected, then the hardware state has to be + // cleaned up now. Note that the EvtFileClose callback gets called for + // an open file object even though the interrupts have been disabled + // possibly due to a Surprise Remove PNP event. In such a case, the + // Interrupt object should not be used. + // + if (interruptContext->IsInterruptConnected) { + + charTime.QuadPart = -SerialGetCharTime(extension).QuadPart; + + // + // Do this now so that if the isr gets called it won't do anything + // to cause more chars to get sent. We want to run down the hardware. + // + + SetDeviceIsOpened(extension, FALSE, FALSE); + + // + // Synchronize with the isr to turn off break if it + // is already on. + // + + WdfInterruptSynchronize( + extension->WdfInterrupt, + SerialTurnOffBreak, + extension + ); + + // + // Wait a reasonable amount of time (20 * fifodepth) until all characters + // have been emptied out of the hardware. + // + + for (flushCount = (20 * 16); flushCount != 0; flushCount--) { + if ((READ_LINE_STATUS(extension, extension->Controller) & + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) != + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { + + KeDelayExecutionThread(KernelMode, FALSE, &charTime); + } else { + break; + } + } + + if (flushCount == 0) { + SerialMarkHardwareBroken(extension); + } + + // + // Synchronize with the ISR to let it know that interrupts are + // no longer important. + // + + WdfInterruptSynchronize( + extension->WdfInterrupt, + SerialMarkClose, + extension + ); + + + // + // If the driver has automatically transmitted an Xoff in + // the context of automatic receive flow control then we + // should transmit an Xon. + // + + if (extension->RXHolding & SERIAL_RX_XOFF) { + + // + // Loop until the holding register is empty. + // + while (!(READ_LINE_STATUS(extension, extension->Controller) & + SERIAL_LSR_THRE)) { + KeDelayExecutionThread( + KernelMode, + FALSE, + &charTime + ); + + } + + WRITE_TRANSMIT_HOLDING(extension, + extension->Controller, + extension->SpecialChars.XonChar + ); + + // + // Wait a reasonable amount of time for the characters + // to be emptied out of the hardware. + // + + for (flushCount = (20 * 16); flushCount != 0; flushCount--) { + if ((READ_LINE_STATUS(extension, extension->Controller) & + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) != + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { + KeDelayExecutionThread(KernelMode, FALSE, &charTime); + } else { + break; + } + } + + if (flushCount == 0) { + SerialMarkHardwareBroken(extension); + } + } + + + // + // The hardware is empty. Delay 10 character times before + // shut down all the flow control. + // + + tenCharDelay.QuadPart = charTime.QuadPart * 10; + + KeDelayExecutionThread( + KernelMode, + TRUE, + &tenCharDelay + ); + +#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "This warning is because we are calling interrupt synchronize routine directly.") + SerialClrDTR(extension->WdfInterrupt, extension); + + // + // We have to be very careful how we clear the RTS line. + // Transmit toggling might have been on at some point. + // + // We know that there is nothing left that could start + // out the "polling" execution path. We need to + // check the counter that indicates that the execution + // path is active. If it is then we loop delaying one + // character time. After each delay we check to see if + // the counter has gone to zero. When it has we know that + // the execution path should be just about finished. We + // make sure that we still aren't in the routine that + // synchronized execution with the ISR by synchronizing + // ourselve with the ISR. + // + + if (extension->CountOfTryingToLowerRTS) { + + do { +#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_HIGH, "This warning is due to suppressing the previous one.") + KeDelayExecutionThread( + KernelMode, + FALSE, + &charTime + ); + + } while (extension->CountOfTryingToLowerRTS); + + // + // The execution path should no longer exist that + // is trying to push down the RTS. Well just + // make sure it's down by falling through to + // code that forces it down. + // + + } + +#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "This warning is because we are calling interrupt synchronize routine directly.") + SerialClrRTS(extension->WdfInterrupt, extension); + + // + // Clean out the holding reasons (since we are closed). + // + + extension->RXHolding = 0; + extension->TXHolding = 0; + + // + // Mark device as not busy for WMI + // + + extension->WmiCommData.IsBusy = FALSE; + + } + + // + // Release the Interrupt state lock. + // + WdfWaitLockRelease(interruptContext->InterruptStateLock); + + // + // All is done. The port has been disabled from interrupting + // so there is no point in keeping the memory around. + // + + extension->BufferSize = 0; + if (extension->InterruptReadBuffer != NULL) { + ExFreePool(extension->InterruptReadBuffer); + } + extension->InterruptReadBuffer = NULL; + + // + // Make sure the wake is disabled. + // + ASSERT(!extension->IsWakeEnabled); + + SerialDrainTimersAndDpcs(extension); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_CREATE_CLOSE, "DPC's drained:\n"); + + // + // It's fine for the device to be powered off if there are no open handles. + // + WdfDeviceResumeIdle(Device); + + // + // It's okay to allow the device to be stopped or removed. + // + // Note to anyone copying this sample as a starting point: + // + // This works in this driver simply because this driver supports exactly + // one open handle at a time. If it supported more, then it would need + // counting logic to determine when all the reasons for failing Stop/Remove + // were gone. + // + WdfDeviceSetStaticStopRemove(Device, TRUE); + + return; + +} + +BOOLEAN +SerialMarkOpen( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine merely sets a boolean to true to mark the fact that + somebody opened the device and its worthwhile to pay attention + to interrupts. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + SerialReset(extension->WdfInterrupt, extension); + + // + // Prepare for the opening by re-enabling interrupts. + // + // We do this my modifying the OUT2 line in the modem control. + // In PC's this bit is "anded" with the interrupt line. + // + + WRITE_MODEM_CONTROL(extension, + extension->Controller, + (UCHAR)(READ_MODEM_CONTROL(extension, extension->Controller) | SERIAL_MCR_OUT2) + ); + + extension->DeviceIsOpened = TRUE; + extension->ErrorWord = 0; + + return FALSE; + +} + +VOID +SerialDrainUART(IN PSERIAL_DEVICE_EXTENSION PDevExt, + IN PLARGE_INTEGER PDrainTime) +{ + PAGED_CODE(); + + // + // Wait until all characters have been emptied out of the hardware. + // + + while ((READ_LINE_STATUS(PDevExt, PDevExt->Controller) & + (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) + != (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) { + KeDelayExecutionThread(KernelMode, FALSE, PDrainTime); + } +} + +VOID +SerialDisableUART(IN PVOID Context) + +/*++ + +Routine Description: + + This routine disables the UART and puts it in a "safe" state when + not in use (like a close or powerdown). + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION extension = Context; + + // + // Prepare for the closing by stopping interrupts. + // + // We do this by adjusting the OUT2 line in the modem control. + // In PC's this bit is "anded" with the interrupt line. + // + + WRITE_MODEM_CONTROL(extension, extension->Controller, + (UCHAR)(READ_MODEM_CONTROL(extension, extension->Controller) + & ~SERIAL_MCR_OUT2)); + + if (extension->FifoPresent) { + WRITE_FIFO_CONTROL(extension, extension->Controller, (UCHAR)0); + } +} + + + +BOOLEAN +SerialMarkClose( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine merely sets a boolean to false to mark the fact that + somebody closed the device and it's no longer worthwhile to pay attention + to interrupts. It also disables the UART. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + SerialDisableUART(Context); + extension->DeviceIsOpened = FALSE; + extension->DeviceState.Reopen = FALSE; + + return FALSE; + +} + +LARGE_INTEGER +SerialGetCharTime( + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + This function will return the number of 100 nanosecond intervals + there are in one character time (based on the present form + of flow control. + +Arguments: + + Extension - Just what it says. + +Return Value: + + 100 nanosecond intervals in a character time. + +--*/ + +{ + ULONG dataSize = 0; + ULONG paritySize; + ULONG stopSize; + ULONG charTime; + ULONG bitTime; + LARGE_INTEGER tmp; + + PAGED_CODE(); + + if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) { + dataSize = 5; + } else if ((Extension->LineControl & SERIAL_DATA_MASK) + == SERIAL_6_DATA) { + dataSize = 6; + } else if ((Extension->LineControl & SERIAL_DATA_MASK) + == SERIAL_7_DATA) { + dataSize = 7; + } else if ((Extension->LineControl & SERIAL_DATA_MASK) + == SERIAL_8_DATA) { + dataSize = 8; + } + + paritySize = 1; + if ((Extension->LineControl & SERIAL_PARITY_MASK) + == SERIAL_NONE_PARITY) { + + paritySize = 0; + + } + + if (Extension->LineControl & SERIAL_2_STOP) { + + // + // Even if it is 1.5, for sanities sake were going + // to say 2. + // + + stopSize = 2; + + } else { + + stopSize = 1; + + } + + // + // First we calculate the number of 100 nanosecond intervals + // are in a single bit time (Approximately). + // + + bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud; + charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime); + + tmp.QuadPart = charTime; + return tmp; + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/pnp.c b/tests/projects/windows/driver/kmdf/serial/pnp.c new file mode 100644 index 000000000..8773f30ac --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/pnp.c @@ -0,0 +1,2804 @@ +/*++ + +Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation + +Module Name: + + pnp.c + +Abstract: + + This module contains the code that handles the plug and play + IRPs for the serial driver. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" +#include +#include +#include + +#if defined(EVENT_TRACING) +#include "pnp.tmh" +#endif + +static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; +static const SUPPORTED_BAUD_RATES SupportedBaudRates[] = { + {75, SERIAL_BAUD_075}, + {110, SERIAL_BAUD_110}, + {135, SERIAL_BAUD_134_5}, + {150, SERIAL_BAUD_150}, + {300, SERIAL_BAUD_300}, + {600, SERIAL_BAUD_600}, + {1200, SERIAL_BAUD_1200}, + {1800, SERIAL_BAUD_1800}, + {2400, SERIAL_BAUD_2400}, + {4800, SERIAL_BAUD_4800}, + {7200, SERIAL_BAUD_7200}, + {9600, SERIAL_BAUD_9600}, + {14400, SERIAL_BAUD_14400}, + {19200, SERIAL_BAUD_19200}, + {38400, SERIAL_BAUD_38400}, + {56000, SERIAL_BAUD_56K}, + {57600, SERIAL_BAUD_57600}, + {115200, SERIAL_BAUD_115200}, + {128000, SERIAL_BAUD_128K}, + {SERIAL_BAUD_INVALID, SERIAL_BAUD_USER} + }; + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGESRP0, SerialEvtDeviceAdd) +#pragma alloc_text(PAGESRP0, SerialEvtPrepareHardware) +#pragma alloc_text(PAGESRP0, SerialEvtReleaseHardware) +#pragma alloc_text(PAGESRP0, SerialEvtDeviceD0ExitPreInterruptsDisabled) +#pragma alloc_text(PAGESRP0, SerialMapHWResources) +#pragma alloc_text(PAGESRP0, SerialUnmapHWResources) +#pragma alloc_text(PAGESRP0, SerialEvtDeviceContextCleanup) +#pragma alloc_text(PAGESRP0, SerialDoExternalNaming) +#pragma alloc_text(PAGESRP0, SerialReportMaxBaudRate) +#pragma alloc_text(PAGESRP0, SerialUndoExternalNaming) +#pragma alloc_text(PAGESRP0, SerialInitController) +#pragma alloc_text(PAGESRP0, SerialGetMappedAddress) +#pragma alloc_text(PAGESRP0, SerialSetPowerPolicy) +#pragma alloc_text(PAGESRP0, SerialReadSymName) + +#endif // ALLOC_PRAGMA + +PVOID LocalMmMapIoSpace( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ SIZE_T NumberOfBytes + ) +{ + typedef + PVOID + (*PFN_MM_MAP_IO_SPACE_EX) ( + _In_ PHYSICAL_ADDRESS PhysicalAddress, + _In_ SIZE_T NumberOfBytes, + _In_ ULONG Protect + ); + + UNICODE_STRING name; + PFN_MM_MAP_IO_SPACE_EX pMmMapIoSpaceEx; + + RtlInitUnicodeString(&name, L"MmMapIoSpaceEx"); + pMmMapIoSpaceEx = (PFN_MM_MAP_IO_SPACE_EX) (ULONG_PTR)MmGetSystemRoutineAddress(&name); + + if (pMmMapIoSpaceEx != NULL){ + // + // Call WIN10 API if available + // + return pMmMapIoSpaceEx(PhysicalAddress, + NumberOfBytes, + PAGE_READWRITE | PAGE_NOCACHE); + } + + // + // Supress warning that MmMapIoSpace allocates executable memory. + // This function is only used if the preferred API, MmMapIoSpaceEx + // is not present. MmMapIoSpaceEx is available starting in WIN10. + // + #pragma warning(suppress: 30029) + return MmMapIoSpace(PhysicalAddress, NumberOfBytes, MmNonCached); +} + +NTSTATUS +SerialEvtDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ) +/*++ + +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. + + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ + +{ + NTSTATUS status; + PSERIAL_DEVICE_EXTENSION pDevExt; + static ULONG currentInstance = 0; + WDF_FILEOBJECT_CONFIG fileobjectConfig; + WDFDEVICE device; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDF_OBJECT_ATTRIBUTES attributes; + WDF_IO_QUEUE_CONFIG queueConfig; + WDFQUEUE defaultqueue; + ULONG isMulti; + PULONG countSoFar; + WDF_INTERRUPT_CONFIG interruptConfig; + PSERIAL_INTERRUPT_CONTEXT interruptContext; + ULONG relinquishPowerPolicy; + + DECLARE_UNICODE_STRING_SIZE(deviceName, DEVICE_OBJECT_NAME_LENGTH); + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "-->SerialEvtDeviceAdd\n"); + + status = RtlUnicodeStringPrintf(&deviceName, L"%ws%u", + L"\\Device\\Serial", + currentInstance++); + + + if (!NT_SUCCESS(status)) { + return status; + } + + status = WdfDeviceInitAssignName(DeviceInit,& deviceName); + if (!NT_SUCCESS(status)) { + return status; + } + + WdfDeviceInitSetExclusive(DeviceInit, TRUE); + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SERIAL_PORT); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); + + WdfDeviceInitSetRequestAttributes(DeviceInit, &attributes); + + // + // Zero out the PnpPowerCallbacks structure. + // + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + + // + // Set Callbacks for any of the functions we are interested in. + // If no callback is set, Framework will take the default action + // by itself. These next two callbacks set up and tear down hardware state, + // specifically that which only has to be done once. + // + + pnpPowerCallbacks.EvtDevicePrepareHardware = SerialEvtPrepareHardware; + pnpPowerCallbacks.EvtDeviceReleaseHardware = SerialEvtReleaseHardware; + + // + // These two callbacks set up and tear down hardware state that must be + // done every time the device moves in and out of the D0-working state. + // + + pnpPowerCallbacks.EvtDeviceD0Entry = SerialEvtDeviceD0Entry; + pnpPowerCallbacks.EvtDeviceD0Exit = SerialEvtDeviceD0Exit; + + // + // Specify the callback for monitoring when the device's interrupt are + // enabled or about to be disabled. + // + + pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = SerialEvtDeviceD0EntryPostInterruptsEnabled; + pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = SerialEvtDeviceD0ExitPreInterruptsDisabled; + + // + // Register the PnP and power callbacks. + // + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + if ( !NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceInitSetPnpPowerEventCallbacks failed %!STATUS!\n", + status); + return status; + } + + // + // Find out if we own power policy + // + SerialGetFdoRegistryKeyValue( DeviceInit, + L"SerialRelinquishPowerPolicy", + &relinquishPowerPolicy ); + + if(relinquishPowerPolicy) { + // + // FDO's are assumed to be power policy owner by default. So tell + // the framework explicitly to relinquish the power policy ownership. + // + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "RelinquishPowerPolicy due to registry settings\n"); + + WdfDeviceInitSetPowerPolicyOwnership(DeviceInit, FALSE); + } + + // + // For Windows XP and below, we will register for the WDM Preprocess callback + // for IRP_MJ_CREATE. This is done because, the Serenum filter doesn't handle + // creates that are marked pending. Since framework always marks the IRP pending, + // we are registering this WDM preprocess handler so that we can bypass the + // framework and handle the create and close ourself. This workaround is need + // only if you intend to install the Serenum as an upper filter. + // + if (RtlIsNtDdiVersionAvailable(NTDDI_VISTA) == FALSE) { + + status = WdfDeviceInitAssignWdmIrpPreprocessCallback( + DeviceInit, + SerialWdmDeviceFileCreate, + IRP_MJ_CREATE, + NULL, // pointer minor function table + 0); // number of entries in the table + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", + status); + return status; + } + + status = WdfDeviceInitAssignWdmIrpPreprocessCallback( + DeviceInit, + SerialWdmFileClose, + IRP_MJ_CLOSE, + NULL, // pointer minor function table + 0); // number of entries in the table + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", + status); + return status; + } + + } else { + + // + // FileEvents can opt for Device level synchronization only if the ExecutionLevel + // of the Device is passive. Since we can't choose passive execution-level for + // device because we have chose to synchronize timers & dpcs with the device, + // we will opt out of synchonization with the device for fileobjects. + // Note: If the driver has to synchronize Create with the other I/O events, + // it can create a queue and configure-dispatch create requests to the queue. + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.SynchronizationScope = WdfSynchronizationScopeNone; + + // + // Set Entry points for Create and Close.. + // + WDF_FILEOBJECT_CONFIG_INIT( + &fileobjectConfig, + SerialEvtDeviceFileCreate, + SerialEvtFileClose, + WDF_NO_EVENT_CALLBACK // Cleanup + ); + + WdfDeviceInitSetFileObjectConfig( + DeviceInit, + &fileobjectConfig, + &attributes + ); + } + + + // + // Since framework queues doesn't handle IRP_MJ_FLUSH_BUFFERS, + // IRP_MJ_QUERY_INFORMATION and IRP_MJ_SET_INFORMATION requests, + // we will register a preprocess callback to handle them. + // + status = WdfDeviceInitAssignWdmIrpPreprocessCallback( + DeviceInit, + SerialFlush, + IRP_MJ_FLUSH_BUFFERS, + NULL, // pointer minor function table + 0); // number of entries in the table + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", + status); + return status; + } + + status = WdfDeviceInitAssignWdmIrpPreprocessCallback( + DeviceInit, + SerialQueryInformationFile, + IRP_MJ_QUERY_INFORMATION, + NULL, // pointer minor function table + 0); // number of entries in the table + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", + status); + return status; + } + status = WdfDeviceInitAssignWdmIrpPreprocessCallback( + DeviceInit, + SerialSetInformationFile, + IRP_MJ_SET_INFORMATION, + NULL, // pointer minor function table + 0); // number of entries in the table + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceInitAssignWdmIrpPreprocessCallback failed %!STATUS!\n", + status); + return status; + } + + + // + // Create a device + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (&attributes, + SERIAL_DEVICE_EXTENSION); + // + // Provide a callback to cleanup the context. This will be called + // when the device is removed. + // + attributes.EvtCleanupCallback = SerialEvtDeviceContextCleanup; + // + // By opting for SynchronizationScopeDevice, we tell the framework to + // synchronize callbacks events of all the objects directly associated + // with the device. In this driver, we will associate queues, dpcs, + // and timers. By doing that we don't have to worrry about synchronizing + // access to device-context by Io Events, cancel-routine, timer and dpc + // callbacks. + // + attributes.SynchronizationScope = WdfSynchronizationScopeDevice; + + status = WdfDeviceCreate(&DeviceInit, &attributes, &device); + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "SerialAddDevice - WdfDeviceCreate failed %!STATUS!\n", + status); + return status; + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "Created device (%p) %wZ\n", device, &deviceName); + + pDevExt = SerialGetDeviceExtension (device); + + pDevExt->DriverObject = WdfDriverWdmGetDriverObject(Driver); + + // + // This sample doesn't support multiport serial devices. + // Multiport devices allow other pseudo-serial devices with extra + // resources to specify another range of I/O ports. + // + if(!SerialGetRegistryKeyValue(device, L"MultiportDevice", &isMulti)) { + isMulti = 0; + } + + if(isMulti) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "This sample doesn't support multiport devices\n"); + return STATUS_DEVICE_CONFIGURATION_ERROR; + } + + // + // Set up the device extension. + // + + pDevExt = SerialGetDeviceExtension (device); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "AddDevice PDO(0x%p) FDO(0x%p), Lower(0x%p) DevExt (0x%p)\n", + WdfDeviceWdmGetPhysicalDevice (device), + WdfDeviceWdmGetDeviceObject (device), + WdfDeviceWdmGetAttachedDevice(device), + pDevExt); + + pDevExt->DeviceIsOpened = FALSE; + pDevExt->DeviceObject = WdfDeviceWdmGetDeviceObject(device); + pDevExt->WdfDevice = device; + + pDevExt->TxFifoAmount = driverDefaults.TxFIFODefault; + pDevExt->UartRemovalDetect = driverDefaults.UartRemovalDetect; + pDevExt->CreatedSymbolicLink = FALSE; + pDevExt->OwnsPowerPolicy = relinquishPowerPolicy ? FALSE : TRUE; + + status = SerialSetPowerPolicy(pDevExt); + if(!NT_SUCCESS(status)){ + return status; + } + + // + // We create four manual queues below. + // Read Queue..(how about using serial queue for read). Since requests + // jump from queue to queue, we cannot configure the queues to receive a + // particular type of request. For example, some of the IOCTLs end up + // in read and write queue. + // + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, + WdfIoQueueDispatchManual); + + queueConfig.EvtIoStop = SerialEvtIoStop; + queueConfig.EvtIoResume = SerialEvtIoResume; + queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; + + status = WdfIoQueueCreate (device, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &pDevExt->ReadQueue + ); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Read failed %!STATUS!\n", status); + return status; + } + + // + // Write Queue.. + // + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, + WdfIoQueueDispatchManual); + + queueConfig.EvtIoStop = SerialEvtIoStop; + queueConfig.EvtIoResume = SerialEvtIoResume; + queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; + + status = WdfIoQueueCreate (device, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &pDevExt->WriteQueue + ); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Write failed %!STATUS!\n", status); + return status; + } + + // + // Mask Queue... + // + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, + WdfIoQueueDispatchManual + ); + + queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; + + queueConfig.EvtIoStop = SerialEvtIoStop; + queueConfig.EvtIoResume = SerialEvtIoResume; + + status = WdfIoQueueCreate (device, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &pDevExt->MaskQueue + ); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Mask failed %!STATUS!\n", status); + return status; + } + + // + // Purge Queue.. + // + WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, + WdfIoQueueDispatchManual + ); + + queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; + + queueConfig.EvtIoStop = SerialEvtIoStop; + queueConfig.EvtIoResume = SerialEvtIoResume; + + status = WdfIoQueueCreate (device, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &pDevExt->PurgeQueue + ); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfIoQueueCreate for Purge failed %!STATUS!\n", status); + return status; + } + + // + // All the incoming I/O requests are routed to the default queue and dispatch to the + // appropriate callback events. These callback event will check to see if another + // request is currently active. If so then it will forward it to other manual queues. + // All the queues are auto managed by the framework in response to the PNP + // and Power events. + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( + &queueConfig, + WdfIoQueueDispatchParallel + ); + queueConfig.EvtIoRead = SerialEvtIoRead; + queueConfig.EvtIoWrite = SerialEvtIoWrite; + queueConfig.EvtIoDeviceControl = SerialEvtIoDeviceControl; + queueConfig.EvtIoInternalDeviceControl = SerialEvtIoInternalDeviceControl; + queueConfig.EvtIoCanceledOnQueue = SerialEvtCanceledOnQueue; + + queueConfig.EvtIoStop = SerialEvtIoStop; + queueConfig.EvtIoResume = SerialEvtIoResume; + + status = WdfIoQueueCreate(device, + &queueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &defaultqueue + ); + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed %!STATUS!\n", status); + return status; + } + + // + // Create WDFINTERRUPT object. Let us leave the ShareVector to default value and + // let the framework decide whether to share the interrupt or not based on the + // ShareDisposition provided by the bus driver in the resource descriptor. + // + + WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, + SerialISR, + NULL); + + interruptConfig.EvtInterruptDisable = SerialEvtInterruptDisable; + interruptConfig.EvtInterruptEnable = SerialEvtInterruptEnable; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, SERIAL_INTERRUPT_CONTEXT); + + status = WdfInterruptCreate(device, + &interruptConfig, + &attributes, + &pDevExt->WdfInterrupt); + + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't create interrupt for %wZ\n", + &pDevExt->DeviceName); + return status; + } + + // + // Interrupt state wait lock... + // + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = pDevExt->WdfInterrupt; + + interruptContext = SerialGetInterruptContext(pDevExt->WdfInterrupt); + + status = WdfWaitLockCreate(&attributes, + &interruptContext->InterruptStateLock + ); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, " WdfWaitLockCreate for InterruptStateLock failed %!STATUS!\n", status); + return status; + } + + // + // Set interrupt policy + // + SerialSetInterruptPolicy(pDevExt->WdfInterrupt); + + // + // Timers and DPCs... + // + status = SerialCreateTimersAndDpcs(pDevExt); + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "SerialCreateTimersAndDpcs failed %x\n", status); + return status; + } + + // + // Register with WMI. + // + status = SerialWmiRegistration(device); + if(!NT_SUCCESS (status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "SerialWmiRegistration failed %!STATUS!\n", status); + return status; + + } + + // + // Upto this point, if we fail, we don't have to worry about freeing any resource because + // framework will free all the objects. + // + // + // Do the external naming. + // + + status = SerialDoExternalNaming(pDevExt); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "External Naming Failed - Status %!STATUS!\n", + status); + return status; + } + + // + // Finally increment the global system configuration that keeps track of number of serial ports. + // + countSoFar = &IoGetConfigurationInformation()->SerialCount; + (*countSoFar)++; + pDevExt->IsSystemConfigInfoUpdated = TRUE; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<--SerialEvtDeviceAdd\n"); + + return status; + +} +#pragma warning(push) +#pragma warning(disable:28118) // this callback will run at IRQL=PASSIVE_LEVEL +_Use_decl_annotations_ +VOID +SerialEvtDeviceContextCleanup ( + WDFOBJECT Device + ) +/*++ + +Routine Description: + + EvtDeviceContextCleanup event callback cleans up anything done in + EvtDeviceAdd, except those things that are automatically cleaned + up by the Framework. + + In a driver derived from this sample, it's quite likely that this function could + be deleted. + +Arguments: + + Device - Handle to a framework device object. + +Return Value: + + VOID + +--*/ +{ + PSERIAL_DEVICE_EXTENSION deviceExtension; + PULONG countSoFar; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialDeviceContextCleanup\n"); + + PAGED_CODE(); + + deviceExtension = SerialGetDeviceExtension (Device); + + if (deviceExtension->InterruptReadBuffer != NULL) { + ExFreePool(deviceExtension->InterruptReadBuffer); + deviceExtension->InterruptReadBuffer = NULL; + } + + // + // Update the global configuration count for serial device. + // + if(deviceExtension->IsSystemConfigInfoUpdated) { + countSoFar = &IoGetConfigurationInformation()->SerialCount; + (*countSoFar)--; + } + + SerialUndoExternalNaming(deviceExtension); + + return; +} +#pragma warning(pop) // enable 28118 again + +NTSTATUS +SerialEvtPrepareHardware( + WDFDEVICE Device, + WDFCMRESLIST Resources, + WDFCMRESLIST ResourcesTranslated + ) +/*++ + +Routine Description: + + SerialEvtPrepareHardware event callback performs operations that are necessary + to make the device operational. The framework calls the driver's + SerialEvtPrepareHardware callback when the PnP manager sends an IRP_MN_START_DEVICE + request to the driver stack. + +Arguments: + + Device - Handle to a framework device object. + + Resources - Handle to a collection of framework resource objects. + This collection identifies the raw (bus-relative) hardware + resources that have been assigned to the device. + + ResourcesTranslated - Handle to a collection of framework resource objects. + This collection identifies the translated (system-physical) + hardware resources that have been assigned to the device. + The resources appear from the CPU's point of view. + Use this list of resources to map I/O space and + device-accessible memory into virtual address space + +Return Value: + + WDF status code + +--*/ +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + NTSTATUS status; + CONFIG_DATA config; + PCONFIG_DATA pConfig = &config; + ULONG defaultClockRate = 1843200; + + PAGED_CODE(); + + SerialDbgPrintEx (TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialEvtPrepareHardware\n"); + // + // Get the Device Extension.. + // + pDevExt = SerialGetDeviceExtension (Device); + + RtlZeroMemory(pConfig, sizeof(CONFIG_DATA)); + + // + // Initialize a config data structure with default values for those that + // may not already be initialized. + // + + pConfig->LogFifo = driverDefaults.LogFifoDefault; + + + // + // Get the hw resources for the device. + // + + status = SerialMapHWResources(Device, Resources, ResourcesTranslated, pConfig); + + if (!NT_SUCCESS(status)) { + goto End; + } + + // + // Open the "Device Parameters" section of registry for this device and get parameters. + // + + if(!SerialGetRegistryKeyValue (Device, + L"DisablePort", + &pConfig->DisablePort)){ + pConfig->DisablePort = 0; + } + + if(!SerialGetRegistryKeyValue (Device, + L"ForceFifoEnable", + &pConfig->ForceFifoEnable)){ + pConfig->ForceFifoEnable = driverDefaults.ForceFifoEnableDefault; + } + + if(!SerialGetRegistryKeyValue (Device, + L"RxFIFO", + &pConfig->RxFIFO)){ + pConfig->RxFIFO = driverDefaults.RxFIFODefault; + } + + if(!SerialGetRegistryKeyValue (Device, + L"TxFIFO", + &pConfig->TxFIFO)){ + pConfig->TxFIFO = driverDefaults.TxFIFODefault; + } + + if(!SerialGetRegistryKeyValue (Device, + L"Share System Interrupt", + &pConfig->PermitShare)){ + pConfig->PermitShare = driverDefaults.PermitShareDefault; + } + + if(!SerialGetRegistryKeyValue (Device, + L"ClockRate", + &pConfig->ClockRate)) { + pConfig->ClockRate = defaultClockRate; + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Com Port ClockRate: %x\n", + pConfig->ClockRate); + + if(!SerialGetRegistryKeyValue(Device, + L"TL16C550C Auto Flow Control", + &pConfig->TL16C550CAFC)){ + pConfig->TL16C550CAFC = 0; + } + + status = SerialInitController(pDevExt, pConfig); + + if (NT_SUCCESS(status)) { + } +End: + + SerialDbgPrintEx (TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialEvtPrepareHardware 0x%x\n", status); + + return status; +} + +NTSTATUS +SerialEvtReleaseHardware( + IN WDFDEVICE Device, + IN WDFCMRESLIST ResourcesTranslated + ) +/*++ + +Routine Description: + + EvtDeviceReleaseHardware is called by the framework whenever the PnP manager + is revoking ownership of our resources. This may be in response to either + IRP_MN_STOP_DEVICE or IRP_MN_REMOVE_DEVICE. The callback is made before + passing down the IRP to the lower driver. + + In this callback, do anything necessary to free those resources. + In this driver, we will not receive this callback when there is open handle to + the device. We explicitly tell the framework (WdfDeviceSetStaticStopRemove) to + fail stop and query-remove when handle is open. + +Arguments: + + Device - Handle to a framework device object. + + ResourcesTranslated - Handle to a collection of framework resource objects. + This collection identifies the translated (system-physical) + hardware resources that have been assigned to the device. + The resources appear from the CPU's point of view. + Use this list of resources to map I/O space and + device-accessible memory into virtual address space + +Return Value: + + NTSTATUS - Failures will be logged, but not acted on. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + + UNREFERENCED_PARAMETER(ResourcesTranslated); + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "--> SerialEvtReleaseHardware\n"); + + pDevExt = SerialGetDeviceExtension (Device); + + // + // Reset and put the device into a known initial state before releasing the hw resources. + // In this driver we can recieve this callback only when there is no handle open because + // we tell the framework to disable stop by calling WdfDeviceSetStaticStopRemove. + // Since we have already reset the device in our close handler, we don't have to + // do anything other than unmapping the I/O resources. + // + + // + // Unmap any Memory-Mapped registers. Disconnecting from the interrupt will + // be done automatically by the framework. + // + SerialUnmapHWResources(pDevExt); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "<-- SerialEvtReleaseHardware\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +SerialEvtDeviceD0EntryPostInterruptsEnabled( + IN WDFDEVICE Device, + IN WDF_POWER_DEVICE_STATE PreviousState + ) +/*++ + +Routine Description: + + EvtDeviceD0EntryPostInterruptsEnabled is called by the framework after the + driver has enabled the device's hardware interrupts. + + This function is not marked pageable because this function is in the + device power up path. When a function is marked pagable and the code + section is paged out, it will generate a page fault which could impact + the fast resume behavior because the client driver will have to wait + until the system drivers can service this page fault. + +Arguments: + + Device - Handle to a framework device object. + + PreviousState - A WDF_POWER_DEVICE_STATE-typed enumerator that identifies + the previous device power state. + +Return Value: + + NTSTATUS - Failures will be logged, but not acted on. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(Device); + PSERIAL_INTERRUPT_CONTEXT interruptContext = SerialGetInterruptContext(extension->WdfInterrupt); + WDF_INTERRUPT_INFO info; + + UNREFERENCED_PARAMETER(PreviousState); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "--> SerialEvtDeviceD0EntryPostInterruptsEnabled\n"); + // + // The following lines of code show how to call WdfInterruptGetInfo. + // + WDF_INTERRUPT_INFO_INIT(&info); + WdfInterruptGetInfo(extension->WdfInterrupt, &info); + + WdfWaitLockAcquire(interruptContext->InterruptStateLock, NULL); + interruptContext->IsInterruptConnected = TRUE; + WdfWaitLockRelease(interruptContext->InterruptStateLock); + + return STATUS_SUCCESS; +} + + +NTSTATUS +SerialEvtDeviceD0ExitPreInterruptsDisabled( + IN WDFDEVICE Device, + IN WDF_POWER_DEVICE_STATE TargetState + ) +/*++ + +Routine Description: + + EvtDeviceD0ExitPreInterruptsDisabled is called by the framework before the + driver disables the device's hardware interrupts. + +Arguments: + + Device - Handle to a framework device object. + + TargetState - A WDF_POWER_DEVICE_STATE-typed enumerator that identifies the + device power state that the device is about to enter. + +Return Value: + + NTSTATUS - Failures will be logged, but not acted on. + +--*/ +{ + PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension(Device); + PSERIAL_INTERRUPT_CONTEXT interruptContext = SerialGetInterruptContext(extension->WdfInterrupt); + + UNREFERENCED_PARAMETER(TargetState); + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "--> SerialEvtDeviceD0ExitPreInterruptsDisabled\n"); + + WdfWaitLockAcquire(interruptContext->InterruptStateLock, NULL); + interruptContext->IsInterruptConnected = FALSE; + WdfWaitLockRelease(interruptContext->InterruptStateLock); + + return STATUS_SUCCESS; +} + + +NTSTATUS +SerialSetPowerPolicy( + IN PSERIAL_DEVICE_EXTENSION DeviceExtension + ) +{ + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; + //WDF_POWER_POLICY_EVENT_CALLBACKS powerPolicyCallbacks; + NTSTATUS status = STATUS_SUCCESS; + WDFDEVICE hDevice = DeviceExtension->WdfDevice; + ULONG powerOnClose; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "--> SerialSetPowerPolicy\n"); + + PAGED_CODE(); + + // + // Find out whether we want to power down the device when there no handles open. + // + SerialGetRegistryKeyValue(hDevice, L"EnablePowerManagement", &powerOnClose); + DeviceExtension->RetainPowerOnClose = powerOnClose ? TRUE : FALSE; + + // + // In some drivers, the device must be specifically programmed to enable + // wake signals. UARTs were designed long, long before such a concept. So + // this driver, which just drives UARTs, doesn't register wake arm/disarm + // callbacks. Arming or disarming for UARTs has to be handled by side-band + // code that controls hardware designed more recently. In this case, ACPI + // is handling it. If one were to write a driver which implemented a more + // modern serial device, one might need to use these callbacks. + // + + // + // Init the power policy callbacks + // + //WDF_POWER_POLICY_EVENT_CALLBACKS_INIT(&powerPolicyCallbacks); + + // + // This group of three callbacks allows this sample driver to manage + // arming the device for wake from the S0 state. + // + + //powerPolicyCallbacks.EvtDeviceArmWakeFromS0 = SerialEvtDeviceWakeArmS0; + //powerPolicyCallbacks.EvtDeviceDisarmWakeFromS0 = SerialEvtDeviceWakeDisarmS0; + //powerPolicyCallbacks.EvtDeviceWakeFromS0Triggered = SerialEvtDeviceWakeTriggeredS0; + + // + // This group of three callbacks allows the device to be armed for wake + // from Sx (S1, S2, S3 or S4.) Networking devices can optionally be put + // into a state where a packet sent to them will cause the device's wake + // signal to be triggered, which causes the machine to wake, moving back + // into the S0 state. + // + + //powerPolicyCallbacks.EvtDeviceArmWakeFromSx = SerialEvtDeviceWakeArmSx; + //powerPolicyCallbacks.EvtDeviceDisarmWakeFromSx = SerialEvtDeviceWakeDisarmSx; + //powerPolicyCallbacks.EvtDeviceWakeFromSxTriggered = SerialEvtDeviceWakeTriggeredSx; + + // + // Register the power policy callbacks. + // + //WdfDeviceSetPowerPolicyEventCallbacks(hDevice, &powerPolicyCallbacks); + + // + // Init the idle policy structure. By setting IdleCannotWakeFromS0 we tell the framework + // to power down the device without arming for wake. The only way the device can come + // back to D0 is when we call WdfDeviceStopIdle in SerialEvtDeviceFileCreate. + // We can't choose IdleCanWakeFromS0 by default is because onboard serial ports typically + // don't have wake capability. If the driver is used for plugin boards that does support + // wait-wake, you can update the settings to match that. If MS provided modem driver + // is used on ports that does support wake on ring, then it will update the settings + // by sending an internal ioctl to us. + // + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); + if(DeviceExtension->OwnsPowerPolicy && !DeviceExtension->RetainPowerOnClose) { + // + // Since we don't have to retain power when there are no open handles, we + // register for idle power management to save power. Check the use of + // WdfDeviceStopIdle in SerialEvtDeviceFileCreate. + // + idleSettings.UserControlOfIdleSettings = IdleAllowUserControl; + + status = WdfDeviceAssignS0IdleSettings(hDevice, &idleSettings); + if ( !NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "WdfDeviceSetPowerPolicyS0IdlePolicy failed %x \n", status); + return status; + } + } + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialSetPowerPolicy\n"); + + return status; +} + +UINT32 +SerialReportMaxBaudRate(ULONG Bauds) +/*++ + +Routine Description: + + This routine returns the max baud rate given a selection of rates + +Arguments: + + Bauds - Bit-encoded list of supported bauds + + + Return Value: + + The max baud rate listed in Bauds + +--*/ +{ + int i; + + PAGED_CODE(); + + for(i=0; SupportedBaudRates[i].BaudRate != SERIAL_BAUD_INVALID; i++) { + + if(Bauds & SupportedBaudRates[i].Mask) { + return SupportedBaudRates[i].BaudRate; + } + } + + // + // We're in bad shape + // + + return 0; +} + +NTSTATUS +SerialInitController( + IN PSERIAL_DEVICE_EXTENSION pDevExt, + IN PCONFIG_DATA PConfigData + ) +/*++ + +Routine Description: + + Really too many things to mention here. In general initializes + kernel synchronization structures, allocates the typeahead buffer, + sets up defaults, etc. + +Arguments: + + PDevObj - Device object for the device to be started + + PConfigData - Pointer to a record for a single port. + +Return Value: + + STATUS_SUCCCESS if everything went ok. A !NT_SUCCESS status + otherwise. + +--*/ + +{ + NTSTATUS status = STATUS_SUCCESS; + SHORT junk; + int i; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialInitController for %wZ\n", + &pDevExt->DeviceName); + + // + // Save the value of clock input to the part. We use this to calculate + // the divisor latch value. The value is in Hertz. + // + + pDevExt->ClockRate = PConfigData->ClockRate; + + + // + // Save if we have to enable TI's auto flow control + // + + + pDevExt->TL16C550CAFC = PConfigData->TL16C550CAFC; + + + // + // Map the memory for the control registers for the serial device + // into virtual memory. + // + pDevExt->Controller = + SerialGetMappedAddress(PConfigData->TrController, + PConfigData->SpanOfController, + (BOOLEAN)PConfigData->AddressSpace, + &pDevExt->UnMapRegisters); + + + if (!pDevExt->Controller) { + + SerialLogError( + pDevExt->DriverObject, + pDevExt->DeviceObject, + PConfigData->TrController, + SerialPhysicalZero, + 0, + 0, + 0, + 7, + STATUS_SUCCESS, + SERIAL_REGISTERS_NOT_MAPPED, + pDevExt->DeviceName.Length+sizeof(WCHAR), + pDevExt->DeviceName.Buffer, + 0, + NULL + ); + + SerialDbgPrintEx(TRACE_LEVEL_WARNING, DBG_PNP, "Could not map memory for device " + "registers for %wZ\n", &pDevExt->DeviceName); + + pDevExt->UnMapRegisters = FALSE; + status = STATUS_NONE_MAPPED; + goto ExtensionCleanup; + + } + + pDevExt->AddressSpace = PConfigData->AddressSpace; + pDevExt->SpanOfController = PConfigData->SpanOfController; + + // + // Save off the interface type and the bus number. + // + + pDevExt->Vector = PConfigData->TrVector; + pDevExt->Irql = (UCHAR)PConfigData->TrIrql; + pDevExt->InterruptMode = PConfigData->InterruptMode; + pDevExt->Affinity = PConfigData->Affinity; + + // + // If the user said to permit sharing within the device, propagate this + // through. + // + + pDevExt->PermitShare = PConfigData->PermitShare; + + + // + // Before we test whether the port exists (which will enable the FIFO) + // convert the rx trigger value to what should be used in the register. + // + // If a bogus value was given - crank them down to 1. + // + // If this is a "souped up" UART with like a 64 byte FIFO, they + // should use the appropriate "spoofing" value to get the desired + // results. I.e., if on their chip 0xC0 in the FCR is for 64 bytes, + // they should specify 14 in the registry. + // + + switch (PConfigData->RxFIFO) { + + case 1: + + pDevExt->RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER; + break; + + case 4: + + pDevExt->RxFifoTrigger = SERIAL_4_BYTE_HIGH_WATER; + break; + + case 8: + + pDevExt->RxFifoTrigger = SERIAL_8_BYTE_HIGH_WATER; + break; + + case 14: + + pDevExt->RxFifoTrigger = SERIAL_14_BYTE_HIGH_WATER; + break; + + default: + + pDevExt->RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER; + break; + + } + + + if (PConfigData->TxFIFO < 1) { + + pDevExt->TxFifoAmount = 1; + + } else { + + pDevExt->TxFifoAmount = PConfigData->TxFIFO; + + } + + if (!SerialDoesPortExist( + pDevExt, + &pDevExt->DeviceName, + PConfigData->ForceFifoEnable, + PConfigData->LogFifo + )) { + + // + // We couldn't verify that there was actually a + // port. No need to log an error as the port exist + // code will log exactly why. + // + + SerialDbgPrintEx(TRACE_LEVEL_WARNING, DBG_PNP, "DoesPortExist test failed for " + "%wZ\n", &pDevExt->DeviceName); + + status = STATUS_NO_SUCH_DEVICE; + goto ExtensionCleanup; + + } + + + // + // If the user requested that we disable the port, then + // do it now. Log the fact that the port has been disabled. + // + + if (PConfigData->DisablePort) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "disabled port %wZ as requested in " + "configuration\n", &pDevExt->DeviceName); + + status = STATUS_NO_SUCH_DEVICE; + + SerialLogError( + pDevExt->DriverObject, + pDevExt->DeviceObject, + PConfigData->TrController, + SerialPhysicalZero, + 0, + 0, + 0, + 57, + STATUS_SUCCESS, + SERIAL_DISABLED_PORT, + pDevExt->DeviceName.Length+sizeof(WCHAR), + pDevExt->DeviceName.Buffer, + 0, + NULL + ); + + goto ExtensionCleanup; + + } + + + + // + // Set up the default device control fields. + // Note that if the values are changed after + // the file is open, they do NOT revert back + // to the old value at file close. + // + + pDevExt->SpecialChars.XonChar = SERIAL_DEF_XON; + pDevExt->SpecialChars.XoffChar = SERIAL_DEF_XOFF; + pDevExt->HandFlow.ControlHandShake = SERIAL_DTR_CONTROL; + pDevExt->HandFlow.FlowReplace = SERIAL_RTS_CONTROL; + + + // + // Default Line control protocol. 7E1 + // + // Seven data bits. + // Even parity. + // 1 Stop bits. + // + + pDevExt->LineControl = SERIAL_7_DATA | + SERIAL_EVEN_PARITY | + SERIAL_NONE_PARITY; + + pDevExt->ValidDataMask = 0x7f; + pDevExt->CurrentBaud = 1200; + + + // + // We set up the default xon/xoff limits. + // + // This may be a bogus value. It looks like the BufferSize + // is not set up until the device is actually opened. + // + + pDevExt->HandFlow.XoffLimit = pDevExt->BufferSize >> 3; + pDevExt->HandFlow.XonLimit = pDevExt->BufferSize >> 1; + + pDevExt->BufferSizePt8 = ((3*(pDevExt->BufferSize>>2))+ + (pDevExt->BufferSize>>4)); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, " The default interrupt read buffer size is: %d\n" + "------ The XoffLimit is : %d\n" + "------ The XonLimit is : %d\n" + "------ The pt 8 size is : %d\n", + pDevExt->BufferSize, pDevExt->HandFlow.XoffLimit, + pDevExt->HandFlow.XonLimit, pDevExt->BufferSizePt8); + + + // + // Go through all the "named" baud rates to find out which ones + // can be supported with this port. + // + // + + pDevExt->SupportedBauds = SERIAL_BAUD_USER; + + + for(i=0; SupportedBaudRates[i].BaudRate != SERIAL_BAUD_INVALID; i++) { + + if (!NT_ERROR(SerialGetDivisorFromBaud( + pDevExt->ClockRate, + (LONG)SupportedBaudRates[i].BaudRate, + &junk + ))) { + + pDevExt->SupportedBauds |= SupportedBaudRates[i].Mask; + } + } + + + + + // + // Mark this device as not being opened by anyone. We keep a + // variable around so that spurious interrupts are easily + // dismissed by the ISR. + // + + SetDeviceIsOpened(pDevExt, FALSE, FALSE); + + // + // Store values into the extension for interval timing. + // + + // + // If the interval timer is less than a second then come + // in with a short "polling" loop. + // + // For large (> then 2 seconds) use a 1 second poller. + // + + pDevExt->ShortIntervalAmount.QuadPart = -1; + pDevExt->LongIntervalAmount.QuadPart = -10000000; + pDevExt->CutOverAmount.QuadPart = 200000000; + + DISABLE_ALL_INTERRUPTS (pDevExt, pDevExt->Controller); + + WRITE_MODEM_CONTROL(pDevExt, pDevExt->Controller, (UCHAR)0); + + // make sure there is no escape character currently set + pDevExt->EscapeChar = 0; + // + // This should set up everything as it should be when + // a device is to be opened. We do need to lower the + // modem lines, and disable the recalcitrant fifo + // so that it will show up if the user boots to dos. + // + + // __WARNING_IRQ_SET_TOO_HIGH: we are calling interrupt synchronize routine directly. Suppress it because interrupt is not connected yet. + // __WARNING_INVALID_PARAM_VALUE_1: Interrupt is UNREFERENCED_PARAMETER, so it can be NULL +#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) + SerialReset(NULL, pDevExt); + +#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) + SerialMarkClose(NULL, pDevExt); + +#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) + SerialClrRTS(NULL, pDevExt); + +#pragma warning(suppress: __WARNING_IRQ_SET_TOO_HIGH; suppress: __WARNING_INVALID_PARAM_VALUE_1) + SerialClrDTR(NULL, pDevExt); + + // + // Fill in WMI hardware data + // + pDevExt->WmiHwData.IrqNumber = pDevExt->Irql; + pDevExt->WmiHwData.IrqLevel = pDevExt->Irql; + pDevExt->WmiHwData.IrqVector = pDevExt->Vector; + pDevExt->WmiHwData.IrqAffinityMask = pDevExt->Affinity; + pDevExt->WmiHwData.InterruptType = pDevExt->InterruptMode == Latched + ? SERIAL_WMI_INTTYPE_LATCHED : SERIAL_WMI_INTTYPE_LEVEL; + pDevExt->WmiHwData.BaseIOAddress = (ULONG_PTR)pDevExt->Controller; + + // + // Fill in WMI device state data (as defaults) + // + + pDevExt->WmiCommData.BaudRate = pDevExt->CurrentBaud; + pDevExt->WmiCommData.BitsPerByte = (pDevExt->LineControl & 0x03) + 5; + pDevExt->WmiCommData.ParityCheckEnable = (pDevExt->LineControl & 0x08) + ? TRUE : FALSE; + + switch (pDevExt->LineControl & SERIAL_PARITY_MASK) { + case SERIAL_NONE_PARITY: + pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE; + break; + + case SERIAL_ODD_PARITY: + pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD; + break; + + case SERIAL_EVEN_PARITY: + pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN; + break; + + case SERIAL_MARK_PARITY: + pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK; + break; + + case SERIAL_SPACE_PARITY: + pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE; + break; + + default: + ASSERTMSG(0, "Illegal Parity setting for WMI"); + pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE; + break; + } + + pDevExt->WmiCommData.StopBits = pDevExt->LineControl & SERIAL_STOP_MASK + ? (pDevExt->WmiCommData.BitsPerByte == 5 ? SERIAL_WMI_STOP_1_5 + : SERIAL_WMI_STOP_2) : SERIAL_WMI_STOP_1; + pDevExt->WmiCommData.XoffCharacter = pDevExt->SpecialChars.XoffChar; + pDevExt->WmiCommData.XoffXmitThreshold = pDevExt->HandFlow.XoffLimit; + pDevExt->WmiCommData.XonCharacter = pDevExt->SpecialChars.XonChar; + pDevExt->WmiCommData.XonXmitThreshold = pDevExt->HandFlow.XonLimit; + pDevExt->WmiCommData.MaximumBaudRate + = SerialReportMaxBaudRate(pDevExt->SupportedBauds); + pDevExt->WmiCommData.MaximumOutputBufferSize = (UINT32)((ULONG)-1); + pDevExt->WmiCommData.MaximumInputBufferSize = (UINT32)((ULONG)-1); + pDevExt->WmiCommData.Support16BitMode = FALSE; + pDevExt->WmiCommData.SupportDTRDSR = TRUE; + pDevExt->WmiCommData.SupportIntervalTimeouts = TRUE; + pDevExt->WmiCommData.SupportParityCheck = TRUE; + pDevExt->WmiCommData.SupportRTSCTS = TRUE; + pDevExt->WmiCommData.SupportXonXoff = TRUE; + pDevExt->WmiCommData.SettableBaudRate = TRUE; + pDevExt->WmiCommData.SettableDataBits = TRUE; + pDevExt->WmiCommData.SettableFlowControl = TRUE; + pDevExt->WmiCommData.SettableParity = TRUE; + pDevExt->WmiCommData.SettableParityCheck = TRUE; + pDevExt->WmiCommData.SettableStopBits = TRUE; + pDevExt->WmiCommData.IsBusy = FALSE; + + // + // Common error path cleanup. If the status is + // bad, get rid of the device extension, device object + // and any memory associated with it. + // + +ExtensionCleanup: ; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialInitController %x\n", status); + + return status; +} + + +NTSTATUS +SerialMapHWResources( + IN WDFDEVICE Device, + IN WDFCMRESLIST PResList, + IN WDFCMRESLIST PTrResList, + OUT PCONFIG_DATA PConfig + ) +/*++ + +Routine Description: + + This routine will get the configuration information and put + it and the translated values into CONFIG_DATA structures. + +Arguments: + + Device - Handle to a framework device object. + + Resources - Handle to a collection of framework resource objects. + This collection identifies the raw (bus-relative) hardware + resources that have been assigned to the device. + + ResourcesTranslated - Handle to a collection of framework resource objects. + This collection identifies the translated (system-physical) + hardware resources that have been assigned to the device. + The resources appear from the CPU's point of view. + Use this list of resources to map I/O space and + device-accessible memory into virtual address space + +Return Value: + + STATUS_SUCCESS if consistant configuration was found - otherwise. + returns STATUS_SERIAL_NO_DEVICE_INITED. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + NTSTATUS status = STATUS_SUCCESS; + ULONG i; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialTrResourceDesc, pPartialRawResourceDesc; + ULONG gotInt = 0; + ULONG gotIO = 0; + ULONG ioResIndex = 0; + ULONG curIoIndex = 0; + ULONG gotMem = 0; + BOOLEAN DebugPortInUse = FALSE; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> SerialMapHWResources\n"); + + // + // Get the DeviceExtension.. + // + pDevExt = SerialGetDeviceExtension (Device); + + if ((PResList == NULL) || (PTrResList == NULL)) { + ASSERT(PResList != NULL); + ASSERT(PTrResList != NULL); + status = STATUS_INSUFFICIENT_RESOURCES; + goto End; + } + + for (i = 0; i < WdfCmResourceListGetCount(PTrResList); i++) { + + pPartialTrResourceDesc = WdfCmResourceListGetDescriptor(PTrResList, i); + pPartialRawResourceDesc = WdfCmResourceListGetDescriptor(PResList, i); + + switch (pPartialTrResourceDesc->Type) { + case CmResourceTypePort: + + ASSERT(!(pPartialTrResourceDesc->u.Port.Length == SERIAL_STATUS_LENGTH)); + + if (gotIO == 0) { + + if (curIoIndex == ioResIndex) { + + gotIO = 1; + PConfig->TrController = pPartialTrResourceDesc->u.Port.Start; + + if (!PConfig->TrController.LowPart) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Bogus port address %x\n", + PConfig->TrController.LowPart); + status = STATUS_DEVICE_CONFIGURATION_ERROR; + goto End; + } + // + // We need the raw address to check if the debugger is using the com port + // + PConfig->Controller = pPartialRawResourceDesc->u.Port.Start; + PConfig->AddressSpace = pPartialTrResourceDesc->Flags; + pDevExt->SerialReadUChar = SerialReadPortUChar; + pDevExt->SerialWriteUChar = SerialWritePortUChar; + + } else { + curIoIndex++; + } + } + + break; + + // + // If this is 8 bytes long and we haven't found any I/O range, + // then this is probably a fancy-pants machine with memory replacing + // IO space + // + case CmResourceTypeMemory: + + ASSERT(!(pPartialTrResourceDesc->u.Port.Length == SERIAL_STATUS_LENGTH)); + + if ((gotMem == 0) && (gotIO == 0) + && (pPartialTrResourceDesc->u.Memory.Length + == (SERIAL_REGISTER_SPAN + SERIAL_STATUS_LENGTH))) { + gotMem = 1; + PConfig->TrController = pPartialTrResourceDesc->u.Memory.Start; + + if (!PConfig->TrController.LowPart) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Bogus I/O memory address %x\n", + PConfig->TrController.LowPart); + status = STATUS_DEVICE_CONFIGURATION_ERROR; + goto End; + } + + PConfig->Controller = pPartialRawResourceDesc->u.Memory.Start; + PConfig->AddressSpace = CM_RESOURCE_PORT_MEMORY; + PConfig->SpanOfController = SERIAL_REGISTER_SPAN; + pDevExt->SerialReadUChar = SerialReadRegisterUChar; + pDevExt->SerialWriteUChar = SerialWriteRegisterUChar; + } + break; + + case CmResourceTypeInterrupt: + if (gotInt == 0) { + gotInt = 1; + PConfig->TrVector = pPartialTrResourceDesc->u.Interrupt.Vector; + + if (!PConfig->TrVector) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Bogus vector 0\n"); + status = STATUS_DEVICE_CONFIGURATION_ERROR; + goto End; + } + + if (pPartialTrResourceDesc->ShareDisposition == CmResourceShareShared) { + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Sharing interrupt with other devices \n"); + } else { + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Interrupt is not shared with other devices\n"); + } + + PConfig->TrIrql = pPartialTrResourceDesc->u.Interrupt.Level; + PConfig->Affinity = pPartialTrResourceDesc->u.Interrupt.Affinity; + } + break; + + default: break; + } // switch (pPartialTrResourceDesc->Type) + + } // for (i = 0; i < WdfCollectionGetCount + + if(!((gotMem || gotIO) && gotInt) ) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto End; + } + + // + // First check what type of AddressSpace this port is in. Then check + // if the debugger is using this port. If it is, set DebugPortInUse to TRUE. + // + if(PConfig->AddressSpace == CM_RESOURCE_PORT_MEMORY) { + + PHYSICAL_ADDRESS KdComPhysical; + + KdComPhysical = MmGetPhysicalAddress(*KdComPortInUse); + + if(KdComPhysical.LowPart == PConfig->Controller.LowPart) { + DebugPortInUse = TRUE; + } + + } else { + // + // This compare is done using **untranslated** values since that is what + // the kernel shoves in regardless of the architecture. + // + + if ((*KdComPortInUse) == (ULongToPtr(PConfig->Controller.LowPart))) { + DebugPortInUse = TRUE; + } + } + + if (DebugPortInUse) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Kernel debugger is using port at " + "address %p\n", *KdComPortInUse); + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Serial driver will not load port\n"); + + SerialLogError( + pDevExt->DriverObject, + NULL, + PConfig->TrController, + SerialPhysicalZero, + 0, + 0, + 0, + 3, + STATUS_SUCCESS, + SERIAL_KERNEL_DEBUGGER_ACTIVE, + pDevExt->DeviceName.Length+sizeof(WCHAR), + pDevExt->DeviceName.Buffer, + 0, + NULL + ); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto End; + } + +End: + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- SerialMapHWResources %x\n", status); + + return status; +} + +VOID +SerialUnmapHWResources( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ) +/*++ + +Routine Description: + + Releases resources (not pool) stored in the device extension. + +Arguments: + + PDevExt - Pointer to the device extension to release resources from. + +Return Value: + + VOID + +--*/ +{ + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "-->SerialUnMapResources(%p)\n", + PDevExt); + PAGED_CODE(); + + // + // If necessary, unmap the device registers. + // + + if (PDevExt->UnMapRegisters) { + MmUnmapIoSpace(PDevExt->Controller, PDevExt->SpanOfController); + PDevExt->UnMapRegisters = FALSE; + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "<--SerialUnMapResources\n"); +} + + +NTSTATUS +SerialReadSymName( + IN WDFDEVICE Device, + _Out_writes_bytes_(*SizeOfRegName) PWSTR RegName, + _Inout_ PUSHORT SizeOfRegName + ) +{ + NTSTATUS status; + WDFKEY hKey; + UNICODE_STRING value; + UNICODE_STRING valueName; + USHORT requiredLength; + + PAGED_CODE(); + + value.Buffer = RegName; + value.MaximumLength = *SizeOfRegName; + value.Length = 0; + + status = WdfDeviceOpenRegistryKey(Device, + PLUGPLAY_REGKEY_DEVICE, + STANDARD_RIGHTS_ALL, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + + if (NT_SUCCESS (status)) { + // + // Fetch PortName which contains the suggested REG_SZ symbolic name. + // + + + RtlInitUnicodeString(&valueName, L"PortName"); + + status = WdfRegistryQueryUnicodeString (hKey, + &valueName, + &requiredLength, + &value); + + if (!NT_SUCCESS (status)) { + // + // This is for PCMCIA which currently puts the name under Identifier. + // + + RtlInitUnicodeString(&valueName, L"Identifier"); + status = WdfRegistryQueryUnicodeString (hKey, + &valueName, + &requiredLength, + &value); + + if (!NT_SUCCESS(status)) { + // + // Hmm. Either we have to pick a name or bail... + // + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Getting PortName/Identifier failed - %x\n", status); + } + } + + WdfRegistryClose(hKey); + } + + if(NT_SUCCESS(status)) { + // + // NULL terminate the string and return number of characters in the string. + // + if(value.Length > *SizeOfRegName - sizeof(WCHAR)) { + return STATUS_UNSUCCESSFUL; + } + + *SizeOfRegName = value.Length; + RegName[*SizeOfRegName/sizeof(WCHAR)] = UNICODE_NULL; + } + return status; +} + + +NTSTATUS +SerialDoExternalNaming(IN PSERIAL_DEVICE_EXTENSION PDevExt) + +/*++ + +Routine Description: + + This routine will be used to create a symbolic link + to the driver name in the given object directory. + + It will also create an entry in the device map for + this device - IF we could create the symbolic link. + +Arguments: + + Extension - Pointer to the device extension. + +Return Value: + + None. + +--*/ + +{ + NTSTATUS status = STATUS_SUCCESS; + WCHAR pRegName[SYMBOLIC_NAME_LENGTH]; + USHORT nameSize = sizeof(pRegName); + WDFSTRING stringHandle = NULL; + WDF_OBJECT_ATTRIBUTES attributes; + DECLARE_UNICODE_STRING_SIZE(symbolicLinkName,SYMBOLIC_NAME_LENGTH ) ; + + PAGED_CODE(); + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ParentObject = PDevExt->WdfDevice; + status = WdfStringCreate(NULL, &attributes, &stringHandle); + if(!NT_SUCCESS(status)){ + goto SerialDoExternalNamingError; + } + + status = WdfDeviceRetrieveDeviceName(PDevExt->WdfDevice, stringHandle); + if(!NT_SUCCESS(status)){ + goto SerialDoExternalNamingError; + } + + // + // Since we are storing the buffer pointer of the string handle in our + // extension, we will hold onto string handle until the device is deleted. + // + WdfStringGetUnicodeString(stringHandle, &PDevExt->DeviceName); + + SerialGetRegistryKeyValue(PDevExt->WdfDevice, L"SerialSkipExternalNaming", &PDevExt->SkipNaming); + + if (PDevExt->SkipNaming) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Skipping external naming due to registry settings\n"); + return STATUS_SUCCESS; + } + + status = SerialReadSymName(PDevExt->WdfDevice, pRegName, &nameSize); + if (!NT_SUCCESS(status)) { + goto SerialDoExternalNamingError; + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "DosName is %ws\n", pRegName); + + status = RtlUnicodeStringPrintf(&symbolicLinkName, + L"%ws%ws", + L"\\DosDevices\\", + pRegName); + + if (!NT_SUCCESS(status)) { + goto SerialDoExternalNamingError; + } + + status = WdfDeviceCreateSymbolicLink(PDevExt->WdfDevice, &symbolicLinkName); + + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't create the symbolic link for port %wZ\n", &symbolicLinkName); + + goto SerialDoExternalNamingError; + + } + + + PDevExt->CreatedSymbolicLink = TRUE; + + status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, + PDevExt->DeviceName.Buffer, + REG_SZ, + pRegName, + nameSize + sizeof(WCHAR)); + + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't create the device map entry\n" + "------- for port %ws\n", PDevExt->DeviceName.Buffer); + + goto SerialDoExternalNamingError; + } + + PDevExt->CreatedSerialCommEntry = TRUE; + + // + // Make the device visible via a device association as well. + // The reference string is the eight digit device index + // + status = WdfDeviceCreateDeviceInterface(PDevExt->WdfDevice, + (LPGUID) &GUID_DEVINTERFACE_COMPORT, + NULL); + + if (!NT_SUCCESS (status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "Couldn't register class association\n" + "for port %wZ\n", &PDevExt->DeviceName); + + goto SerialDoExternalNamingError; + } + + return status; + + SerialDoExternalNamingError:; + + // + // Clean up error conditions + // + + PDevExt->DeviceName.Buffer = NULL; + + if (PDevExt->CreatedSerialCommEntry) { + _Analysis_assume_(NULL != PDevExt->DeviceName.Buffer); + RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP, + PDevExt->DeviceName.Buffer); + } + + if(stringHandle) { + WdfObjectDelete(stringHandle); + } + + return status; +} + + +VOID +SerialUndoExternalNaming(IN PSERIAL_DEVICE_EXTENSION Extension) + +/*++ + +Routine Description: + + This routine will be used to delete a symbolic link + to the driver name in the given object directory. + + It will also delete an entry in the device map for + this device if the symbolic link had been created. + +Arguments: + + Extension - Pointer to the device extension. + +Return Value: + + None. + +--*/ + +{ + + NTSTATUS status; + PWCHAR deviceName = Extension->DeviceName.Buffer; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "In SerialUndoExternalNaming for extension: " + "%p of port %ws\n", Extension, deviceName); + + // + // Maybe there is nothing for us to do + // + + if (Extension->SkipNaming) { + return; + } + + // + // We're cleaning up here. One reason we're cleaning up + // is that we couldn't allocate space for the NtNameOfPort. + // + + if ((deviceName != NULL) && Extension->CreatedSerialCommEntry) { + + status = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, + SERIAL_DEVICE_MAP, + deviceName); + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, + "Couldn't delete value entry %ws\n", + deviceName); + + } + } +} + +VOID +SerialPurgePendingRequests(PSERIAL_DEVICE_EXTENSION pDevExt) +/*++ + +Routine Description: + + This routine completes any irps pending for the passed device object. + +Arguments: + + PDevObj - Pointer to the device object whose irps must die. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS status; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + ">SerialPurgePendingRequests(%p)\n", pDevExt); + + // + // Then cancel all the reads and writes. + // + + SerialPurgeRequests(pDevExt->WriteQueue, &pDevExt->CurrentWriteRequest); + + SerialPurgeRequests(pDevExt->ReadQueue, &pDevExt->CurrentReadRequest); + + // + // Next get rid of purges. + // + + SerialPurgeRequests(pDevExt->PurgeQueue, &pDevExt->CurrentPurgeRequest); + + // + // Get rid of any mask operations. + // + + SerialPurgeRequests( pDevExt->MaskQueue, &pDevExt->CurrentMaskRequest); + + // + // Now get rid of pending wait mask request. + // + + if (pDevExt->CurrentWaitRequest) { + + status = SerialClearCancelRoutine(pDevExt->CurrentWaitRequest, TRUE ); + if (NT_SUCCESS(status)) { + + SerialCompleteRequest(pDevExt->CurrentWaitRequest, STATUS_CANCELLED, 0); + pDevExt->CurrentWaitRequest = NULL; + + } + + } + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, "Controller); + + // + // Make sure that we are *aren't* accessing the divsior latch. + // + + WRITE_LINE_CONTROL(Extension, + Extension->Controller, + (UCHAR)(oldLCRContents & ~SERIAL_LCR_DLAB) + ); + + oldIERContents = READ_INTERRUPT_ENABLE(Extension, Extension->Controller); + + // + // Go up to power level for a very short time to prevent + // any interrupts from this device from coming in. + // + + KeRaiseIrql( + POWER_LEVEL, + &oldIrql + ); + + WRITE_INTERRUPT_ENABLE(Extension, + Extension->Controller, + 0x0f + ); + + value1 = READ_INTERRUPT_ENABLE(Extension, Extension->Controller); + value1 = value1 << 8; + value1 |= READ_RECEIVE_BUFFER(Extension, Extension->Controller); + + READ_DIVISOR_LATCH(Extension, + Extension->Controller, + (PSHORT) &value2 + ); + + WRITE_LINE_CONTROL(Extension, + Extension->Controller, + oldLCRContents + ); + + // + // Put the ier back to where it was before. If we are on a + // level sensitive port this should prevent the interrupts + // from coming in. If we are on a latched, we don't care + // cause the interrupts generated will just get dropped. + // + + WRITE_INTERRUPT_ENABLE(Extension, + Extension->Controller, + oldIERContents + ); + + KeLowerIrql(oldIrql); + + if (value1 == value2) { + + SerialLogError( + Extension->DeviceObject->DriverObject, + Extension->DeviceObject, + SerialPhysicalZero, + SerialPhysicalZero, + 0, + 0, + 0, + 62, + STATUS_SUCCESS, + SERIAL_DLAB_INVALID, + InsertString->Length+sizeof(WCHAR), + InsertString->Buffer, + 0, + NULL + ); + returnValue = FALSE; + goto AllDone; + + } + + AllDone: ; + + + // + // If we think that there is a serial device then we determine + // if a fifo is present. + // + + if (returnValue) { + + // + // Well, we think it's a serial device. Absolutely + // positively, prevent interrupts from occuring. + // + // We disable all the interrupt enable bits, and + // push down all the lines in the modem control + // We only needed to push down OUT2 which in + // PC's must also be enabled to get an interrupt. + // + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + + WRITE_MODEM_CONTROL(Extension, Extension->Controller, (UCHAR)0); + + // + // See if this is a 16550. We do this by writing to + // what would be the fifo control register with a bit + // pattern that tells the device to enable fifo's. + // We then read the iterrupt Id register to see if the + // bit pattern is present that identifies the 16550. + // + + WRITE_FIFO_CONTROL(Extension, + Extension->Controller, + SERIAL_FCR_ENABLE + ); + + regContents = READ_INTERRUPT_ID_REG(Extension, Extension->Controller); + + if (regContents & SERIAL_IIR_FIFOS_ENABLED) { + + // + // Save off that the device supports fifos. + // + + Extension->FifoPresent = TRUE; + + // + // There is a fine new "super" IO chip out there that + // will get stuck with a line status interrupt if you + // attempt to clear the fifo and enable it at the same + // time if data is present. The best workaround seems + // to be that you should turn off the fifo read a single + // byte, and then re-enable the fifo. + // + + WRITE_FIFO_CONTROL(Extension, + Extension->Controller, + (UCHAR)0 + ); + + READ_RECEIVE_BUFFER(Extension, Extension->Controller); + + // + // There are fifos on this card. Set the value of the + // receive fifo to interrupt when 4 characters are present. + // + + WRITE_FIFO_CONTROL(Extension, Extension->Controller, + (UCHAR)(SERIAL_FCR_ENABLE + | Extension->RxFifoTrigger + | SERIAL_FCR_RCVR_RESET + | SERIAL_FCR_TXMT_RESET)); + + } + + // + // The !Extension->FifoPresent is included in the test so that + // broken chips like the WinBond will still work after we test + // for the fifo. + // + + if (!ForceFifo || !Extension->FifoPresent) { + + Extension->FifoPresent = FALSE; + WRITE_FIFO_CONTROL(Extension, + Extension->Controller, + (UCHAR)0 + ); + + } + + if (Extension->FifoPresent) { + + if (LogFifo) { + + SerialLogError( + Extension->DeviceObject->DriverObject, + Extension->DeviceObject, + SerialPhysicalZero, + SerialPhysicalZero, + 0, + 0, + 0, + 15, + STATUS_SUCCESS, + SERIAL_FIFO_PRESENT, + InsertString->Length+sizeof(WCHAR), + InsertString->Buffer, + 0, + NULL + ); + + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, + "Fifo's detected at port address: %p\n", + Extension->Controller); + } + } + + return returnValue; +} + + + +BOOLEAN +SerialReset( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This places the hardware in a standard configuration. + + NOTE: This assumes that it is called at interrupt level. + + +Arguments: + + Context - The device extension for serial device + being managed. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension = Context; + UCHAR regContents; + UCHAR oldModemControl; + ULONG i; + + UNREFERENCED_PARAMETER(Interrupt); + + // + // Adjust the out2 bit. + // This will also prevent any interrupts from occuring. + // + + oldModemControl = READ_MODEM_CONTROL(extension, extension->Controller); + + WRITE_MODEM_CONTROL(extension, extension->Controller, + (UCHAR)(oldModemControl & ~SERIAL_MCR_OUT2)); + + // + // Reset the fifo's if there are any. + // + + if (extension->FifoPresent) { + + // + // There is a fine new "super" IO chip out there that + // will get stuck with a line status interrupt if you + // attempt to clear the fifo and enable it at the same + // time if data is present. The best workaround seems + // to be that you should turn off the fifo read a single + // byte, and then re-enable the fifo. + // + + WRITE_FIFO_CONTROL(extension, + extension->Controller, + (UCHAR)0 + ); + + READ_RECEIVE_BUFFER(extension, extension->Controller); + + WRITE_FIFO_CONTROL(extension, + extension->Controller, + (UCHAR)(SERIAL_FCR_ENABLE | extension->RxFifoTrigger | + SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET) + ); + + } + + // + // Make sure that the line control set up correct. + // + // 1) Make sure that the Divisor latch select is set + // up to select the transmit and receive register. + // + // 2) Make sure that we aren't in a break state. + // + + regContents = READ_LINE_CONTROL(extension, extension->Controller); + regContents &= ~(SERIAL_LCR_DLAB | SERIAL_LCR_BREAK); + + WRITE_LINE_CONTROL(extension, + extension->Controller, + regContents + ); + + // + // Read the receive buffer until the line status is + // clear. (Actually give up after a 5 reads.) + // + + for (i = 0; + i < 5; + i++ + ) { + #pragma warning(disable: 4127) + if (IsNotNEC_98) { + #pragma warning(default: 4127) + READ_RECEIVE_BUFFER(extension, extension->Controller); + if (!(READ_LINE_STATUS(extension, extension->Controller) & 1)) { + + break; + + } + } else { + // + // I get incorrect data when read enpty buffer. + // But do not read no data! for PC98! + // + if (!(READ_LINE_STATUS(extension, extension->Controller) & 1)) { + + break; + + } + READ_RECEIVE_BUFFER(extension, extension->Controller); + } + + } + + // + // Read the modem status until the low 4 bits are + // clear. (Actually give up after a 5 reads.) + // + + for (i = 0; + i < 1000; + i++ + ) { + + if (!(READ_MODEM_STATUS(extension, extension->Controller) & 0x0f)) { + + break; + + } + + } + + // + // Now we set the line control, modem control, and the + // baud to what they should be. + // + + // + // See if we have to enable special Auto Flow Control + // + + if (extension->TL16C550CAFC) { + oldModemControl = READ_MODEM_CONTROL(extension, extension->Controller); + + WRITE_MODEM_CONTROL(extension, extension->Controller, + (UCHAR)(oldModemControl | SERIAL_MCR_TL16C550CAFE)); + } + + + + SerialSetLineControl(extension->WdfInterrupt, extension); + + SerialSetupNewHandFlow( + extension, + &extension->HandFlow + ); + + SerialHandleModemUpdate( + extension, + FALSE + ); + + { + SHORT appropriateDivisor; + SERIAL_IOCTL_SYNC s; + + SerialGetDivisorFromBaud( extension->ClockRate, + extension->CurrentBaud, + &appropriateDivisor ); + + s.Extension = extension; + s.Data = (PVOID) (ULONG_PTR) appropriateDivisor; + SerialSetBaud(extension->WdfInterrupt, &s); + } + + // + // Enable which interrupts we want to receive. + // + // NOTE NOTE: This does not actually let interrupts + // occur. We must still raise the OUT2 bit in the + // modem control register. We will do that on open. + // + + ENABLE_ALL_INTERRUPTS(extension, extension->Controller); + + // + // Read the interrupt id register until the low bit is + // set. (Actually give up after a 5 reads.) + // + + for (i = 0; + i < 5; + i++ + ) { + + if (READ_INTERRUPT_ID_REG(extension, extension->Controller) & 0x01) { + + break; + + } + + } + + // + // Now we know that nothing could be transmitting at this point + // so we set the HoldingEmpty indicator. + // + + extension->HoldingEmpty = TRUE; + + return FALSE; +} + + + +PVOID +SerialGetMappedAddress( + PHYSICAL_ADDRESS IoAddress, + ULONG NumberOfBytes, + ULONG AddressSpace, + PBOOLEAN MappedAddress + ) + +/*++ + +Routine Description: + + This routine maps an IO address to system address space. + +Arguments: + + IoAddress - base device address to be mapped. + NumberOfBytes - number of bytes for which address is valid. + AddressSpace - Denotes whether the address is in io space or memory. + MappedAddress - indicates whether the address was mapped. + This only has meaning if the address returned + is non-null. + +Return Value: + + Mapped address + +--*/ + +{ + PVOID address; + + PAGED_CODE(); + + // + // Map the device base address into the virtual address space + // if the address is in memory space. + // + + if (!AddressSpace) { + + address = LocalMmMapIoSpace(IoAddress, + NumberOfBytes); + + *MappedAddress = (BOOLEAN)((address)?(TRUE):(FALSE)); + + + } else { + + address = ULongToPtr(IoAddress.LowPart); + *MappedAddress = FALSE; + + } + + return address; +} + +VOID +SerialSetInterruptPolicy( + _In_ WDFINTERRUPT WdfInterrupt + ) +/*++ + +Routine Description: + + This routine shows how to set the interrupt policy preferences. + +Arguments: + + WdfInterrupt - Interrupt object handle. + +Return Value: + + None + +--*/ +{ + WDF_INTERRUPT_EXTENDED_POLICY policyAndGroup; +#ifdef SERIAL_SELECT_INTERRUPT_GROUP + USHORT groupCount = 1; + USHORT group = 0; + UNICODE_STRING funcName; + PFN_KE_GET_ACTIVE_GROUP_COUNT fnKeQueryActiveGroupCount; + PFN_KE_QUERY_GROUP_AFFINITY fnKeQueryGroupAffinity; + KAFFINITY groupAffinity = (KAFFINITY)1; +#endif + + WDF_INTERRUPT_EXTENDED_POLICY_INIT(&policyAndGroup); + policyAndGroup.Priority = WdfIrqPriorityNormal; + +#ifdef SERIAL_SELECT_INTERRUPT_GROUP + // + // If OS supports groups, find how many they are. + // + RtlInitUnicodeString(&funcName, L"KeQueryActiveGroupCount"); + fnKeQueryActiveGroupCount = (PFN_KE_GET_ACTIVE_GROUP_COUNT) + MmGetSystemRoutineAddress(&funcName); + + if (fnKeQueryActiveGroupCount != NULL) { + groupCount = fnKeQueryActiveGroupCount(); + + // + // Make sure there is at least one group for the boot processor. + // + if (0 == groupCount) { + groupCount = 1; + } + } + + if (groupCount <= SERIAL_PREFERRED_INTERRUPT_GROUP) { + group = groupCount - 1; + } + else { + group = SERIAL_PREFERRED_INTERRUPT_GROUP; + } + + // + // Get the group affinity. + // + RtlInitUnicodeString(&funcName, L"KeQueryGroupAffinity"); + fnKeQueryGroupAffinity = (PFN_KE_QUERY_GROUP_AFFINITY) + MmGetSystemRoutineAddress(&funcName); + + if (fnKeQueryGroupAffinity != NULL) { + groupAffinity = fnKeQueryGroupAffinity(group); + + // + // Active groups have at least one processor. + // + if ((KAFFINITY)0 == groupAffinity) { + groupAffinity = (KAFFINITY)1; + } + } + + // + // Initialize group. + // + policyAndGroup.Policy = WdfIrqPolicySpecifiedProcessors; + policyAndGroup.TargetProcessorSetAndGroup.Group = group; + policyAndGroup.TargetProcessorSetAndGroup.Mask = groupAffinity; +#endif + + // + // Set interrupt policy and group preference. + // + WdfInterruptSetExtendedPolicy(WdfInterrupt, &policyAndGroup); +} + diff --git a/tests/projects/windows/driver/kmdf/serial/power.c b/tests/projects/windows/driver/kmdf/serial/power.c new file mode 100644 index 000000000..68aad3efa --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/power.c @@ -0,0 +1,331 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + power.c + +Abstract: + + This module contains the code that handles the power IRPs for the serial + driver. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + + +#if defined(EVENT_TRACING) +#include "power.tmh" +#endif + + +PCHAR +DbgDevicePowerString( + IN WDF_POWER_DEVICE_STATE Type + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGESER,SerialEvtDeviceD0Exit) +#pragma alloc_text(PAGESER,SerialSaveDeviceState) +#endif // ALLOC_PRAGMA + +PCHAR +DbgDevicePowerString( + IN WDF_POWER_DEVICE_STATE Type + ) +/*++ + +Updated Routine Description: + DbgDevicePowerString does not change in this stage of the function driver. + +--*/ +{ + + switch (Type) + { + case WdfPowerDeviceInvalid: + return "WdfPowerDeviceInvalid"; + case WdfPowerDeviceD0: + return "WdfPowerDeviceD0"; + case WdfPowerDeviceD1: + return "WdfPowerDeviceD1"; + case WdfPowerDeviceD2: + return "WdfPowerDeviceD2"; + case WdfPowerDeviceD3: + return "WdfPowerDeviceD3"; + case WdfPowerDeviceD3Final: + return "WdfPowerDeviceD3Final"; + case WdfPowerDevicePrepareForHibernation: + return "WdfPowerDevicePrepareForHibernation"; + case WdfPowerDeviceMaximum: + return "WdfPowerDeviceMaximum"; + default: + return "UnKnown Device Power State"; + } +} + +NTSTATUS +SerialEvtDeviceD0Entry( + IN WDFDEVICE Device, + IN WDF_POWER_DEVICE_STATE PreviousState + ) +/*++ + +Routine Description: + + EvtDeviceD0Entry event callback must perform any operations that are + necessary before the specified device is used. It will be called every + time the hardware needs to be (re-)initialized. This includes after + IRP_MN_START_DEVICE, IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE, + IRP_MN_SET_POWER-D0. + + This function is not marked pageable because this function is in the + device power up path. When a function is marked pagable and the code + section is paged out, it will generate a page fault which could impact + the fast resume behavior because the client driver will have to wait + until the system drivers can service this page fault. + + This function runs at PASSIVE_LEVEL, even though it is not paged. A + driver can optionally make this function pageable if DO_POWER_PAGABLE + is set. Even if DO_POWER_PAGABLE isn't set, this function still runs + at PASSIVE_LEVEL. In this case, though, the function absolutely must + not do anything that will cause a page fault. + +Arguments: + + Device - Handle to a framework device object. + + PreviousState - Device power state which the device was in most recently. + If the device is being newly started, this will be + PowerDeviceUnspecified. + +Return Value: + + NTSTATUS + +--*/ +{ + PSERIAL_DEVICE_EXTENSION deviceExtension; + PSERIAL_DEVICE_STATE pDevState; + SHORT divisor; + SERIAL_IOCTL_SYNC S; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, + "-->SerialEvtDeviceD0Entry - coming from %s\n", DbgDevicePowerString(PreviousState)); + + deviceExtension = SerialGetDeviceExtension (Device); + pDevState = &deviceExtension->DeviceState; + + // + // Restore the state of the UART. First, that involves disabling + // interrupts both via OUT2 and IER. + // + + WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller, 0); + DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller); + + // + // Set the baud rate + // + + SerialGetDivisorFromBaud(deviceExtension->ClockRate, deviceExtension->CurrentBaud, &divisor); + S.Extension = deviceExtension; + S.Data = (PVOID) (ULONG_PTR) divisor; + +#pragma prefast(suppress: __WARNING_INFERRED_IRQ_TOO_LOW, "PFD warning that we are calling interrupt synchronize routine directly. Suppress it because interrupt is disabled above.") + SerialSetBaud(deviceExtension->WdfInterrupt, &S); + + // + // Reset / Re-enable the FIFO's + // + + if (deviceExtension->FifoPresent) { + WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0); + READ_RECEIVE_BUFFER(deviceExtension, deviceExtension->Controller); + WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, + (UCHAR)(SERIAL_FCR_ENABLE | deviceExtension->RxFifoTrigger + | SERIAL_FCR_RCVR_RESET + | SERIAL_FCR_TXMT_RESET)); + } else { + WRITE_FIFO_CONTROL(deviceExtension, deviceExtension->Controller, (UCHAR)0); + } + + // + // Restore a couple more registers + // + + WRITE_INTERRUPT_ENABLE(deviceExtension, deviceExtension->Controller, pDevState->IER); + WRITE_LINE_CONTROL(deviceExtension, deviceExtension->Controller, pDevState->LCR); + + // + // Clear out any stale interrupts + // + + READ_INTERRUPT_ID_REG(deviceExtension, deviceExtension->Controller); + READ_LINE_STATUS(deviceExtension, deviceExtension->Controller); + READ_MODEM_STATUS(deviceExtension, deviceExtension->Controller); + + // + // TODO: move this code to EvtInterruptEnable. + // + + if (deviceExtension->DeviceState.Reopen == TRUE) { + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Reopening device\n"); + + SetDeviceIsOpened(deviceExtension, TRUE, FALSE); + + // + // This enables interrupts on the device! + // + + WRITE_MODEM_CONTROL(deviceExtension, deviceExtension->Controller, + (UCHAR)(pDevState->MCR | SERIAL_MCR_OUT2)); + + // + // Refire the state machine + // + + DISABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller); + ENABLE_ALL_INTERRUPTS(deviceExtension, deviceExtension->Controller); + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--SerialEvtDeviceD0Entry\n"); + + return STATUS_SUCCESS; +} + + +NTSTATUS +SerialEvtDeviceD0Exit( + IN WDFDEVICE Device, + IN WDF_POWER_DEVICE_STATE TargetState + ) +/*++ + +Routine Description: + + EvtDeviceD0Exit event callback must perform any operations that are + necessary before the specified device is moved out of the D0 state. If the + driver needs to save hardware state before the device is powered down, then + that should be done here. + + This function runs at PASSIVE_LEVEL, though it is generally not paged. A + driver can optionally make this function pageable if DO_POWER_PAGABLE is set. + + Even if DO_POWER_PAGABLE isn't set, this function still runs at + PASSIVE_LEVEL. In this case, though, the function absolutely must not do + anything that will cause a page fault. + +Arguments: + + Device - Handle to a framework device object. + + TargetState - Device power state which the device will be put in once this + callback is complete. + +Return Value: + + NTSTATUS + +--*/ +{ + PSERIAL_DEVICE_EXTENSION deviceExtension; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, + "-->SerialEvtDeviceD0Exit - moving to %s\n", DbgDevicePowerString(TargetState)); + + PAGED_CODE(); + + deviceExtension = SerialGetDeviceExtension (Device); + + if (deviceExtension->DeviceIsOpened == TRUE) { + LARGE_INTEGER charTime; + + SetDeviceIsOpened(deviceExtension, FALSE, TRUE); + + charTime.QuadPart = -SerialGetCharTime(deviceExtension).QuadPart; + + // + // Shut down the chip + // + + SerialDisableUART(deviceExtension); + + // + // Drain the device + // + + SerialDrainUART(deviceExtension, &charTime); + + // + // Save the device state + // + + SerialSaveDeviceState(deviceExtension); + } + else + { + SetDeviceIsOpened(deviceExtension, FALSE, FALSE); + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "<--SerialEvtDeviceD0Exit\n"); + + return STATUS_SUCCESS; +} + + +VOID +SerialSaveDeviceState(IN PSERIAL_DEVICE_EXTENSION PDevExt) +/*++ + +Routine Description: + + This routine saves the device state of the UART + +Arguments: + + PDevExt - Pointer to the device extension for the devobj to save the state + for. + +Return Value: + + VOID + + +--*/ +{ + PSERIAL_DEVICE_STATE pDevState = &PDevExt->DeviceState; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Entering SerialSaveDeviceState\n"); + + // + // Read necessary registers direct + // + + pDevState->IER = READ_INTERRUPT_ENABLE(PDevExt, PDevExt->Controller); + pDevState->MCR = READ_MODEM_CONTROL(PDevExt, PDevExt->Controller); + pDevState->LCR = READ_LINE_CONTROL(PDevExt, PDevExt->Controller); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_POWER, "Leaving SerialSaveDeviceState\n"); +} + + +VOID +SetDeviceIsOpened(IN PSERIAL_DEVICE_EXTENSION PDevExt, IN BOOLEAN DeviceIsOpened, IN BOOLEAN Reopen) +{ + + PDevExt->DeviceIsOpened = DeviceIsOpened; + PDevExt->DeviceState.Reopen = Reopen; + +} + + + diff --git a/tests/projects/windows/driver/kmdf/serial/precomp.h b/tests/projects/windows/driver/kmdf/serial/precomp.h new file mode 100644 index 000000000..7c7c5d5ef --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/precomp.h @@ -0,0 +1,18 @@ + +#include +#include +#define WIN9X_COMPAT_SPINLOCK +#include "ntddk.h" +#include +#define NTSTRSAFE_LIB +#include +#include "ntddser.h" +#include +#include // required for GUID definitions +#include +#include "serial.h" +#include "serialp.h" +#include "serlog.h" +#include "log.h" +#include "trace.h" + diff --git a/tests/projects/windows/driver/kmdf/serial/precompsrc.c b/tests/projects/windows/driver/kmdf/serial/precompsrc.c new file mode 100644 index 000000000..5944cf515 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/precompsrc.c @@ -0,0 +1 @@ +#include "precomp.h" \ No newline at end of file diff --git a/tests/projects/windows/driver/kmdf/serial/purge.c b/tests/projects/windows/driver/kmdf/serial/purge.c new file mode 100644 index 000000000..fcc32148e --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/purge.c @@ -0,0 +1,175 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + purge.c + +Abstract: + + This module contains the code that is very specific to purge + operations in the serial driver + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "purge.tmh" +#endif + + +VOID +SerialStartPurge( + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + Depending on the mask in the current request, purge the interrupt + buffer, the read queue, or the write queue, or all of the above. + +Arguments: + + Extension - Pointer to the device extension. + +Return Value: + + Will return STATUS_SUCCESS always. This is reasonable + since the DPC completion code that calls this routine doesn't + care and the purge request always goes through to completion + once it's started. + +--*/ + +{ + + WDFREQUEST NewRequest; + PREQUEST_CONTEXT reqContext; + + do { + + ULONG Mask; + reqContext = SerialGetRequestContext(Extension->CurrentPurgeRequest); + Mask = *((ULONG *) (reqContext->SystemBuffer)); + + if (Mask & SERIAL_PURGE_TXABORT) { + + SerialFlushRequests( + Extension->WriteQueue, + &Extension->CurrentWriteRequest + ); + + SerialFlushRequests( + Extension->WriteQueue, + &Extension->CurrentXoffRequest + ); + + } + + if (Mask & SERIAL_PURGE_RXABORT) { + + SerialFlushRequests( + Extension->ReadQueue, + &Extension->CurrentReadRequest + ); + + } + + if (Mask & SERIAL_PURGE_RXCLEAR) { + + // + // Clean out the interrupt buffer. + // + // Note that we do this under protection of the + // the drivers control lock so that we don't hose + // the pointers if there is currently a read that + // is reading out of the buffer. + // + + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialPurgeInterruptBuff, + Extension + ); + + } + + reqContext->Status = STATUS_SUCCESS; + reqContext->Information = 0; + + SerialGetNextRequest( + &Extension->CurrentPurgeRequest, + Extension->PurgeQueue, + &NewRequest, + TRUE, + Extension + ); + + } while (NewRequest); + + return; + +} + +BOOLEAN +SerialPurgeInterruptBuff( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine simply resets the interrupt (typeahead) buffer. + + NOTE: This routine is being called from WdfInterruptSynchronize. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + Always false. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + UNREFERENCED_PARAMETER(Interrupt); + + // + // The typeahead buffer is by definition empty if there + // currently is a read owned by the isr. + // + + + if (Extension->ReadBufferBase == Extension->InterruptReadBuffer) { + + Extension->CurrentCharSlot = Extension->InterruptReadBuffer; + Extension->FirstReadableChar = Extension->InterruptReadBuffer; + Extension->LastCharSlot = Extension->InterruptReadBuffer + + (Extension->BufferSize - 1); + Extension->CharsInInterruptBuffer = 0; + + SerialHandleReducedIntBuffer(Extension); + + } + + return FALSE; + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/qsfile.c b/tests/projects/windows/driver/kmdf/serial/qsfile.c new file mode 100644 index 000000000..ad1604131 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/qsfile.c @@ -0,0 +1,180 @@ +/*++ + +Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation + +Module Name: + + qsfile.c + +Abstract: + + This module contains the code that is very specific to query/set file + operations in the serial driver. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "qsfile.tmh" +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGESRP0,SerialQueryInformationFile) +#pragma alloc_text(PAGESRP0,SerialSetInformationFile) +#endif + + +NTSTATUS +SerialQueryInformationFile( + IN WDFDEVICE Device, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This routine is used to query the end of file information on + the opened serial port. Any other file information request + is retured with an invalid parameter. + + This routine always returns an end of file of 0. + +Arguments: + + DeviceObject - Pointer to the device object for this device + + Irp - Pointer to the IRP for the current request + +Return Value: + + The function value is the final status of the call + +--*/ + +{ + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialQueryInformationFile(%p, %p)\n", Device, Irp); + + PAGED_CODE(); + + + IrpSp = IoGetCurrentIrpStackLocation(Irp); + Irp->IoStatus.Information = 0L; + Status = STATUS_SUCCESS; + + if (IrpSp->Parameters.QueryFile.FileInformationClass == + FileStandardInformation) { + + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(FILE_STANDARD_INFORMATION)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + PFILE_STANDARD_INFORMATION Buf = Irp->AssociatedIrp.SystemBuffer; + + Buf->AllocationSize.QuadPart = 0; + Buf->EndOfFile = Buf->AllocationSize; + Buf->NumberOfLinks = 0; + Buf->DeletePending = FALSE; + Buf->Directory = FALSE; + Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION); + } + + } else if (IrpSp->Parameters.QueryFile.FileInformationClass == + FilePositionInformation) { + + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < + sizeof(FILE_POSITION_INFORMATION)) + { + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + + ((PFILE_POSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer)-> + CurrentByteOffset.QuadPart = 0; + Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION); + } + + } else { + Status = STATUS_INVALID_PARAMETER; + } + + Irp->IoStatus.Status = Status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; + +} + +NTSTATUS +SerialSetInformationFile( + IN WDFDEVICE Device, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This routine is used to set the end of file information on + the opened parallel port. Any other file information request + is retured with an invalid parameter. + + This routine always ignores the actual end of file since + the query information code always returns an end of file of 0. + +Arguments: + + DeviceObject - Pointer to the device object for this device + + Irp - Pointer to the IRP for the current request + +Return Value: + +The function value is the final status of the call + +--*/ + +{ + NTSTATUS Status; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_PNP, ">SerialSetInformationFile(%p, %p)\n", Device, Irp); + + Irp->IoStatus.Information = 0L; + if ((IoGetCurrentIrpStackLocation(Irp)-> + Parameters.SetFile.FileInformationClass == + FileEndOfFileInformation) || + (IoGetCurrentIrpStackLocation(Irp)-> + Parameters.SetFile.FileInformationClass == + FileAllocationInformation)) { + + Status = STATUS_SUCCESS; + + } else { + + Status = STATUS_INVALID_PARAMETER; + + } + + Irp->IoStatus.Status = Status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; + +} + diff --git a/tests/projects/windows/driver/kmdf/serial/read.c b/tests/projects/windows/driver/kmdf/serial/read.c new file mode 100644 index 000000000..ab745fdd7 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/read.c @@ -0,0 +1,1748 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + read.c + +Abstract: + + This module contains the code that is very specific to read + operations in the serial driver + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "read.tmh" +#endif + +EVT_WDF_REQUEST_CANCEL SerialCancelCurrentRead; + +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabReadFromIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateReadByIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateInterruptBuffer; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateAndSwitchToUser; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialUpdateAndSwitchToNew; + +ULONG +SerialGetCharsFromIntBuffer( + PSERIAL_DEVICE_EXTENSION Extension + ); + + +NTSTATUS +SerialResizeBuffer( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +ULONG +SerialMoveToNewIntBuffer( + PSERIAL_DEVICE_EXTENSION Extension, + PUCHAR NewBuffer + ); + +VOID +SerialEvtIoRead( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t Length + ) + +/*++ + +Routine Description: + + This is the dispatch routine for reading. It validates the parameters + for the read request and if all is ok then it places the request + on the work queue. + +Arguments: + + Queue - Queue handle + Request - Handle to the read request + Lenght - Length of the data buffer associated with the request. + The default property of the queue is to not dispatch + zero lenght read & write requests to the driver and + complete is with status success. So we will never get + a zero length request. + +Return Value: + + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension; + NTSTATUS status; + WDFDEVICE hDevice; + WDF_REQUEST_PARAMETERS params; + PREQUEST_CONTEXT reqContext; + size_t bufLen; + + hDevice = WdfIoQueueGetDevice(Queue); + extension = SerialGetDeviceExtension(hDevice); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, + ">SerialEvtIoRead(%p, 0x%I64x)\n", Request, Length); + + if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "MajorFunction = params.Type; + reqContext->Length = (ULONG) Length; + + status = WdfRequestRetrieveOutputBuffer (Request, Length, &reqContext->SystemBuffer, &bufLen); + + if (!NT_SUCCESS (status)) { + + SerialCompleteRequest(Request , status, 0); + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_READ, "Length); + + // + // Well it looks like we actually have to do some + // work. Put the read on the queue so that we can + // process it when our previous reads are done. + // + SerialStartOrQueue(extension, Request, extension->ReadQueue, + &extension->CurrentReadRequest, SerialStartRead); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "SerialStartRead(%p)\n", Extension); + + updateChar.Extension = Extension; + + + do { + + reqContext = SerialGetRequestContext(Extension->CurrentReadRequest); + + // + // Check to see if this is a resize request. If it is + // then go to a routine that specializes in that. + // + + if (reqContext->MajorFunction != IRP_MJ_READ) { + + NTSTATUS localStatus = SerialResizeBuffer(Extension); + UNREFERENCED_PARAMETER(localStatus); + ASSERT(NT_SUCCESS(localStatus)); + + } else { + + Extension->NumberNeededForRead = reqContext->Length; + + // + // Calculate the timeout value needed for the + // request. Note that the values stored in the + // timeout record are in milliseconds. + // + + useTotalTimer = FALSE; + returnWithWhatsPresent = FALSE; + os2ssreturn = FALSE; + crunchDownToOne = FALSE; + useIntervalTimer = FALSE; + + // + // + // CIMEXCIMEX -- this is a lie + // + // Always initialize the timer objects so that the + // completion code can tell when it attempts to + // cancel the timers whether the timers had ever + // been Set. + // + // CIMEXCIMEX -- this is the truth + // + // What we want to do is just make sure the timers are + // cancelled to the best of our ability and move on with + // life. + // + + SerialCancelTimer(Extension->ReadRequestTotalTimer, Extension); + SerialCancelTimer(Extension->ReadRequestIntervalTimer, Extension); + + // + // We get the *current* timeout values to use for timing + // this read. + // + + + timeoutsForIrp = Extension->Timeouts; + + // + // Calculate the interval timeout for the read. + // + + if (timeoutsForIrp.ReadIntervalTimeout && + (timeoutsForIrp.ReadIntervalTimeout != + MAXULONG)) { + + useIntervalTimer = TRUE; + + Extension->IntervalTime.QuadPart = + UInt32x32To64( + timeoutsForIrp.ReadIntervalTimeout, + 10000 + ); + + + if (Extension->IntervalTime.QuadPart >= + Extension->CutOverAmount.QuadPart) { + + Extension->IntervalTimeToUse = + &Extension->LongIntervalAmount; + + } else { + + Extension->IntervalTimeToUse = + &Extension->ShortIntervalAmount; + + } + + } + + if (timeoutsForIrp.ReadIntervalTimeout == MAXULONG) { + + // + // We need to do special return quickly stuff here. + // + // 1) If both constant and multiplier are + // 0 then we return immediately with whatever + // we've got, even if it was zero. + // + // 2) If constant and multiplier are not MAXULONG + // then return immediately if any characters + // are present, but if nothing is there, then + // use the timeouts as specified. + // + // 3) If multiplier is MAXULONG then do as in + // "2" but return when the first character + // arrives. + // + + if (!timeoutsForIrp.ReadTotalTimeoutConstant && + !timeoutsForIrp.ReadTotalTimeoutMultiplier) { + + returnWithWhatsPresent = TRUE; + + } else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG) + && + (timeoutsForIrp.ReadTotalTimeoutMultiplier + != MAXULONG)) { + + useTotalTimer = TRUE; + os2ssreturn = TRUE; + multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier; + constantVal = timeoutsForIrp.ReadTotalTimeoutConstant; + + } else if ((timeoutsForIrp.ReadTotalTimeoutConstant != MAXULONG) + && + (timeoutsForIrp.ReadTotalTimeoutMultiplier + == MAXULONG)) { + + useTotalTimer = TRUE; + os2ssreturn = TRUE; + crunchDownToOne = TRUE; + multiplierVal = 0; + constantVal = timeoutsForIrp.ReadTotalTimeoutConstant; + + } + + } else { + + // + // If both the multiplier and the constant are + // zero then don't do any total timeout processing. + // + + if (timeoutsForIrp.ReadTotalTimeoutMultiplier || + timeoutsForIrp.ReadTotalTimeoutConstant) { + + // + // We have some timer values to calculate. + // + + useTotalTimer = TRUE; + multiplierVal = timeoutsForIrp.ReadTotalTimeoutMultiplier; + constantVal = timeoutsForIrp.ReadTotalTimeoutConstant; + + } + + } + + if (useTotalTimer) { + + totalTime.QuadPart = ((LONGLONG)(UInt32x32To64( + Extension->NumberNeededForRead, + multiplierVal + ) + + constantVal)) + * -10000; + + } + + + // + // We do this copy in the hope of getting most (if not + // all) of the characters out of the interrupt buffer. + // + // Note that we need to protect this operation with a + // spinlock since we don't want a purge to hose us. + // + + updateChar.CharsCopied = SerialGetCharsFromIntBuffer(Extension); + + // + // See if we have any cause to return immediately. + // + + if (returnWithWhatsPresent || (!Extension->NumberNeededForRead) || + (os2ssreturn && + reqContext->Information)) { + + // + // We got all we needed for this read. + // Update the number of characters in the + // interrupt read buffer. + // + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialUpdateInterruptBuffer, + &updateChar + ); + + reqContext->Status = STATUS_SUCCESS; + + } else { + + // + // The request might go under control of the isr. It + // won't hurt to initialize the reference count + // right now. + // + + SERIAL_INIT_REFERENCE(reqContext); + + // + // If we are supposed to crunch the read down to + // one character, then update the read length + // in the request and truncate the number needed for + // read down to one. Note that if we are doing + // this crunching, then the information must be + // zero (or we would have completed above) and + // the number needed for the read must still be + // equal to the read length. + // + + if (crunchDownToOne) { + + ASSERT( + (!reqContext->Information) + && + (Extension->NumberNeededForRead == reqContext->Length) + ); + + Extension->NumberNeededForRead = 1; + reqContext->Length = 1; + + } + + // + // We still need to get more characters for this read. + // synchronize with the isr so that we can update the + // number of characters and if necessary it will have the + // isr switch to copying into the users buffer. + // + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialUpdateAndSwitchToUser, + &updateChar + ); + + if (!updateChar.Completed) { + + SerialSetCancelRoutine(Extension->CurrentReadRequest, + SerialCancelCurrentRead); + + // + // The request still isn't complete. The + // completion routines will end up reinvoking + // this routine. So we simply leave. + // + // First thought we should start off the total + // timer for the read and increment the reference + // count that the total timer has on the current + // request. Note that this is safe, because even if + // the io has been satisfied by the isr it can't + // complete yet because we still own the cancel + // spinlock. + // + + if (useTotalTimer) { + BOOLEAN result; + + result = SerialSetTimer( + Extension->ReadRequestTotalTimer, + totalTime + ); + + if(result == FALSE) { + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_TOTAL_TIMER + ); + } + + } + + if (useIntervalTimer) { + + BOOLEAN result; + + KeQuerySystemTime( + &Extension->LastReadTime + + ); + result = SerialSetTimer( + Extension->ReadRequestIntervalTimer, + *Extension->IntervalTimeToUse + ); + + if(result == FALSE) { + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_INT_TIMER + ); + } + + } + + break; + + } else { + + reqContext->Status = STATUS_SUCCESS; + } + + } + + } + + // + // Well the operation is complete. + // + + SerialGetNextRequest(&Extension->CurrentReadRequest, + Extension->ReadQueue, + &newRequest, TRUE, Extension); + + } while (newRequest); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "SerialCompleteRead(%p)\n", + extension); + + // + // We set this to indicate to the interval timer + // that the read has completed. + // + // Recall that the interval timer dpc can be lurking in some + // DPC queue. + // + + extension->CountOnLastRead = SERIAL_COMPLETE_READ_COMPLETE; + + SerialTryToCompleteCurrent( + extension, + NULL, + STATUS_SUCCESS, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_ISR + ); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "CountOnLastRead = SERIAL_COMPLETE_READ_CANCEL; + + SerialTryToCompleteCurrent( + extension, + SerialGrabReadFromIsr, + STATUS_CANCELLED, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_CANCEL + ); + +} + + +BOOLEAN +SerialGrabReadFromIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to grab (if possible) the request from the + isr. If it finds that the isr still owns the request it grabs + the ipr away (updating the number of characters copied into the + users buffer). If it grabs it away it also decrements the + reference count on the request since it no longer belongs to the + isr (and the dpc that would complete it). + + NOTE: This routine assumes that if the current buffer that the + ISR is copying characters into is the interrupt buffer then + the dpc has already been queued. + + NOTE: This routine is being called from WdfInterruptSynchronize. + + NOTE: This routine assumes that it is called with the cancel spin + lock held. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + Always false. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension = Context; + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(extension->CurrentReadRequest); + + if (extension->ReadBufferBase != + extension->InterruptReadBuffer) { + + // + // We need to set the information to the number of characters + // that the read wanted minus the number of characters that + // didn't get read into the interrupt buffer. + // + + reqContext->Information = reqContext->Length - + ((extension->LastCharSlot - extension->CurrentCharSlot) + 1); + + // + // Switch back to the interrupt buffer. + // + + extension->ReadBufferBase = extension->InterruptReadBuffer; + extension->CurrentCharSlot = extension->InterruptReadBuffer; + extension->FirstReadableChar = extension->InterruptReadBuffer; + extension->LastCharSlot = extension->InterruptReadBuffer + + (extension->BufferSize - 1); + extension->CharsInInterruptBuffer = 0; + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + } + + return FALSE; + +} + +VOID +SerialReadTimeout( + IN WDFTIMER Timer + ) + +/*++ + +Routine Description: + + This routine is used to complete a read because its total + timer has expired. + +Arguments: + + +Return Value: + + None. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension = NULL; + + extension = SerialGetDeviceExtension(WdfTimerGetParentObject(Timer)); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, ">SerialReadTimeout(%p)\n", + extension); + + // + // We set this to indicate to the interval timer + // that the read has completed due to total timeout. + // + // Recall that the interval timer dpc can be lurking in some + // DPC queue. + // + + extension->CountOnLastRead = SERIAL_COMPLETE_READ_TOTAL; + + SerialTryToCompleteCurrent( + extension, + SerialGrabReadFromIsr, + STATUS_TIMEOUT, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_TOTAL_TIMER + ); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "CountOnLastRead = extension->ReadByIsr; + extension->ReadByIsr = 0; + + return FALSE; + +} + + +VOID +SerialIntervalReadTimeout( + IN WDFTIMER Timer + ) + +/*++ + +Routine Description: + + This routine is used timeout the request if the time between + characters exceed the interval time. A global is kept in + the device extension that records the count of characters read + the last the last time this routine was invoked (This dpc + will resubmit the timer if the count has changed). If the + count has not changed then this routine will attempt to complete + the request. Note the special case of the last count being zero. + The timer isn't really in effect until the first character is + read. + +Arguments: + + +Return Value: + + None. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION extension = NULL; + + extension = SerialGetDeviceExtension(WdfTimerGetParentObject(Timer)); + + + //SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, ">SerialIntervalReadTimeout(%p)\n", + // extension); + + if (extension->CountOnLastRead == SERIAL_COMPLETE_READ_TOTAL) { + + // + // This value is only set by the total + // timer to indicate that it has fired. + // If so, then we should simply try to complete. + // + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, "in SERIAL_COMPLETE_READ_TOTAL\n"); + + SerialTryToCompleteCurrent( + extension, + SerialGrabReadFromIsr, + STATUS_TIMEOUT, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_INT_TIMER + ); + + } else if (extension->CountOnLastRead == SERIAL_COMPLETE_READ_COMPLETE) { + + // + // This value is only set by the regular + // completion routine. + // + // If so, then we should simply try to complete. + // + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, "in SERIAL_COMPLETE_READ_COMPLETE\n"); + + SerialTryToCompleteCurrent( + extension, + SerialGrabReadFromIsr, + STATUS_SUCCESS, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_INT_TIMER + ); + + } else if (extension->CountOnLastRead == SERIAL_COMPLETE_READ_CANCEL) { + + // + // This value is only set by the cancel + // read routine. + // + // If so, then we should simply try to complete. + // + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_INIT, "in SERIAL_COMPLETE_READ_CANCEL\n"); + + SerialTryToCompleteCurrent( + extension, + SerialGrabReadFromIsr, + STATUS_CANCELLED, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_INT_TIMER + ); + + } else if (extension->CountOnLastRead || extension->ReadByIsr) { + + // + // Something has happened since we last came here. We + // check to see if the ISR has read in any more characters. + // If it did then we should update the isr's read count + // and resubmit the timer. + // + + if (extension->ReadByIsr) { + + WdfInterruptSynchronize( + extension->WdfInterrupt, + SerialUpdateReadByIsr, + extension + ); + + // + // Save off the "last" time something was read. + // As we come back to this routine we will compare + // the current time to the "last" time. If the + // difference is ever larger then the interval + // requested by the user, then time out the request. + // + + KeQuerySystemTime( + &extension->LastReadTime + ); + + SerialSetTimer( + extension->ReadRequestIntervalTimer, + *extension->IntervalTimeToUse + ); + + } else { + + // + // Take the difference between the current time + // and the last time we had characters and + // see if it is greater then the interval time. + // if it is, then time out the request. Otherwise + // go away again for a while. + // + + // + // No characters read in the interval time. Kill + // this read. + // + + LARGE_INTEGER currentTime; + + KeQuerySystemTime( + ¤tTime + ); + + if ((currentTime.QuadPart - extension->LastReadTime.QuadPart) >= + extension->IntervalTime.QuadPart) { + + SerialTryToCompleteCurrent( + extension, + SerialGrabReadFromIsr, + STATUS_TIMEOUT, + &extension->CurrentReadRequest, + extension->ReadQueue, + extension->ReadRequestIntervalTimer, + extension->ReadRequestTotalTimer, + SerialStartRead, + SerialGetNextRequest, + SERIAL_REF_INT_TIMER + ); + + } else { + + SerialSetTimer( + extension->ReadRequestIntervalTimer, + *extension->IntervalTimeToUse + ); + + } + + + } + + } else { + + // + // Timer doesn't really start until the first character. + // So we should simply resubmit ourselves. + // + + SerialSetTimer( + extension->ReadRequestIntervalTimer, + *extension->IntervalTimeToUse + ); + + } + + + //SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_READ, "CurrentReadRequest); + + // + // The minimum of the number of characters we need and + // the number of characters available + // + + numberOfCharsToGet = Extension->CharsInInterruptBuffer; + + if (numberOfCharsToGet > Extension->NumberNeededForRead) { + + numberOfCharsToGet = Extension->NumberNeededForRead; + + } + + if (numberOfCharsToGet) { + + // + // This will hold the number of characters between the + // first available character and the end of the buffer. + // Note that the buffer could wrap around but for the + // purposes of the first copy we don't care about that. + // + + firstTryNumberToGet = (ULONG)(Extension->LastCharSlot - + Extension->FirstReadableChar) + 1; + + if (firstTryNumberToGet > numberOfCharsToGet) { + + // + // The characters don't wrap. Actually they may wrap but + // we don't care for the purposes of this read since the + // characters we need are available before the wrap. + // + + RtlMoveMemory( + ((PUCHAR)(reqContext->SystemBuffer)) + + (reqContext->Length - Extension->NumberNeededForRead), + Extension->FirstReadableChar, + numberOfCharsToGet + ); + + Extension->NumberNeededForRead -= numberOfCharsToGet; + + // + // We now will move the pointer to the first character after + // what we just copied into the users buffer. + // + // We need to check if the stream of readable characters + // is wrapping around to the beginning of the buffer. + // + // Note that we may have just taken the last characters + // at the end of the buffer. + // + + if ((Extension->FirstReadableChar + (numberOfCharsToGet - 1)) == + Extension->LastCharSlot) { + + Extension->FirstReadableChar = Extension->InterruptReadBuffer; + + } else { + + Extension->FirstReadableChar += numberOfCharsToGet; + + } + + } else { + + // + // The characters do wrap. Get up until the end of the buffer. + // + + RtlMoveMemory( + ((PUCHAR)(reqContext->SystemBuffer)) + + (reqContext->Length - Extension->NumberNeededForRead), + Extension->FirstReadableChar, + firstTryNumberToGet + ); + + Extension->NumberNeededForRead -= firstTryNumberToGet; + + // + // Now get the rest of the characters from the beginning of the + // buffer. + // + + RtlMoveMemory( + ((PUCHAR)(reqContext->SystemBuffer)) + + (reqContext->Length - Extension->NumberNeededForRead), + Extension->InterruptReadBuffer, + numberOfCharsToGet - firstTryNumberToGet + ); + + Extension->FirstReadableChar = Extension->InterruptReadBuffer + + (numberOfCharsToGet - + firstTryNumberToGet); + + Extension->NumberNeededForRead -= (numberOfCharsToGet - + firstTryNumberToGet); + + } + + } + + reqContext->Information += numberOfCharsToGet; + return numberOfCharsToGet; + +} + + +BOOLEAN +SerialUpdateInterruptBuffer( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to update the number of characters that + remain in the interrupt buffer. We need to use this routine + since the count could be updated during the update by execution + of the ISR. + + NOTE: This is called by WdfInterruptSynchronize. + +Arguments: + + Context - Points to a structure that contains a pointer to the + device extension and count of the number of characters + that we previously copied into the users buffer. The + structure actually has a third field that we don't + use in this routine. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_UPDATE_CHAR update = Context; + PSERIAL_DEVICE_EXTENSION extension = update->Extension; + + UNREFERENCED_PARAMETER(Interrupt); + + ASSERT(extension->CharsInInterruptBuffer >= update->CharsCopied); + extension->CharsInInterruptBuffer -= update->CharsCopied; + + // + // Deal with flow control if necessary. + // + + SerialHandleReducedIntBuffer(extension); + + + return FALSE; + +} + + +BOOLEAN +SerialUpdateAndSwitchToUser( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine gets the (hopefully) few characters that + remain in the interrupt buffer after the first time we tried + to get them out. If we still don't have enough characters + to satisfy the read it will then we set things up so that the + ISR uses the user buffer copy into. + + This routine is also used to update a count that is maintained + by the ISR to keep track of the number of characters in its buffer. + + NOTE: This is called by WdfInterruptSynchronize. + +Arguments: + + Context - Points to a structure that contains a pointer to the + device extension, a count of the number of characters + that we previously copied into the users buffer, and + a boolean that we will set that defines whether we + switched the ISR to copy into the users buffer. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_UPDATE_CHAR updateChar = Context; + PSERIAL_DEVICE_EXTENSION extension = updateChar->Extension; + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(extension->CurrentReadRequest); + + SerialUpdateInterruptBuffer(extension->WdfInterrupt, Context); + + // + // There are more characters to get to satisfy this read. + // Copy any characters that have arrived since we got + // the last batch. + // + + updateChar->CharsCopied = SerialGetCharsFromIntBuffer(extension); + + SerialUpdateInterruptBuffer(extension->WdfInterrupt, Context); + + // + // No more new characters will be "received" until we exit + // this routine. We again check to make sure that we + // haven't satisfied this read, and if we haven't we set things + // up so that the ISR copies into the user buffer. + // + + if (extension->NumberNeededForRead) { + + // + // We shouldn't be switching unless there are no + // characters left. + // + + ASSERT(!extension->CharsInInterruptBuffer); + + // + // We use the following to values to do inteval timing. + // + // CountOnLastRead is mostly used to simply prevent + // the interval timer from timing out before any characters + // are read. (Interval timing should only be effective + // after the first character is read.) + // + // After the first time the interval timer fires and + // characters have be read we will simply update with + // the value of ReadByIsr and then set ReadByIsr to zero. + // (We do that in a synchronization routine. + // + // If the interval timer dpc routine ever encounters + // ReadByIsr == 0 when CountOnLastRead is non-zero it + // will timeout the read. + // + // (Note that we have a special case of CountOnLastRead + // < 0. This is done by the read completion routines other + // than the total timeout dpc to indicate that the total + // timeout has expired.) + // + + extension->CountOnLastRead = (LONG)reqContext->Information; + + extension->ReadByIsr = 0; + + // + // By compareing the read buffer base address to the + // the base address of the interrupt buffer the ISR + // can determine whether we are using the interrupt + // buffer or the user buffer. + // + + extension->ReadBufferBase = reqContext->SystemBuffer; + + // + // The current char slot is after the last copied in + // character. We know there is always room since we + // we wouldn't have gotten here if there wasn't. + // + + extension->CurrentCharSlot = extension->ReadBufferBase + + reqContext->Information; + + // + // The last position that a character can go is on the + // last byte of user buffer. While the actual allocated + // buffer space may be bigger, we know that there is at + // least as much as the read length. + // + + extension->LastCharSlot = extension->ReadBufferBase + + (reqContext->Length - 1); +#if 0 // We set the cancel before calling this routine in StartRead + // + // Mark the request as being in a cancelable state. + // + IoSetCancelRoutine( + extension->CurrentReadIrp, + SerialCancelCurrentRead + ); + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_CANCEL + ); +#endif + // + // Increment the reference count twice. + // + // Once for the Isr owning the request and once + // because the cancel routine has a reference + // to it. + // + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + updateChar->Completed = FALSE; + + } else { + + updateChar->Completed = TRUE; + + } + + return FALSE; + +} +// +// We use this structure only to communicate to the synchronization +// routine when we are switching to the resized buffer. +// +typedef struct _SERIAL_RESIZE_PARAMS { + PSERIAL_DEVICE_EXTENSION Extension; + PUCHAR OldBuffer; + PUCHAR NewBuffer; + ULONG NewBufferSize; + ULONG NumberMoved; + } SERIAL_RESIZE_PARAMS,*PSERIAL_RESIZE_PARAMS; + + +NTSTATUS +SerialResizeBuffer( + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + This routine will process the resize buffer request. + If size requested for the RX buffer is smaller than + the current buffer then we will simply return + STATUS_SUCCESS. (We don't want to make buffers smaller. + If we did that then we all of a sudden have "overrun" + problems to deal with as well as flow control to deal + with - very painful.) We ignore the TX buffer size + request since we don't use a TX buffer. + +Arguments: + + Extension - Pointer to the device extension for the port. + +Return Value: + + STATUS_SUCCESS if everything worked out ok. + STATUS_INSUFFICIENT_RESOURCES if we couldn't allocate the + memory for the buffer. + +--*/ + +{ + + PREQUEST_CONTEXT reqContext = SerialGetRequestContext(Extension->CurrentReadRequest); + PSERIAL_QUEUE_SIZE rs = reqContext->SystemBuffer; + + PVOID newBuffer = reqContext->Type3InputBuffer; + + + reqContext->Type3InputBuffer = NULL; + reqContext->Information = 0L; + reqContext->Status = STATUS_SUCCESS; + + if (rs->InSize <= Extension->BufferSize) { + + // + // Nothing to do. We don't make buffers smaller. Just + // agree with the user. We must deallocate the memory + // that was already allocated in the ioctl dispatch routine. + // + + ExFreePool(newBuffer); + + } else { + + SERIAL_RESIZE_PARAMS rp; + + // + // Hmmm, looks like we actually have to go + // through with this. We need to move all the + // data that is in the current buffer into this + // new buffer. We'll do this in two steps. + // + // First we go up to dispatch level and try to + // move as much as we can without stopping the + // ISR from running. We go up to dispatch level + // by acquiring the control lock. We do it at + // dispatch using the control lock so that: + // + // 1) We can't be context switched in the middle + // of the move. Our pointers into the buffer + // could be *VERY* stale by the time we got back. + // + // 2) We use the control lock since we don't want + // some pesky purge request to come along while + // we are trying to move. + // + // After the move, but while we still hold the control + // lock, we synch with the ISR and get those last + // (hopefully) few characters that have come in since + // we started the copy. We switch all of our pointers, + // counters, and such to point to this new buffer. NOTE: + // we need to be careful. If the buffer we were using + // was not the default one created when we initialized + // the device (i.e. it was created via a previous WDFREQUEST of + // this type), we should deallocate it. + // + + rp.Extension = Extension; + rp.OldBuffer = Extension->InterruptReadBuffer; + rp.NewBuffer = newBuffer; + rp.NewBufferSize = rs->InSize; + + rp.NumberMoved = SerialMoveToNewIntBuffer( + Extension, + newBuffer + ); + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialUpdateAndSwitchToNew, + &rp + ); + + // + // Free up the memory that the old buffer consumed. + // + + ExFreePool(rp.OldBuffer); + + } + + return STATUS_SUCCESS; + +} + + +ULONG +SerialMoveToNewIntBuffer( + PSERIAL_DEVICE_EXTENSION Extension, + PUCHAR NewBuffer + ) + +/*++ + +Routine Description: + + This routine is used to copy any characters out of the interrupt + buffer into the "new" buffer. It will be reading values that + are updated with the ISR but this is safe since this value is + only decremented by synchronization routines. This routine will + return the number of characters copied so some other routine + can call a synchronization routine to update what is seen at + interrupt level. + +Arguments: + + Extension - A pointer to the device extension. + NewBuffer - Where the characters are to be move to. + +Return Value: + + The number of characters that were copied into the user + buffer. + +--*/ + +{ + + ULONG numberOfCharsMoved = Extension->CharsInInterruptBuffer; + + + if (numberOfCharsMoved) { + + // + // This holds the number of characters between the first + // readable character and the last character we will read or + // the real physical end of the buffer (not the last readable + // character). + // + ULONG firstTryNumberToGet = (ULONG)(Extension->LastCharSlot - + Extension->FirstReadableChar) + 1; + + if (firstTryNumberToGet >= numberOfCharsMoved) { + + // + // The characters don't wrap. + // + + RtlMoveMemory( + NewBuffer, + Extension->FirstReadableChar, + numberOfCharsMoved + ); + + if ((Extension->FirstReadableChar+(numberOfCharsMoved-1)) == + Extension->LastCharSlot) { + + Extension->FirstReadableChar = Extension->InterruptReadBuffer; + + } else { + + Extension->FirstReadableChar += numberOfCharsMoved; + + } + + } else { + + // + // The characters do wrap. Get up until the end of the buffer. + // + + RtlMoveMemory( + NewBuffer, + Extension->FirstReadableChar, + firstTryNumberToGet + ); + + // + // Now get the rest of the characters from the beginning of the + // buffer. + // + + RtlMoveMemory( + NewBuffer+firstTryNumberToGet, + Extension->InterruptReadBuffer, + numberOfCharsMoved - firstTryNumberToGet + ); + + Extension->FirstReadableChar = Extension->InterruptReadBuffer + + numberOfCharsMoved - firstTryNumberToGet; + + } + + } + + return numberOfCharsMoved; + +} + + +BOOLEAN +SerialUpdateAndSwitchToNew( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine gets the (hopefully) few characters that + remain in the interrupt buffer after the first time we tried + to get them out. + + NOTE: This is called by WdfInterruptSynchronize. + +Arguments: + + Context - Points to a structure that contains a pointer to the + device extension, a pointer to the buffer we are moving + to, and a count of the number of characters + that we previously copied into the new buffer, and the + actual size of the new buffer. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_RESIZE_PARAMS params = Context; + PSERIAL_DEVICE_EXTENSION extension = params->Extension; + ULONG tempCharsInInterruptBuffer = extension->CharsInInterruptBuffer; + + UNREFERENCED_PARAMETER(Interrupt); + + ASSERT(extension->CharsInInterruptBuffer >= params->NumberMoved); + + // + // We temporarily reduce the chars in interrupt buffer to + // "fool" the move routine. We will restore it after the + // move. + // + + extension->CharsInInterruptBuffer -= params->NumberMoved; + + if (extension->CharsInInterruptBuffer) { + + SerialMoveToNewIntBuffer( + extension, + params->NewBuffer + params->NumberMoved + ); + + } + + extension->CharsInInterruptBuffer = tempCharsInInterruptBuffer; + + + extension->LastCharSlot = params->NewBuffer + (params->NewBufferSize - 1); + extension->FirstReadableChar = params->NewBuffer; + extension->ReadBufferBase = params->NewBuffer; + extension->InterruptReadBuffer = params->NewBuffer; + extension->BufferSize = params->NewBufferSize; + + // + // We *KNOW* that the new interrupt buffer is larger than the + // old buffer. We don't need to worry about it being full. + // + + extension->CurrentCharSlot = extension->InterruptReadBuffer + + extension->CharsInInterruptBuffer; + + // + // We set up the default xon/xoff limits. + // + + extension->HandFlow.XoffLimit = extension->BufferSize >> 3; + extension->HandFlow.XonLimit = extension->BufferSize >> 1; + + extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit; + extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit; + + extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+ + (extension->BufferSize>>4)); + + // + // Since we (essentially) reduced the percentage of the interrupt + // buffer being full, we need to handle any flow control. + // + + SerialHandleReducedIntBuffer(extension); + + return FALSE; + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/registry.c b/tests/projects/windows/driver/kmdf/serial/registry.c new file mode 100644 index 000000000..5ab25955a --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/registry.c @@ -0,0 +1,443 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + registry.c + +Abstract: + + This module contains the code that is used to get values from the + registry and to manipulate entries in the registry. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "registry.tmh" +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,SerialGetConfigDefaults) +#pragma alloc_text(PAGESRP0,SerialGetRegistryKeyValue) +#pragma alloc_text(PAGESRP0,SerialPutRegistryKeyValue) +#pragma alloc_text(PAGESRP0,SerialGetFdoRegistryKeyValue) +#endif // ALLOC_PRAGMA + + +#define PARAMATER_NAME_LEN 80 + + +NTSTATUS +SerialGetConfigDefaults( + IN PSERIAL_FIRMWARE_DATA DriverDefaultsPtr, + IN WDFDRIVER Driver + ) + +/*++ + +Routine Description: + + This routine reads the default configuration data from the + registry for the serial driver. + + It also builds fields in the registry for several configuration + options if they don't exist. + +Arguments: + + DriverDefaultsPtr - Pointer to a structure that will contain + the default configuration values. + + RegistryPath - points to the entry for this driver in the + current control set of the registry. + +Return Value: + + STATUS_SUCCESS if we got the defaults, otherwise we failed. + The only way to fail this call is if the STATUS_INSUFFICIENT_RESOURCES. + +--*/ + +{ + + NTSTATUS status = STATUS_SUCCESS; // return value + WDFKEY hKey; + DECLARE_UNICODE_STRING_SIZE(valueName,PARAMATER_NAME_LEN); + + status = WdfDriverOpenParametersRegistryKey(Driver, + STANDARD_RIGHTS_ALL, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + if (!NT_SUCCESS (status)) { + return status; + } + + status = RtlUnicodeStringPrintf(&valueName,L"BreakOnEntry"); + if (!NT_SUCCESS (status)) { + goto End; + + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->ShouldBreakOnEntry); + + if (!NT_SUCCESS (status)) { + DriverDefaultsPtr->ShouldBreakOnEntry = 0; + } + + status = RtlUnicodeStringPrintf(&valueName,L"DebugLevel"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->DebugLevel); + + if (!NT_SUCCESS (status)) { + DriverDefaultsPtr->DebugLevel = 0; + } + + + status = RtlUnicodeStringPrintf(&valueName,L"ForceFifoEnable"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->ForceFifoEnableDefault); + + if (!NT_SUCCESS (status)) { + + // + // If it isn't then write out values so that it could + // be adjusted later. + // + DriverDefaultsPtr->ForceFifoEnableDefault = SERIAL_FORCE_FIFO_DEFAULT; + + status = WdfRegistryAssignULong(hKey, + &valueName, + DriverDefaultsPtr->ForceFifoEnableDefault + ); + if (!NT_SUCCESS (status)) { + goto End; + } + + } + + status = RtlUnicodeStringPrintf(&valueName,L"RxFIFO"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->RxFIFODefault); + + if (!NT_SUCCESS (status)) { + + DriverDefaultsPtr->RxFIFODefault = SERIAL_RX_FIFO_DEFAULT; + + status = WdfRegistryAssignULong(hKey, + &valueName, + DriverDefaultsPtr->RxFIFODefault + ); + if (!NT_SUCCESS (status)) { + goto End; + } + + } + + status = RtlUnicodeStringPrintf(&valueName,L"TxFIFO"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->TxFIFODefault); + + if (!NT_SUCCESS (status)) { + + DriverDefaultsPtr->TxFIFODefault = SERIAL_TX_FIFO_DEFAULT; + + status = WdfRegistryAssignULong(hKey, + &valueName, + DriverDefaultsPtr->TxFIFODefault + ); + if (!NT_SUCCESS (status)) { + goto End; + } + + } + + status = RtlUnicodeStringPrintf(&valueName,L"PermitShare"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->PermitShareDefault); + + if (!NT_SUCCESS (status)) { + + DriverDefaultsPtr->PermitShareDefault = SERIAL_PERMIT_SHARE_DEFAULT; + + status = WdfRegistryAssignULong(hKey, + &valueName, + DriverDefaultsPtr->PermitShareDefault + ); + if (!NT_SUCCESS (status)) { + goto End; + } + + } + + status = RtlUnicodeStringPrintf(&valueName,L"LogFifo"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->LogFifoDefault); + + if (!NT_SUCCESS (status)) { + + DriverDefaultsPtr->LogFifoDefault = SERIAL_LOG_FIFO_DEFAULT; + + status = WdfRegistryAssignULong(hKey, + &valueName, + DriverDefaultsPtr->LogFifoDefault + ); + if (!NT_SUCCESS (status)) { + goto End; + } + + DriverDefaultsPtr->LogFifoDefault = 1; + } + + + status = RtlUnicodeStringPrintf(&valueName,L"UartRemovalDetect"); + if (!NT_SUCCESS (status)) { + goto End; + } + + status = WdfRegistryQueryULong (hKey, + &valueName, + &DriverDefaultsPtr->UartRemovalDetect); + + if (!NT_SUCCESS (status)) { + DriverDefaultsPtr->UartRemovalDetect = 0; + } + + +End: + WdfRegistryClose(hKey); + return (status); +} + +BOOLEAN +SerialGetRegistryKeyValue( + IN WDFDEVICE WdfDevice, + _In_ PCWSTR Name, + OUT PULONG Value + ) +/*++ + +Routine Description: + + Can be used to read any REG_DWORD registry value stored + under Device Parameter. + +Arguments: + + FdoData - pointer to the device extension + Name - Name of the registry value + Value - + + +Return Value: + + TRUE if successful + FALSE if not present/error in reading registry + +--*/ +{ + WDFKEY hKey = NULL; + NTSTATUS status; + BOOLEAN retValue = FALSE; + UNICODE_STRING valueName; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, ">SerialGetRegistryKeyValue(XXX)\n"); + + *Value = 0; + + status = WdfDeviceOpenRegistryKey(WdfDevice, + PLUGPLAY_REGKEY_DEVICE, + STANDARD_RIGHTS_ALL, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + + if (NT_SUCCESS (status)) { + + RtlInitUnicodeString(&valueName,Name); + + status = WdfRegistryQueryULong (hKey, + &valueName, + Value); + + if (NT_SUCCESS (status)) { + retValue = TRUE; + } + + WdfRegistryClose(hKey); + } + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "<--SerialGetRegistryKeyValue %ws %d \n", + Name, *Value); + + return retValue; +} + +#define PARAMATER_NAME_LEN 80 + +BOOLEAN +SerialPutRegistryKeyValue( + IN WDFDEVICE WdfDevice, + _In_ PCWSTR Name, + IN ULONG Value + ) +/*++ + +Routine Description: + + Can be used to write any REG_DWORD registry value stored + under Device Parameter. + +Arguments: + + +Return Value: + + TRUE - if write is successful + FALSE - otherwise + +--*/ +{ + WDFKEY hKey = NULL; + NTSTATUS status; + BOOLEAN retValue = FALSE; + UNICODE_STRING valueName; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, "Entered PciDrvWriteRegistryValue\n"); + + // + // write the value out to the registry + // + status = WdfDeviceOpenRegistryKey(WdfDevice, + PLUGPLAY_REGKEY_DEVICE, + STANDARD_RIGHTS_ALL, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + + if (NT_SUCCESS (status)) { + + RtlInitUnicodeString(&valueName,Name); + + status = WdfRegistryAssignULong (hKey, + &valueName, + Value + ); + + if (NT_SUCCESS (status)) { + retValue = TRUE; + } + + WdfRegistryClose(hKey); + } + + return retValue; + +} + +BOOLEAN +SerialGetFdoRegistryKeyValue( + IN PWDFDEVICE_INIT DeviceInit, + _In_ PCWSTR Name, + OUT PULONG Value + ) +/*++ + +Routine Description: + + Can be used to read any REG_DWORD registry value stored + under Device Parameter. + +Arguments: + + FdoData - pointer to the device extension + Name - Name of the registry value + Value - + + +Return Value: + + TRUE if successful + FALSE if not present/error in reading registry + +--*/ +{ + WDFKEY hKey = NULL; + NTSTATUS status; + BOOLEAN retValue = FALSE; + UNICODE_STRING valueName; + + PAGED_CODE(); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, + "-->SerialGetFdoRegistryKeyValue\n"); + + *Value = 0; + + status = WdfFdoInitOpenRegistryKey(DeviceInit, + PLUGPLAY_REGKEY_DEVICE, + STANDARD_RIGHTS_ALL, + WDF_NO_OBJECT_ATTRIBUTES, + &hKey); + + if (NT_SUCCESS (status)) { + + RtlInitUnicodeString(&valueName,Name); + + status = WdfRegistryQueryULong (hKey, &valueName, Value); + + if (NT_SUCCESS (status)) { + retValue = TRUE; + } + + WdfRegistryClose(hKey); + } + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, + "<--SerialGetFdoRegistryKeyValue %ws %d \n", + Name, *Value); + + return retValue; +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/serial.h b/tests/projects/windows/driver/kmdf/serial/serial.h new file mode 100644 index 000000000..fcbf9748f --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/serial.h @@ -0,0 +1,1757 @@ +/*++ + +Copyright (c) 1990, 1991, 1992, 1993 - 1997 Microsoft Corporation + +Module Name : + + serial.h + +Abstract: + + Type definitions and data for the serial port driver + +--*/ + +#define POOL_TAG 'XMOC' + + +// +// Some default driver values. We will check the registry for +// them first. +// +#define SERIAL_UNINITIALIZED_DEFAULT 1234567 +#define SERIAL_FORCE_FIFO_DEFAULT 1 +#define SERIAL_RX_FIFO_DEFAULT 8 +#define SERIAL_TX_FIFO_DEFAULT 14 +#define SERIAL_PERMIT_SHARE_DEFAULT 0 +#define SERIAL_LOG_FIFO_DEFAULT 0 + + +// +// This define gives the default Object directory +// that we should use to insert the symbolic links +// between the NT device name and namespace used by +// that object directory. +#define DEFAULT_DIRECTORY L"DosDevices" + +// +// For the above directory, the serial port will +// use the following name as the suffix of the serial +// ports for that directory. It will also append +// a number onto the end of the name. That number +// will start at 1. +#define DEFAULT_SERIAL_NAME L"COM" +// +// +// This define gives the default NT name for +// for serial ports detected by the firmware. +// This name will be appended to Device prefix +// with a number following it. The number is +// incremented each time encounter a serial +// port detected by the firmware. Note that +// on a system with multiple busses, this means +// that the first port on a bus is not necessarily +// \Device\Serial0. +// +#define DEFAULT_NT_SUFFIX L"Serial" +#define _DRIVER_NAME_ "Serial.sys" + +#define DEVICE_OBJECT_NAME_LENGTH 128 +#define SYMBOLIC_NAME_LENGTH 128 +#define SERIAL_DEVICE_MAP L"SERIALCOMM" + +// +// GUID_DEVINTERFACE_COMPORT is not defined in the Win2K +// headers, so we will need this definition to avoid compilation +// errors. +// +#define GUID_DEVINTERFACE_COMPORT GUID_CLASS_COMPORT + +// +// This value - which could be redefined at compile +// time, define the stride between registers +// +#if !defined(SERIAL_REGISTER_STRIDE) +#define SERIAL_REGISTER_STRIDE 1 +#endif + +// +// Offsets from the base register address of the +// various registers for the 8250 family of UARTS. +// +#define RECEIVE_BUFFER_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE)) +#define TRANSMIT_HOLDING_REGISTER ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE)) +#define INTERRUPT_ENABLE_REGISTER ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE)) +#define INTERRUPT_IDENT_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE)) +#define FIFO_CONTROL_REGISTER ((ULONG)((0x02)*SERIAL_REGISTER_STRIDE)) +#define LINE_CONTROL_REGISTER ((ULONG)((0x03)*SERIAL_REGISTER_STRIDE)) +#define MODEM_CONTROL_REGISTER ((ULONG)((0x04)*SERIAL_REGISTER_STRIDE)) +#define LINE_STATUS_REGISTER ((ULONG)((0x05)*SERIAL_REGISTER_STRIDE)) +#define MODEM_STATUS_REGISTER ((ULONG)((0x06)*SERIAL_REGISTER_STRIDE)) +#define DIVISOR_LATCH_LSB ((ULONG)((0x00)*SERIAL_REGISTER_STRIDE)) +#define DIVISOR_LATCH_MSB ((ULONG)((0x01)*SERIAL_REGISTER_STRIDE)) +#define SERIAL_REGISTER_SPAN ((ULONG)(7*SERIAL_REGISTER_STRIDE)) + +// +// If we have an interrupt status register this is its assumed +// length. +// +#define SERIAL_STATUS_LENGTH ((ULONG)(1*SERIAL_REGISTER_STRIDE)) + +// +// Bitmask definitions for accessing the 8250 device registers. +// + +// +// These bits define the number of data bits trasmitted in +// the Serial Data Unit (SDU - Start,data, parity, and stop bits) +// +#define SERIAL_DATA_LENGTH_5 0x00 +#define SERIAL_DATA_LENGTH_6 0x01 +#define SERIAL_DATA_LENGTH_7 0x02 +#define SERIAL_DATA_LENGTH_8 0x03 + + +// +// These masks define the interrupts that can be enabled or disabled. +// +// +// This interrupt is used to notify that there is new incomming +// data available. The SERIAL_RDA interrupt is enabled by this bit. +// +#define SERIAL_IER_RDA 0x01 + +// +// This interrupt is used to notify that there is space available +// in the transmitter for another character. The SERIAL_THR +// interrupt is enabled by this bit. +// +#define SERIAL_IER_THR 0x02 + +// +// This interrupt is used to notify that some sort of error occured +// with the incomming data. The SERIAL_RLS interrupt is enabled by +// this bit. +#define SERIAL_IER_RLS 0x04 + +// +// This interrupt is used to notify that some sort of change has +// taken place in the modem control line. The SERIAL_MS interrupt is +// enabled by this bit. +// +#define SERIAL_IER_MS 0x08 + + +// +// These masks define the values of the interrupt identification +// register. The low bit must be clear in the interrupt identification +// register for any of these interrupts to be valid. The interrupts +// are defined in priority order, with the highest value being most +// important. See above for a description of what each interrupt +// implies. +// +#define SERIAL_IIR_RLS 0x06 +#define SERIAL_IIR_RDA 0x04 +#define SERIAL_IIR_CTI 0x0c +#define SERIAL_IIR_THR 0x02 +#define SERIAL_IIR_MS 0x00 + +// +// This bit mask get the value of the high two bits of the +// interrupt id register. If this is a 16550 class chip +// these bits will be a one if the fifo's are enbled, otherwise +// they will always be zero. +// +#define SERIAL_IIR_FIFOS_ENABLED 0xc0 + +// +// If the low bit is logic one in the interrupt identification register +// this implies that *NO* interrupts are pending on the device. +// +#define SERIAL_IIR_NO_INTERRUPT_PENDING 0x01 + + +// +// Use these bits to detect removal of serial card for Stratus implementation +// +#define SERIAL_IIR_MUST_BE_ZERO 0x30 + + +// +// These masks define access to the fifo control register. +// + +// +// Enabling this bit in the fifo control register will turn +// on the fifos. If the fifos are enabled then the high two +// bits of the interrupt id register will be set to one. Note +// that this only occurs on a 16550 class chip. If the high +// two bits in the interrupt id register are not one then +// we know we have a lower model chip. +// +// +#define SERIAL_FCR_ENABLE ((UCHAR)0x01) +#define SERIAL_FCR_RCVR_RESET ((UCHAR)0x02) +#define SERIAL_FCR_TXMT_RESET ((UCHAR)0x04) + +// +// This set of values define the high water marks (when the +// interrupts trip) for the receive fifo. +// +#define SERIAL_1_BYTE_HIGH_WATER ((UCHAR)0x00) +#define SERIAL_4_BYTE_HIGH_WATER ((UCHAR)0x40) +#define SERIAL_8_BYTE_HIGH_WATER ((UCHAR)0x80) +#define SERIAL_14_BYTE_HIGH_WATER ((UCHAR)0xc0) + +// +// These masks define access to the line control register. +// + +// +// This defines the bit used to control the definition of the "first" +// two registers for the 8250. These registers are the input/output +// register and the interrupt enable register. When the DLAB bit is +// enabled these registers become the least significant and most +// significant bytes of the divisor value. +// +#define SERIAL_LCR_DLAB 0x80 + +// +// This defines the bit used to control whether the device is sending +// a break. When this bit is set the device is sending a space (logic 0). +// +// Most protocols will assume that this is a hangup. +// +#define SERIAL_LCR_BREAK 0x40 + +// +// These defines are used to set the line control register. +// +#define SERIAL_5_DATA ((UCHAR)0x00) +#define SERIAL_6_DATA ((UCHAR)0x01) +#define SERIAL_7_DATA ((UCHAR)0x02) +#define SERIAL_8_DATA ((UCHAR)0x03) +#define SERIAL_DATA_MASK ((UCHAR)0x03) + +#define SERIAL_1_STOP ((UCHAR)0x00) +#define SERIAL_1_5_STOP ((UCHAR)0x04) // Only valid for 5 data bits +#define SERIAL_2_STOP ((UCHAR)0x04) // Not valid for 5 data bits +#define SERIAL_STOP_MASK ((UCHAR)0x04) + +#define SERIAL_NONE_PARITY ((UCHAR)0x00) +#define SERIAL_ODD_PARITY ((UCHAR)0x08) +#define SERIAL_EVEN_PARITY ((UCHAR)0x18) +#define SERIAL_MARK_PARITY ((UCHAR)0x28) +#define SERIAL_SPACE_PARITY ((UCHAR)0x38) +#define SERIAL_PARITY_MASK ((UCHAR)0x38) + +// +// These masks define access the modem control register. +// + +// +// This bit controls the data terminal ready (DTR) line. When +// this bit is set the line goes to logic 0 (which is then inverted +// by normal hardware). This is normally used to indicate that +// the device is available to be used. Some odd hardware +// protocols (like the kernel debugger) use this for handshaking +// purposes. +// +#define SERIAL_MCR_DTR 0x01 + +// +// This bit controls the ready to send (RTS) line. When this bit +// is set the line goes to logic 0 (which is then inverted by the normal +// hardware). This is used for hardware handshaking. It indicates that +// the hardware is ready to send data and it is waiting for the +// receiving end to set clear to send (CTS). +// +#define SERIAL_MCR_RTS 0x02 + +// +// This bit is used for general purpose output. +// +#define SERIAL_MCR_OUT1 0x04 + +// +// This bit is used for general purpose output. +// +#define SERIAL_MCR_OUT2 0x08 + +// +// This bit controls the loopback testing mode of the device. Basically +// the outputs are connected to the inputs (and vice versa). +// +#define SERIAL_MCR_LOOP 0x10 + +// +// This bit enables auto flow control on a TI TL16C550C/TL16C550CI +// + +#define SERIAL_MCR_TL16C550CAFE 0x20 + + +// +// These masks define access to the line status register. The line +// status register contains information about the status of data +// transfer. The first five bits deal with receive data and the +// last two bits deal with transmission. An interrupt is generated +// whenever bits 1 through 4 in this register are set. +// + +// +// This bit is the data ready indicator. It is set to indicate that +// a complete character has been received. This bit is cleared whenever +// the receive buffer register has been read. +// +#define SERIAL_LSR_DR 0x01 + +// +// This is the overrun indicator. It is set to indicate that the receive +// buffer register was not read befor a new character was transferred +// into the buffer. This bit is cleared when this register is read. +// +#define SERIAL_LSR_OE 0x02 + +// +// This is the parity error indicator. It is set whenever the hardware +// detects that the incoming serial data unit does not have the correct +// parity as defined by the parity select in the line control register. +// This bit is cleared by reading this register. +// +#define SERIAL_LSR_PE 0x04 + +// +// This is the framing error indicator. It is set whenever the hardware +// detects that the incoming serial data unit does not have a valid +// stop bit. This bit is cleared by reading this register. +// +#define SERIAL_LSR_FE 0x08 + +// +// This is the break interrupt indicator. It is set whenever the data +// line is held to logic 0 for more than the amount of time it takes +// to send one serial data unit. This bit is cleared whenever the +// this register is read. +// +#define SERIAL_LSR_BI 0x10 + +// +// This is the transmit holding register empty indicator. It is set +// to indicate that the hardware is ready to accept another character +// for transmission. This bit is cleared whenever a character is +// written to the transmit holding register. +// +#define SERIAL_LSR_THRE 0x20 + +// +// This bit is the transmitter empty indicator. It is set whenever the +// transmit holding buffer is empty and the transmit shift register +// (a non-software accessable register that is used to actually put +// the data out on the wire) is empty. Basically this means that all +// data has been sent. It is cleared whenever the transmit holding or +// the shift registers contain data. +// +#define SERIAL_LSR_TEMT 0x40 + +// +// This bit indicates that there is at least one error in the fifo. +// The bit will not be turned off until there are no more errors +// in the fifo. +// +#define SERIAL_LSR_FIFOERR 0x80 + + +// +// These masks are used to access the modem status register. +// Whenever one of the first four bits in the modem status +// register changes state a modem status interrupt is generated. +// + +// +// This bit is the delta clear to send. It is used to indicate +// that the clear to send bit (in this register) has *changed* +// since this register was last read by the CPU. +// +#define SERIAL_MSR_DCTS 0x01 + +// +// This bit is the delta data set ready. It is used to indicate +// that the data set ready bit (in this register) has *changed* +// since this register was last read by the CPU. +// +#define SERIAL_MSR_DDSR 0x02 + +// +// This is the trailing edge ring indicator. It is used to indicate +// that the ring indicator input has changed from a low to high state. +// +#define SERIAL_MSR_TERI 0x04 + +// +// This bit is the delta data carrier detect. It is used to indicate +// that the data carrier bit (in this register) has *changed* +// since this register was last read by the CPU. +// +#define SERIAL_MSR_DDCD 0x08 + +// +// This bit contains the (complemented) state of the clear to send +// (CTS) line. +// +#define SERIAL_MSR_CTS 0x10 + +// +// This bit contains the (complemented) state of the data set ready +// (DSR) line. +// +#define SERIAL_MSR_DSR 0x20 + +// +// This bit contains the (complemented) state of the ring indicator +// (RI) line. +// +#define SERIAL_MSR_RI 0x40 + +// +// This bit contains the (complemented) state of the data carrier detect +// (DCD) line. +// +#define SERIAL_MSR_DCD 0x80 + +// +// This should be more than enough space to hold then +// numeric suffix of the device name. +// +#define DEVICE_NAME_DELTA 20 + + +// +// Up to 16 Ports Per card. However for sixteen +// port cards the interrupt status register must me +// the indexing kind rather then the bitmask kind. +// +// +#define SERIAL_MAX_PORTS_INDEXED (16) +#define SERIAL_MAX_PORTS_NONINDEXED (8) + +typedef struct _CONFIG_DATA { + PHYSICAL_ADDRESS Controller; + PHYSICAL_ADDRESS TrController; + ULONG SpanOfController; + ULONG ClockRate; + ULONG AddressSpace; + ULONG DisablePort; + ULONG ForceFifoEnable; + ULONG RxFIFO; + ULONG TxFIFO; + ULONG PermitShare; + ULONG PermitSystemWideShare; + ULONG LogFifo; + KINTERRUPT_MODE InterruptMode; + ULONG TrVector; + ULONG TrIrql; + KAFFINITY Affinity; + ULONG TL16C550CAFC; + } CONFIG_DATA,*PCONFIG_DATA; + + +// +// This structure contains configuration data, much of which +// is read from the registry. +// +typedef struct _SERIAL_FIRMWARE_DATA { + PDRIVER_OBJECT DriverObject; + ULONG ControllersFound; + ULONG ForceFifoEnableDefault; + ULONG DebugLevel; + ULONG ShouldBreakOnEntry; + ULONG RxFIFODefault; + ULONG TxFIFODefault; + ULONG PermitShareDefault; + ULONG PermitSystemWideShare; + ULONG LogFifoDefault; + ULONG UartRemovalDetect; + UNICODE_STRING Directory; + UNICODE_STRING NtNameSuffix; + UNICODE_STRING DirectorySymbolicName; + LIST_ENTRY ConfigList; +} SERIAL_FIRMWARE_DATA,*PSERIAL_FIRMWARE_DATA; + +// +// Default xon/xoff characters. +// +#define SERIAL_DEF_XON 0x11 +#define SERIAL_DEF_XOFF 0x13 + +// +// Reasons that recption may be held up. +// +#define SERIAL_RX_DTR ((ULONG)0x01) +#define SERIAL_RX_XOFF ((ULONG)0x02) +#define SERIAL_RX_RTS ((ULONG)0x04) +#define SERIAL_RX_DSR ((ULONG)0x08) + +// +// Reasons that transmission may be held up. +// +#define SERIAL_TX_CTS ((ULONG)0x01) +#define SERIAL_TX_DSR ((ULONG)0x02) +#define SERIAL_TX_DCD ((ULONG)0x04) +#define SERIAL_TX_XOFF ((ULONG)0x08) +#define SERIAL_TX_BREAK ((ULONG)0x10) + +// +// These values are used by the routines that can be used +// to complete a read (other than interval timeout) to indicate +// to the interval timeout that it should complete. +// +#define SERIAL_COMPLETE_READ_CANCEL ((LONG)-1) +#define SERIAL_COMPLETE_READ_TOTAL ((LONG)-2) +#define SERIAL_COMPLETE_READ_COMPLETE ((LONG)-3) + +// +// These are default values that shouldn't appear in the registry +// +#define SERIAL_BAD_VALUE ((ULONG)-1) + + +typedef struct _SERIAL_DEVICE_STATE { + // + // TRUE if we need to set the state to open + // on a powerup + // + + BOOLEAN Reopen; + + // + // Hardware registers + // + + UCHAR IER; + // FCR is known by other values + UCHAR LCR; + UCHAR MCR; + // LSR is never written + // MSR is never written + // SCR is either scratch or interrupt status + + +} SERIAL_DEVICE_STATE, *PSERIAL_DEVICE_STATE; + + +typedef +UCHAR +(*PREAD_PORT_UCHAR)( + IN UCHAR *Register + ); + +typedef +VOID +(*PWRITE_PORT_UCHAR)( + IN UCHAR *Register, + IN UCHAR Value + ); + +typedef struct _SERIAL_DEVICE_EXTENSION { + // + // WDF device handle + // + WDFDEVICE WdfDevice; + // + // Points to the device object that contains + // this device extension. + // + PDEVICE_OBJECT DeviceObject; + // + // We keep a pointer around to our device name for dumps + // and for creating "external" symbolic links to this + // device. + // + UNICODE_STRING DeviceName; + // + // Pointer to the driver object + // + + PDRIVER_OBJECT DriverObject; + + // + // Records whether we actually created the symbolic link name + // at driver load time. If we didn't create it, we won't try + // to destroy it when we unload. + // + BOOLEAN CreatedSymbolicLink; + + // + // Records whether we actually created an entry in SERIALCOMM + // at driver load time. If we didn't create it, we won't try + // to destroy it when the device is removed. + // + BOOLEAN CreatedSerialCommEntry; + + // + // Did we update system count for serial ports + // + BOOLEAN IsSystemConfigInfoUpdated; + + // + // Should we expose external interfaces? + // + ULONG SkipNaming; + + // + // Support the TI TL16C550C and TL16C550CI auto flow control + // + + ULONG TL16C550CAFC; + + // + // Detect removed hardware in intterrupt routine flag + // + ULONG UartRemovalDetect; + + // + // We keep track of whether the somebody has the device currently + // opened with a simple boolean. We need to know this so that + // spurious interrupts from the device (especially during initialization) + // will be ignored. This value is only accessed in the ISR and + // is only set via synchronization routines. We may be able + // to get rid of this boolean when the code is more fleshed out. + // + BOOLEAN DeviceIsOpened; + + // + // Current state during powerdown + // + + SERIAL_DEVICE_STATE DeviceState; + + // + // TRUE if we own power policy + // + + BOOLEAN OwnsPowerPolicy; + + // + // TRUE if we should retain power on close and not aggressively + // reduce power consumption + // + + BOOLEAN RetainPowerOnClose; + + // + // Should we enable wakeup + // + + BOOLEAN IsWakeEnabled; + + // + // This list head is used to contain the time ordered list + // of read requests. Access to this list is protected by + // the global cancel spinlock. + // + WDFQUEUE ReadQueue; + + // + // This list head is used to contain the time ordered list + // of write requests. Access to this list is protected by + // the global cancel spinlock. + // + WDFQUEUE WriteQueue; + + // + // This list head is used to contain the time ordered list + // of set and wait mask requests. Access to this list is protected by + // the global cancel spinlock. + // + WDFQUEUE MaskQueue; + + // + // Holds the serialized list of purge requests. + // + WDFQUEUE PurgeQueue; + + // + // This points to the request that is currently being processed + // for the read queue. This field is initialized by the open to + // NULL. + // + // This value is only set at dispatch level. It may be + // read at interrupt level. + // + WDFREQUEST CurrentReadRequest; + + // + // This points to the request that is currently being processed + // for the write queue. + // + // This value is only set at dispatch level. It may be + // read at interrupt level. + // + WDFREQUEST CurrentWriteRequest; + + // + // Points to the request that is currently being processed to + // affect the wait mask operations. + // + WDFREQUEST CurrentMaskRequest; + + // + // Points to the request that is currently being processed to + // purge the read/write queues and buffers. + // + WDFREQUEST CurrentPurgeRequest; + + // + // Points to the current request that is waiting on a comm event. + // + WDFREQUEST CurrentWaitRequest; + + // + // Points to the request that is being used to send an immediate + // character. + // + WDFREQUEST CurrentImmediateRequest; + + // + // Points to the request that is being used to count the number + // of characters received after an xoff (as currently defined + // by the IOCTL_SERIAL_XOFF_COUNTER ioctl) is sent. + // + WDFREQUEST CurrentXoffRequest; + + // + // The base address for the set of device registers + // of the serial port. + // + PUCHAR Controller; + // + // This value holds the span (in units of bytes) of the register + // set controlling this port. This is constant over the life + // of the port. + // + ULONG SpanOfController; + + // + // Address space + // + + ULONG AddressSpace; + + PREAD_PORT_UCHAR SerialReadUChar; + PWRITE_PORT_UCHAR SerialWriteUChar; + + // + // Hold the clock rate input to the serial part. + // + ULONG ClockRate; + + // + // The number of characters to push out if a fifo is present. + // + ULONG TxFifoAmount; + + // + // Set to indicate that it is ok to share interrupts within the device. + // + ULONG PermitShare; + + + // + // Points to the interrupt object for used by this device. + // + WDFINTERRUPT WdfInterrupt; + + // + // Translated vector + // + ULONG Vector; + // + // Translated Irql + // + KIRQL Irql; + + KINTERRUPT_MODE InterruptMode; + + KAFFINITY Affinity; + + // + // This value is set by the read code to hold the time value + // used for read interval timing. We keep it in the extension + // so that the interval timer dpc routine determine if the + // interval time has passed for the IO. + // + LARGE_INTEGER IntervalTime; + + // + // These two values hold the "constant" time that we should use + // to delay for the read interval time. + // + LARGE_INTEGER ShortIntervalAmount; + LARGE_INTEGER LongIntervalAmount; + + // + // This holds the value that we use to determine if we should use + // the long interval delay or the short interval delay. + // + LARGE_INTEGER CutOverAmount; + + // + // This holds the system time when we last time we had + // checked that we had actually read characters. Used + // for interval timing. + // + LARGE_INTEGER LastReadTime; + + + // + // This points the the delta time that we should use to + // delay for interval timing. + // + PLARGE_INTEGER IntervalTimeToUse; + + + // + // Set at intialization to indicate that on the current + // architecture we need to unmap the base register address + // when we unload the driver. + // + BOOLEAN UnMapRegisters; + + // + // Holds the number of bytes remaining in the current write + // request. + // + // This location is only accessed while at interrupt level. + // + ULONG WriteLength; + + // + // Holds a pointer to the current character to be sent in + // the current write. + // + // This location is only accessed while at interrupt level. + // + PUCHAR WriteCurrentChar; + + // + // This is a buffer for the read processing. + // + // The buffer works as a ring. When the character is read from + // the device it will be place at the end of the ring. + // + // Characters are only placed in this buffer at interrupt level + // although character may be read at any level. The pointers + // that manage this buffer may not be updated except at interrupt + // level. + // + PUCHAR InterruptReadBuffer; + + // + // This is a pointer to the first character of the buffer into + // which the interrupt service routine is copying characters. + // + PUCHAR ReadBufferBase; + + // + // This is a count of the number of characters in the interrupt + // buffer. This value is set and read at interrupt level. Note + // that this value is only *incremented* at interrupt level so + // it is safe to read it at any level. When characters are + // copied out of the read buffer, this count is decremented by + // a routine that synchronizes with the ISR. + // + ULONG CharsInInterruptBuffer; + + // + // Points to the first available position for a newly received + // character. This variable is only accessed at interrupt level and + // buffer initialization code. + // + PUCHAR CurrentCharSlot; + + // + // This variable is used to contain the last available position + // in the read buffer. It is updated at open and at interrupt + // level when switching between the users buffer and the interrupt + // buffer. + // + PUCHAR LastCharSlot; + + // + // This marks the first character that is available to satisfy + // a read request. Note that while this always points to valid + // memory, it may not point to a character that can be sent to + // the user. This can occur when the buffer is empty. + // + PUCHAR FirstReadableChar; + + // + // Pointer to the lock variable returned for this extension when + // locking down the driver + // + PVOID LockPtr; + + + // + // This variable holds the size of whatever buffer we are currently + // using. + // + ULONG BufferSize; + + // + // This variable holds .8 of BufferSize. We don't want to recalculate + // this real often - It's needed when so that an application can be + // "notified" that the buffer is getting full. + // + ULONG BufferSizePt8; + + // + // This value holds the number of characters desired for a + // particular read. It is initially set by read length in the + // WDFREQUEST. It is decremented each time more characters are placed + // into the "users" buffer buy the code that reads characters + // out of the typeahead buffer into the users buffer. If the + // typeahead buffer is exhausted by the read, and the reads buffer + // is given to the isr to fill, this value is becomes meaningless. + // + ULONG NumberNeededForRead; + + // + // This mask will hold the bitmask sent down via the set mask + // ioctl. It is used by the interrupt service routine to determine + // if the occurence of "events" (in the serial drivers understanding + // of the concept of an event) should be noted. + // + ULONG IsrWaitMask; + + // + // This mask will always be a subset of the IsrWaitMask. While + // at device level, if an event occurs that is "marked" as interesting + // in the IsrWaitMask, the driver will turn on that bit in this + // history mask. The driver will then look to see if there is a + // request waiting for an event to occur. If there is one, it + // will copy the value of the history mask into the wait request, zero + // the history mask, and complete the wait request. If there is no + // waiting request, the driver will be satisfied with just recording + // that the event occured. If a wait request should be queued, + // the driver will look to see if the history mask is non-zero. If + // it is non-zero, the driver will copy the history mask into the + // request, zero the history mask, and then complete the request. + // + ULONG HistoryMask; + + // + // This is a pointer to the where the history mask should be + // placed when completing a wait. It is only accessed at + // device level. + // + // We have a pointer here to assist us to synchronize completing a wait. + // If this is non-zero, then we have wait outstanding, and the isr still + // knows about it. We make this pointer null so that the isr won't + // attempt to complete the wait. + // + // We still keep a pointer around to the wait request, since the actual + // pointer to the wait request will be used for the "common" request completion + // path. + // + ULONG *IrpMaskLocation; + + // + // This mask holds all of the reason that transmission + // is not proceeding. Normal transmission can not occur + // if this is non-zero. + // + // This is only written from interrupt level. + // This could be (but is not) read at any level. + // + ULONG TXHolding; + + // + // This mask holds all of the reason that reception + // is not proceeding. Normal reception can not occur + // if this is non-zero. + // + // This is only written from interrupt level. + // This could be (but is not) read at any level. + // + ULONG RXHolding; + + // + // This holds the reasons that the driver thinks it is in + // an error state. + // + // This is only written from interrupt level. + // This could be (but is not) read at any level. + // + ULONG ErrorWord; + + // + // This keeps a total of the number of characters that + // are in all of the "write" irps that the driver knows + // about. It is only accessed with the cancel spinlock + // held. + // + ULONG TotalCharsQueued; + + // + // This holds a count of the number of characters read + // the last time the interval timer dpc fired. It + // is a long (rather than a ulong) since the other read + // completion routines use negative values to indicate + // to the interval timer that it should complete the read + // if the interval timer DPC was lurking in some DPC queue when + // some other way to complete occurs. + // + LONG CountOnLastRead; + + // + // This is a count of the number of characters read by the + // isr routine. It is *ONLY* written at isr level. We can + // read it at dispatch level. + // + ULONG ReadByIsr; + + // + // This holds the current baud rate for the device. + // + ULONG CurrentBaud; + + // + // This is the number of characters read since the XoffCounter + // was started. This variable is only accessed at device level. + // If it is greater than zero, it implies that there is an + // XoffCounter ioctl in the queue. + // + LONG CountSinceXoff; + + // + // This ulong is incremented each time something trys to start + // the execution path that tries to lower the RTS line when + // doing transmit toggling. If it "bumps" into another path + // (indicated by a false return value from queueing a dpc + // and a TRUE return value tring to start a timer) it will + // decrement the count. These increments and decrements + // are all done at device level. Note that in the case + // of a bump while trying to start the timer, we have to + // go up to device level to do the decrement. + // + ULONG CountOfTryingToLowerRTS; + + // + // This ULONG is used to keep track of the "named" (in ntddser.h) + // baud rates that this particular device supports. + // + ULONG SupportedBauds; + + // + // Holds the timeout controls for the device. This value + // is set by the Ioctl processing. + // + // It should only be accessed under protection of the control + // lock since more than one request can be in the control dispatch + // routine at one time. + // + SERIAL_TIMEOUTS Timeouts; + + // + // This holds the various characters that are used + // for replacement on errors and also for flow control. + // + // They are only set at interrupt level. + // + SERIAL_CHARS SpecialChars; + + // + // This structure holds the handshake and control flow + // settings for the serial driver. + // + // It is only set at interrupt level. It can be + // be read at any level with the control lock held. + // + SERIAL_HANDFLOW HandFlow; + + + // + // Holds performance statistics that applications can query. + // Reset on each open. Only set at device level. + // + SERIALPERF_STATS PerfStats; + + // + // This holds what we beleive to be the current value of + // the line control register. + // + // It should only be accessed under protection of the control + // lock since more than one request can be in the control dispatch + // routine at one time. + // + UCHAR LineControl; + + + // + // This is only accessed at interrupt level. It keeps track + // of whether the holding register is empty. + // + BOOLEAN HoldingEmpty; + + // + // This variable is only accessed at interrupt level. It + // indicates that we want to transmit a character immediately. + // That is - in front of any characters that could be transmitting + // from a normal write. + // + BOOLEAN TransmitImmediate; + + // + // This variable is only accessed at interrupt level. Whenever + // a wait is initiated this variable is set to false. + // Whenever any kind of character is written it is set to true. + // Whenever the write queue is found to be empty the code that + // is processing that completing request will synchonize with the interrupt. + // If this synchronization code finds that the variable is true and that + // there is a wait on the transmit queue being empty then it is + // certain that the queue was emptied and that it has happened since + // the wait was initiated. + // + BOOLEAN EmptiedTransmit; + + // + // We keep the following values around so that we can connect + // to the interrupt and report resources after the configuration + // record is gone. + // + + // + // We hold the character that should be transmitted immediately. + // + // Note that we can't use this to determine whether there is + // a character to send because the character to send could be + // zero. + // + UCHAR ImmediateChar; + + // + // This holds the mask that will be used to mask off unwanted + // data bits of the received data (valid data bits can be 5,6,7,8) + // The mask will normally be 0xff. This is set while the control + // lock is held since it wouldn't have adverse effects on the + // isr if it is changed in the middle of reading characters. + // (What it would do to the app is another question - but then + // the app asked the driver to do it.) + // + UCHAR ValidDataMask; + + // + // The application can turn on a mode,via the + // IOCTL_SERIAL_LSRMST_INSERT ioctl, that will cause the + // serial driver to insert the line status or the modem + // status into the RX stream. The parameter with the ioctl + // is a pointer to a UCHAR. If the value of the UCHAR is + // zero, then no insertion will ever take place. If the + // value of the UCHAR is non-zero (and not equal to the + // xon/xoff characters), then the serial driver will insert. + // + UCHAR EscapeChar; + + // + // These two booleans are used to indicate to the isr transmit + // code that it should send the xon or xoff character. They are + // only accessed at open and at interrupt level. + // + BOOLEAN SendXonChar; + BOOLEAN SendXoffChar; + + // + // This boolean will be true if a 16550 is present *and* enabled. + // + BOOLEAN FifoPresent; + + // + // This is the water mark that the rxfifo should be + // set to when the fifo is turned on. This is not the actual + // value, but the encoded value that goes into the register. + // + UCHAR RxFifoTrigger; + + // + // This points to a DPC used to complete write requests. + // + WDFDPC CompleteWriteDpc; + + // + // This points to a DPC used to complete read requests. + // + WDFDPC CompleteReadDpc; + + + // + // This dpc is fired off if a comm error occurs. It will + // execute a dpc routine that will cancel all pending reads + // and writes. + // + WDFDPC CommErrorDpc; + + // + // This dpc is fired off if an event occurs and there was + // a request waiting on that event. A dpc routine will execute + // that completes the request. + // + WDFDPC CommWaitDpc; + + // + // This dpc is fired off when the transmit immediate char + // character is given to the hardware. It will simply complete + // the request. + // + WDFDPC CompleteImmediateDpc; + + // + // This dpc is fired off if the xoff counter actually runs down + // to zero. + // + WDFDPC XoffCountCompleteDpc; + + // + // This dpc is fired off only from device level to start off + // a timer that will queue a dpc to check if the RTS line + // should be lowered when we are doing transmit toggling. + // + WDFDPC StartTimerLowerRTSDpc; + + // + // This timer used to handle total read request timing. + // + WDFTIMER ReadRequestTotalTimer; + + // + // This timer used to handle interval read request timing. + // + WDFTIMER ReadRequestIntervalTimer; + + // + // This timer used to handle total write request timing. + // + WDFTIMER WriteRequestTotalTimer; + + // + // This is timer structure used to handle total time request timing. + // + WDFTIMER ImmediateTotalTimer; + + // + // This timer is used to timeout the xoff counter io. + // + WDFTIMER XoffCountTimer; + + // + // This timer is used to invoke a dpc one character time + // after the timer is set. That dpc will be used to check + // whether we should lower the RTS line if we are doing + // transmit toggling. + // + WDFTIMER LowerRTSTimer; + + // + // WMI Information + // + + // + // WMI Comm Data + // + + SERIAL_WMI_COMM_DATA WmiCommData; + + // + // WMI HW Data + // + + SERIAL_WMI_HW_DATA WmiHwData; + + // + // WMI Performance Data + // + + SERIAL_WMI_PERF_DATA WmiPerfData; + +} SERIAL_DEVICE_EXTENSION,*PSERIAL_DEVICE_EXTENSION; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SERIAL_DEVICE_EXTENSION, + SerialGetDeviceExtension) + +// +// This is the scratch area for every request. +// We will copy some of the frequently used information of the request +// into our context area so that way we don't have to call WdfRequestGetParams +// function everytime. +// +typedef struct _REQUEST_CONTEXT { + ULONG_PTR Information; + NTSTATUS Status; + ULONG Length; + PVOID RefCount; + PVOID SystemBuffer; + UCHAR MajorFunction; + PFN_WDF_REQUEST_CANCEL CancelRoutine; + BOOLEAN Cancelled; + PVOID Type3InputBuffer; + PSERIAL_DEVICE_EXTENSION Extension; + ULONG IoctlCode; + BOOLEAN MarkCancelableOnResume; +} REQUEST_CONTEXT, *PREQUEST_CONTEXT; + + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(REQUEST_CONTEXT, + SerialGetRequestContext) + + +// +// This is the Interrupt context for the Serial device. This structure is used +// for keeping track of whether the Interrupt is connected or not. +// +typedef struct _SERIAL_INTERRUPT_CONTEXT { + + // + // This boolean value indicates whether Interrupt is connected. + // + BOOLEAN IsInterruptConnected; + + // + // This lock is used to synchronize the file close logic and + // the Surprise Removal logic. When a surprise remove happens, + // the device interrupts are disabled. When this occurs, the + // file close logic should not attempt to use the interrupt + // object. + // + WDFWAITLOCK InterruptStateLock; + +} SERIAL_INTERRUPT_CONTEXT, *PSERIAL_INTERRUPT_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(SERIAL_INTERRUPT_CONTEXT, + SerialGetInterruptContext) + + +#define SERIAL_FLAGS_CLEAR 0x0L +#define SERIAL_FLAGS_STARTED 0x1L +#define SERIAL_FLAGS_STOPPED 0x2L +#define SERIAL_FLAGS_BROKENHW 0x4L +#define SERIAL_FLAGS_LEGACY_ENUMED 0x8L + + +__inline +UCHAR +SerialReadPortUChar ( + IN UCHAR * x + ) +{ + return READ_PORT_UCHAR (x); +} +__inline +VOID +SerialWritePortUChar ( + IN UCHAR * x, + IN UCHAR y + ) +{ + WRITE_PORT_UCHAR (x,y); +} + +__inline +UCHAR +SerialReadRegisterUChar ( + IN UCHAR * x + ) +{ + return READ_REGISTER_UCHAR (x); +} + +__inline +VOID +SerialWriteRegisterUChar ( + IN UCHAR * x, + IN UCHAR y + ) +{ + WRITE_REGISTER_UCHAR (x,y); +} + + + +// +// Sets the divisor latch register. The divisor latch register +// is used to control the baud rate of the 8250. +// +// As with all of these routines it is assumed that it is called +// at a safe point to access the hardware registers. In addition +// it also assumes that the data is correct. +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// DesiredDivisor - The value to which the divisor latch register should +// be set. +// +#define WRITE_DIVISOR_LATCH(Extension, BaseAddress,DesiredDivisor) \ +do \ +{ \ + PUCHAR Address = BaseAddress; \ + SHORT Divisor = DesiredDivisor; \ + UCHAR LineControl; \ + LineControl = Extension->SerialReadUChar(Address+LINE_CONTROL_REGISTER); \ + Extension->SerialWriteUChar( \ + Address+LINE_CONTROL_REGISTER, \ + (UCHAR)(LineControl | SERIAL_LCR_DLAB) \ + ); \ + Extension->SerialWriteUChar( \ + Address+DIVISOR_LATCH_LSB, \ + (UCHAR)(Divisor & 0xff) \ + ); \ + Extension->SerialWriteUChar( \ + Address+DIVISOR_LATCH_MSB, \ + (UCHAR)((Divisor & 0xff00) >> 8) \ + ); \ + Extension->SerialWriteUChar( \ + Address+LINE_CONTROL_REGISTER, \ + LineControl \ + ); \ +} WHILE (0) + +// +// Reads the divisor latch register. The divisor latch register +// is used to control the baud rate of the 8250. +// +// As with all of these routines it is assumed that it is called +// at a safe point to access the hardware registers. In addition +// it also assumes that the data is correct. +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// DesiredDivisor - A pointer to the 2 byte word which will contain +// the value of the divisor. +// +#define READ_DIVISOR_LATCH(Extension, BaseAddress,PDesiredDivisor) \ +do \ +{ \ + PUCHAR Address = BaseAddress; \ + PSHORT PDivisor = PDesiredDivisor; \ + UCHAR LineControl; \ + UCHAR Lsb; \ + UCHAR Msb; \ + LineControl = Extension->SerialReadUChar(Address+LINE_CONTROL_REGISTER); \ + Extension->SerialWriteUChar( \ + Address+LINE_CONTROL_REGISTER, \ + (UCHAR)(LineControl | SERIAL_LCR_DLAB) \ + ); \ + Lsb = Extension->SerialReadUChar(Address+DIVISOR_LATCH_LSB); \ + Msb = Extension->SerialReadUChar(Address+DIVISOR_LATCH_MSB); \ + *PDivisor = Lsb; \ + *PDivisor = *PDivisor | (((USHORT)Msb) << 8); \ + Extension->SerialWriteUChar( \ + Address+LINE_CONTROL_REGISTER, \ + LineControl \ + ); \ +} WHILE (0) + +// +// This macro reads the interrupt enable register. +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +#define READ_INTERRUPT_ENABLE(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+INTERRUPT_ENABLE_REGISTER)) + +// +// This macro writes the interrupt enable register. +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// Values - The values to write to the interrupt enable register. +// +#define WRITE_INTERRUPT_ENABLE(Extension, BaseAddress,Values) \ +do \ +{ \ + Extension->SerialWriteUChar( \ + BaseAddress+INTERRUPT_ENABLE_REGISTER, \ + Values \ + ); \ +} WHILE (0) + +// +// This macro disables all interrupts on the hardware. +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define DISABLE_ALL_INTERRUPTS(Extension, BaseAddress) \ +do \ +{ \ + WRITE_INTERRUPT_ENABLE(Extension, BaseAddress,0); \ +} WHILE (0) + +// +// This macro enables all interrupts on the hardware. +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define ENABLE_ALL_INTERRUPTS(Extension, BaseAddress) \ +do \ +{ \ + \ + WRITE_INTERRUPT_ENABLE( \ + (Extension), (BaseAddress), \ + (UCHAR)(SERIAL_IER_RDA | SERIAL_IER_THR | \ + SERIAL_IER_RLS | SERIAL_IER_MS) \ + ); \ + \ +} WHILE (0) + +// +// This macro reads the interrupt identification register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// Note that this routine potententially quites a transmitter +// empty interrupt. This is because one way that the transmitter +// empty interrupt is cleared is to simply read the interrupt id +// register. +// +// +#define READ_INTERRUPT_ID_REG(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+INTERRUPT_IDENT_REGISTER)) + +// +// This macro reads the modem control register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define READ_MODEM_CONTROL(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+MODEM_CONTROL_REGISTER)) + +// +// This macro reads the modem status register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define READ_MODEM_STATUS(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+MODEM_STATUS_REGISTER)) + +// +// This macro reads a value out of the receive buffer +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define READ_RECEIVE_BUFFER(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+RECEIVE_BUFFER_REGISTER)) + +// +// This macro reads the line status register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define READ_LINE_STATUS(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+LINE_STATUS_REGISTER)) + +// +// This macro writes the line control register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define WRITE_LINE_CONTROL(Extension, BaseAddress,NewLineControl) \ +do \ +{ \ + Extension->SerialWriteUChar( \ + (BaseAddress)+LINE_CONTROL_REGISTER, \ + (NewLineControl) \ + ); \ +} WHILE (0) + +// +// This macro reads the line control register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// +#define READ_LINE_CONTROL(Extension, BaseAddress) \ + (Extension->SerialReadUChar((BaseAddress)+LINE_CONTROL_REGISTER)) + + +// +// This macro writes to the transmit register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// TransmitChar - The character to send down the wire. +// +// +#define WRITE_TRANSMIT_HOLDING(Extension, BaseAddress,TransmitChar) \ +do \ +{ \ + Extension->SerialWriteUChar( \ + (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \ + (TransmitChar) \ + ); \ +} WHILE (0) + +// +// This macro writes to the transmit FIFO register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// TransmitChars - Pointer to the characters to send down the wire. +// +// TxN - number of charactes to send. +// +// +#define WRITE_TRANSMIT_FIFO_HOLDING(Extension, BaseAddress,TransmitChars,TxN) \ +do \ +{ \ + WRITE_PORT_BUFFER_UCHAR( \ + (BaseAddress)+TRANSMIT_HOLDING_REGISTER, \ + (TransmitChars), \ + (TxN) \ + ); \ +} WHILE (0) + +// +// This macro writes to the control register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// ControlValue - The value to set the fifo control register too. +// +// +#define WRITE_FIFO_CONTROL(Extension, BaseAddress,ControlValue) \ +do \ +{ \ + Extension->SerialWriteUChar( \ + (BaseAddress)+FIFO_CONTROL_REGISTER, \ + (ControlValue) \ + ); \ +} WHILE (0) + +// +// This macro writes to the modem control register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. +// +// ModemControl - The control bits to send to the modem control. +// +// +#define WRITE_MODEM_CONTROL(Extension, BaseAddress,ModemControl) \ +do \ +{ \ + Extension->SerialWriteUChar( \ + (BaseAddress)+MODEM_CONTROL_REGISTER, \ + (ModemControl) \ + ); \ +} WHILE (0) + +#define WRITE_INTERRUPT_STATUS(Extension, BaseAddress,Status) \ +do \ +{ \ + Extension->SerialWriteUChar(BaseAddress, Status); \ +} WHILE (0) + + +// +// This macro reads the interrupt status register +// +// Arguments: +// +// BaseAddress - A pointer to the address from which the hardware +// device registers are located. BaseAddress is gotten +// from PSERIAL_MULTIPORT_DISPATCH->InterruptStatus which +// already has the complete address +// +// AddressSpace - Flag indicating where port is located, MMIO or IO +// space +// +// +#define READ_INTERRUPT_STATUS(Extension, BaseAddress) \ + Extension->SerialReadUChar(BaseAddress)) + +// +// We use this to query into the registry as to whether we +// should break at driver entry. +// + +extern SERIAL_FIRMWARE_DATA driverDefaults; + + +// +// This is exported from the kernel. It is used to point +// to the address that the kernel debugger is using. +// + +extern PUCHAR *KdComPortInUse; + + +typedef enum _SERIAL_MEM_COMPARES { + AddressesAreEqual, + AddressesOverlap, + AddressesAreDisjoint + } SERIAL_MEM_COMPARES,*PSERIAL_MEM_COMPARES; + +#define SERIAL_BAUD_INVALID 0xFFFFFFFF + +typedef struct _SUPPORTED_BAUD_RATES { + UINT32 BaudRate; + ULONG Mask; +}SUPPORTED_BAUD_RATES; + diff --git a/tests/projects/windows/driver/kmdf/serial/serial.inx b/tests/projects/windows/driver/kmdf/serial/serial.inx new file mode 100644 index 000000000..3322653b0 Binary files /dev/null and b/tests/projects/windows/driver/kmdf/serial/serial.inx differ diff --git a/tests/projects/windows/driver/kmdf/serial/serial.rc b/tests/projects/windows/driver/kmdf/serial/serial.rc new file mode 100644 index 000000000..9fbb59de3 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/serial.rc @@ -0,0 +1,14 @@ +#include + +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Serial Device Driver" +#define VER_INTERNALNAME_STR "serial.sys" +#define VER_ORIGINALFILENAME_STR "serial.sys" + +#include "common.ver" + +#include "serlog.rc" + diff --git a/tests/projects/windows/driver/kmdf/serial/serialp.h b/tests/projects/windows/driver/kmdf/serial/serialp.h new file mode 100644 index 000000000..d363f3503 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/serialp.h @@ -0,0 +1,596 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name : + + serialp.h + +Abstract: + + Prototypes and macros that are used throughout the driver. + +--*/ + +//----------------------------------------------------------------------------- +// 4127 -- Conditional Expression is Constant warning +//----------------------------------------------------------------------------- +#define WHILE(constant) \ +__pragma(warning(suppress: 4127)) while(constant) + +typedef +VOID +(*PSERIAL_START_ROUTINE) ( + IN PSERIAL_DEVICE_EXTENSION + ); + +typedef +VOID +(*PSERIAL_GET_NEXT_ROUTINE) ( + IN WDFREQUEST *CurrentOpRequest, + IN WDFQUEUE QueueToProcess, + OUT WDFREQUEST *NewRequest, + IN BOOLEAN CompleteCurrent, + PSERIAL_DEVICE_EXTENSION Extension + ); + +DRIVER_INITIALIZE DriverEntry; + +EVT_WDF_DRIVER_DEVICE_ADD SerialEvtDeviceAdd; +EVT_WDF_OBJECT_CONTEXT_CLEANUP SerialEvtDriverContextCleanup; +EVT_WDF_DEVICE_CONTEXT_CLEANUP SerialEvtDeviceContextCleanup; + +EVT_WDF_DEVICE_D0_ENTRY SerialEvtDeviceD0Entry; +EVT_WDF_DEVICE_D0_EXIT SerialEvtDeviceD0Exit; +EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED SerialEvtDeviceD0EntryPostInterruptsEnabled; +EVT_WDF_DEVICE_D0_EXIT_PRE_INTERRUPTS_DISABLED SerialEvtDeviceD0ExitPreInterruptsDisabled; +EVT_WDF_DEVICE_PREPARE_HARDWARE SerialEvtPrepareHardware; +EVT_WDF_DEVICE_RELEASE_HARDWARE SerialEvtReleaseHardware; + +EVT_WDF_DEVICE_FILE_CREATE SerialEvtDeviceFileCreate; +EVT_WDF_FILE_CLOSE SerialEvtFileClose; + +EVT_WDF_IO_QUEUE_IO_READ SerialEvtIoRead; +EVT_WDF_IO_QUEUE_IO_WRITE SerialEvtIoWrite; +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL SerialEvtIoDeviceControl; +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL SerialEvtIoInternalDeviceControl; +EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE SerialEvtCanceledOnQueue; +EVT_WDF_IO_QUEUE_IO_STOP SerialEvtIoStop; +EVT_WDF_IO_QUEUE_IO_RESUME SerialEvtIoResume; + +EVT_WDF_INTERRUPT_ENABLE SerialEvtInterruptEnable; +EVT_WDF_INTERRUPT_DISABLE SerialEvtInterruptDisable; + +EVT_WDF_DPC SerialCompleteRead; +EVT_WDF_DPC SerialCompleteWrite; +EVT_WDF_DPC SerialCommError; +EVT_WDF_DPC SerialCompleteImmediate; +EVT_WDF_DPC SerialCompleteXoff; +EVT_WDF_DPC SerialCompleteWait; +EVT_WDF_DPC SerialStartTimerLowerRTS; + +EVT_WDF_TIMER SerialReadTimeout; +EVT_WDF_TIMER SerialIntervalReadTimeout; +EVT_WDF_TIMER SerialWriteTimeout; +EVT_WDF_TIMER SerialTimeoutImmediate; +EVT_WDF_TIMER SerialTimeoutXoff; +EVT_WDF_TIMER SerialInvokePerhapsLowerRTS; + +VOID +SerialStartRead( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialStartWrite( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialStartMask( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialStartImmediate( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialStartPurge( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialGetNextWrite( + IN WDFREQUEST *CurrentOpRequest, + IN WDFQUEUE QueueToProcess, + IN WDFREQUEST *NewRequest, + IN BOOLEAN CompleteCurrent, + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialWdmDeviceFileCreate; +EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialWdmFileClose; +EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialFlush; + +EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialQueryInformationFile; +EVT_WDFDEVICE_WDM_IRP_PREPROCESS SerialSetInformationFile; + +NTSTATUS +SerialDeviceFileCreateWorker ( + IN WDFDEVICE Device + ); + + +VOID +SerialFileCloseWorker( + IN WDFDEVICE Device + ); + +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialProcessEmptyTransmit; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetDTR; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialClrDTR; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetRTS; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialClrRTS; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetBaud; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetLineControl; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetHandFlow; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialTurnOnBreak; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialTurnOffBreak; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPretendXoff; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPretendXon; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialReset; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPerhapsLowerRTS; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialMarkOpen; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialMarkClose; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetStats; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialClearStats; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetChars; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetMCRContents; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGetMCRContents; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialSetFCRContents; + +BOOLEAN +SerialSetupNewHandFlow( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN PSERIAL_HANDFLOW NewHandFlow + ); + + +VOID +SerialHandleReducedIntBuffer( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialProdXonXoff( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN BOOLEAN SendXon + ); + +EVT_WDF_REQUEST_CANCEL SerialCancelWait; + + +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialPurgeInterruptBuff; + +VOID +SerialPurgeRequests( + IN WDFQUEUE QueueToClean, + IN WDFREQUEST *CurrentOpRequest + ); + +VOID +SerialFlushRequests( + IN WDFQUEUE QueueToClean, + IN WDFREQUEST *CurrentOpRequest + ); + +VOID +SerialGetNextRequest( + IN WDFREQUEST *CurrentOpRequest, + IN WDFQUEUE QueueToProcess, + OUT WDFREQUEST *NextIrp, + IN BOOLEAN CompleteCurrent, + IN PSERIAL_DEVICE_EXTENSION extension + ); + + +VOID +SerialTryToCompleteCurrent( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN PFN_WDF_INTERRUPT_SYNCHRONIZE SynchRoutine OPTIONAL, + IN NTSTATUS StatusToUse, + IN WDFREQUEST *CurrentOpRequest, + IN WDFQUEUE QueueToProcess, + IN WDFTIMER IntervalTimer, + IN WDFTIMER TotalTimer, + IN PSERIAL_START_ROUTINE Starter, + IN PSERIAL_GET_NEXT_ROUTINE GetNextIrp, + IN LONG RefType + ); + +VOID +SerialStartOrQueue( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN WDFREQUEST Request, + IN WDFQUEUE QueueToExamine, + IN WDFREQUEST *CurrentOpRequest, + IN PSERIAL_START_ROUTINE Starter + ); + +NTSTATUS +SerialCompleteIfError( + PSERIAL_DEVICE_EXTENSION extension, + WDFREQUEST Request + ); + +ULONG +SerialHandleModemUpdate( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN BOOLEAN DoingTX + ); + + +EVT_WDF_INTERRUPT_ISR SerialISR; + +NTSTATUS +SerialGetDivisorFromBaud( + IN ULONG ClockRate, + IN LONG DesiredBaud, + OUT PSHORT AppropriateDivisor + ); + +VOID +SerialCleanupDevice( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +UCHAR +SerialProcessLSR( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +LARGE_INTEGER +SerialGetCharTime( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + + +VOID +SerialPutChar( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN UCHAR CharToPut + ); + +NTSTATUS +SerialGetConfigDefaults( + IN PSERIAL_FIRMWARE_DATA DriverDefaultsPtr, + IN WDFDRIVER Driver + ); + +VOID +SerialGetProperties( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN PSERIAL_COMMPROP Properties + ); + +VOID +SerialLogError( + _In_ PDRIVER_OBJECT DriverObject, + _In_opt_ PDEVICE_OBJECT DeviceObject, + _In_ PHYSICAL_ADDRESS P1, + _In_ PHYSICAL_ADDRESS P2, + _In_ ULONG SequenceNumber, + _In_ UCHAR MajorFunctionCode, + _In_ UCHAR RetryCount, + _In_ ULONG UniqueErrorValue, + _In_ NTSTATUS FinalStatus, + _In_ NTSTATUS SpecificIOStatus, + _In_ ULONG LengthOfInsert1, + _In_reads_bytes_opt_(LengthOfInsert1) PWCHAR Insert1, + _In_ ULONG LengthOfInsert2, + _In_reads_bytes_opt_(LengthOfInsert2) PWCHAR Insert2 + ); + +NTSTATUS +SerialMapHWResources( + IN WDFDEVICE Device, + IN WDFCMRESLIST PResList, + IN WDFCMRESLIST PTrResList, + OUT PCONFIG_DATA PConfig + ); + +VOID +SerialUnmapHWResources( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +BOOLEAN +SerialGetRegistryKeyValue ( + IN WDFDEVICE WdfDevice, + _In_ PCWSTR Name, + OUT PULONG Value + ); + + +BOOLEAN +SerialPutRegistryKeyValue ( + IN WDFDEVICE WdfDevice, + _In_ PCWSTR Name, + IN ULONG Value + ); + +NTSTATUS +SerialInitController( + IN PSERIAL_DEVICE_EXTENSION pDevExt, + IN PCONFIG_DATA PConfigData + ); + +BOOLEAN +SerialCIsrSw( + IN WDFINTERRUPT Interrupt, + IN ULONG MessageID + ); + +NTSTATUS +SerialDoExternalNaming( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +PVOID +SerialGetMappedAddress( + PHYSICAL_ADDRESS IoAddress, + ULONG NumberOfBytes, + ULONG AddressSpace, + PBOOLEAN MappedAddress + ); + +BOOLEAN +SerialDoesPortExist( + IN PSERIAL_DEVICE_EXTENSION Extension, + PUNICODE_STRING InsertString, + IN ULONG ForceFifo, + IN ULONG LogFifo + ); + +SERIAL_MEM_COMPARES +SerialMemCompare( + IN PHYSICAL_ADDRESS A, + IN ULONG SpanOfA, + IN PHYSICAL_ADDRESS B, + IN ULONG SpanOfB + ); + +VOID +SerialUndoExternalNaming( + IN PSERIAL_DEVICE_EXTENSION Extension + ); + +VOID +SerialReleaseResources( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +VOID +SerialPurgePendingRequests( + PSERIAL_DEVICE_EXTENSION pDevExt + ); + +VOID +SerialDisableUART( + IN PVOID Context + ); + +VOID +SerialDrainUART( + IN PSERIAL_DEVICE_EXTENSION PDevExt, + IN PLARGE_INTEGER PDrainTime + ); + +VOID +SerialSaveDeviceState( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +NTSTATUS +SerialSetPowerPolicy( + IN PSERIAL_DEVICE_EXTENSION DeviceExtension + ); + +UINT32 +SerialReportMaxBaudRate( + ULONG Bauds + ); + +BOOLEAN +SerialInsertQueueDpc( + IN WDFDPC Dpc + ); + +BOOLEAN +SerialSetTimer( + IN WDFTIMER Timer, + IN LARGE_INTEGER DueTime + ); + +BOOLEAN +SerialCancelTimer( + IN WDFTIMER Timer, + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +VOID +SerialUnlockPages( + IN WDFDPC PDpc, + IN PVOID PDeferredContext, + IN PVOID PSysContext1, + IN PVOID PSysContext2) + ; + +VOID +SerialMarkHardwareBroken( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +VOID +SerialDisableInterfacesResources( + IN PSERIAL_DEVICE_EXTENSION PDevExt, + IN BOOLEAN DisableUART + ); + +VOID +SerialSetDeviceFlags( + IN PSERIAL_DEVICE_EXTENSION PDevExt, + OUT PULONG PFlags, + IN ULONG Value, + IN BOOLEAN Set + ); + + +VOID +SetDeviceIsOpened( + IN PSERIAL_DEVICE_EXTENSION PDevExt, + IN BOOLEAN DeviceIsOpened, + IN BOOLEAN Reopen + ); + +BOOLEAN +IsQueueEmpty( + IN WDFQUEUE Queue + ); + +NTSTATUS +SerialCreateTimersAndDpcs( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +VOID +SerialDrainTimersAndDpcs( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ); + +VOID +SerialSetCancelRoutine( + IN WDFREQUEST Request, + IN PFN_WDF_REQUEST_CANCEL CancelRoutine + ); + +NTSTATUS +SerialClearCancelRoutine( + IN WDFREQUEST Request, + IN BOOLEAN ClearReference + ); + +NTSTATUS +SerialWmiRegistration( + WDFDEVICE Device + ); + +NTSTATUS +SerialReadSymName( + IN WDFDEVICE Device, + _Out_writes_bytes_(*SizeOfRegName) PWSTR RegName, + _Inout_ PUSHORT SizeOfRegName + ); + +VOID +SerialCompleteRequest( + IN WDFREQUEST Request, + IN NTSTATUS Status, + IN ULONG_PTR Info + ); + +BOOLEAN +SerialGetFdoRegistryKeyValue( + IN PWDFDEVICE_INIT DeviceInit, + _In_ PCWSTR Name, + OUT PULONG Value + ); + +VOID +SerialSetInterruptPolicy( + _In_ WDFINTERRUPT WdfInterrupt + ); + +typedef struct _SERIAL_UPDATE_CHAR { + PSERIAL_DEVICE_EXTENSION Extension; + ULONG CharsCopied; + BOOLEAN Completed; + } SERIAL_UPDATE_CHAR,*PSERIAL_UPDATE_CHAR; + +// +// The following simple structure is used to send a pointer +// the device extension and an ioctl specific pointer +// to data. +// +typedef struct _SERIAL_IOCTL_SYNC { + PSERIAL_DEVICE_EXTENSION Extension; + PVOID Data; + } SERIAL_IOCTL_SYNC,*PSERIAL_IOCTL_SYNC; + + +// +// The following three macros are used to initialize, set +// and clear references in IRPs that are used by +// this driver. The reference is stored in the fourth +// argument of the request, which is never used by any operation +// accepted by this driver. +// + +#define SERIAL_REF_ISR (0x00000001) +#define SERIAL_REF_CANCEL (0x00000002) +#define SERIAL_REF_TOTAL_TIMER (0x00000004) +#define SERIAL_REF_INT_TIMER (0x00000008) +#define SERIAL_REF_XOFF_REF (0x00000010) + + +#define SERIAL_INIT_REFERENCE(ReqContext) { \ + (ReqContext)->RefCount = NULL; \ + } + +#define SERIAL_SET_REFERENCE(ReqContext, RefType) \ + do { \ + LONG _refType = (RefType); \ + PULONG_PTR _arg4 = (PVOID)&(ReqContext)->RefCount; \ + ASSERT(!(*_arg4 & _refType)); \ + *_arg4 |= _refType; \ + } WHILE (0) + +#define SERIAL_CLEAR_REFERENCE(ReqContext, RefType) \ + do { \ + LONG _refType = (RefType); \ + PULONG_PTR _arg4 = (PVOID)&(ReqContext)->RefCount; \ + ASSERT(*_arg4 & _refType); \ + *_arg4 &= ~_refType; \ + } WHILE (0) + +#define SERIAL_REFERENCE_COUNT(ReqContext) \ + ((ULONG_PTR)(((ReqContext)->RefCount))) + +#define SERIAL_TEST_REFERENCE(ReqContext, RefType) ((ULONG_PTR)ReqContext ->RefCount & RefType) + +// +// Prototypes and defines to handle processor groups. +// +typedef +USHORT +(*PFN_KE_GET_ACTIVE_GROUP_COUNT)( + VOID + ); + +typedef +KAFFINITY +(*PFN_KE_QUERY_GROUP_AFFINITY) ( + _In_ USHORT GroupNumber + ); + +// +// Force the serial interrupt to run on the last interrupt group. +// +//#define SERIAL_SELECT_INTERRUPT_GROUP 1 +#define SERIAL_LAST_INTERRUPT_GROUP 0xFFFF +#define SERIAL_PREFERRED_INTERRUPT_GROUP SERIAL_LAST_INTERRUPT_GROUP + + + diff --git a/tests/projects/windows/driver/kmdf/serial/serlog.mc b/tests/projects/windows/driver/kmdf/serial/serlog.mc new file mode 100644 index 000000000..ee6935b67 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/serlog.mc @@ -0,0 +1,290 @@ +;/*++ BUILD Version: 0001 // Increment this if a change has global effects +; +;Copyright (c) 1992, 1993 Microsoft Corporation +; +;Module Name: +; +; ntiologc.h +; +;Abstract: +; +; Constant definitions for the I/O error code log values. +; +;--*/ +; +;#ifndef _SERLOG_ +;#define _SERLOG_ +; +;// +;// Status values are 32 bit values layed out as follows: +;// +;// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +;// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +;// +---+-+-------------------------+-------------------------------+ +;// |Sev|C| Facility | Code | +;// +---+-+-------------------------+-------------------------------+ +;// +;// where +;// +;// Sev - is the severity code +;// +;// 00 - Success +;// 01 - Informational +;// 10 - Warning +;// 11 - Error +;// +;// C - is the Customer code flag +;// +;// Facility - is the facility code +;// +;// Code - is the facility's status code +;// +; +MessageIdTypedef=NTSTATUS + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + +FacilityNames=(System=0x0 + RpcRuntime=0x2:FACILITY_RPC_RUNTIME + RpcStubs=0x3:FACILITY_RPC_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + Serial=0x6:FACILITY_SERIAL_ERROR_CODE + ) + + +MessageId=0x0001 Facility=Serial Severity=Informational SymbolicName=SERIAL_KERNEL_DEBUGGER_ACTIVE +Language=English +The kernel debugger is already using %2. +. + +MessageId=0x0002 Facility=Serial Severity=Informational SymbolicName=SERIAL_FIFO_PRESENT +Language=English +While validating that %2 was really a serial port, a fifo was detected. The fifo will be used. +. + +MessageId=0x0003 Facility=Serial Severity=Informational SymbolicName=SERIAL_USER_OVERRIDE +Language=English +User configuration data for parameter %2 overriding firmware configuration data. +. + +MessageId=0x0004 Facility=Serial Severity=Warning SymbolicName=SERIAL_NO_SYMLINK_CREATED +Language=English +Unable to create the symbolic link for %2. +. + +MessageId=0x0005 Facility=Serial Severity=Warning SymbolicName=SERIAL_NO_DEVICE_MAP_CREATED +Language=English +Unable to create the device map entry for %2. +. + +MessageId=0x0006 Facility=Serial Severity=Warning SymbolicName=SERIAL_NO_DEVICE_MAP_DELETED +Language=English +Unable to delete the device map entry for %2. +. + +MessageId=0x0007 Facility=Serial Severity=Error SymbolicName=SERIAL_UNREPORTED_IRQL_CONFLICT +Language=English +Another driver on the system, which did not report its resources, has already claimed the interrupt used by %2. +. + +MessageId=0x0008 Facility=Serial Severity=Error SymbolicName=SERIAL_INSUFFICIENT_RESOURCES +Language=English +Not enough resources were available for the driver. +. + +MessageId=0x0009 Facility=Serial Severity=Error SymbolicName=SERIAL_UNSUPPORTED_CLOCK_RATE +Language=English +The baud clock rate configuration is not supported on device %2. +. + +MessageId=0x000A Facility=Serial Severity=Error SymbolicName=SERIAL_REGISTERS_NOT_MAPPED +Language=English +The hardware locations for %2 could not be translated to something the memory management system could understand. +. + +MessageId=0x000B Facility=Serial Severity=Error SymbolicName=SERIAL_RESOURCE_CONFLICT +Language=English +The hardware resources for %2 are already in use by another device. +. + +MessageId=0x000C Facility=Serial Severity=Error SymbolicName=SERIAL_NO_BUFFER_ALLOCATED +Language=English +No memory could be allocated in which to place new data for %2. +. + +MessageId=0x000D Facility=Serial Severity=Error SymbolicName=SERIAL_IER_INVALID +Language=English +While validating that %2 was really a serial port, the interrupt enable register contained enabled bits in a must be zero bitfield. +The device is assumed not to be a serial port and will be deleted. +. + +MessageId=0x000E Facility=Serial Severity=Error SymbolicName=SERIAL_MCR_INVALID +Language=English +While validating that %2 was really a serial port, the modem control register contained enabled bits in a must be zero bitfield. +The device is assumed not to be a serial port and will be deleted. +. + +MessageId=0x000F Facility=Serial Severity=Error SymbolicName=SERIAL_IIR_INVALID +Language=English +While validating that %2 was really a serial port, the interrupt id register contained enabled bits in a must be zero bitfield. +The device is assumed not to be a serial port and will be deleted. +. + +MessageId=0x0010 Facility=Serial Severity=Error SymbolicName=SERIAL_DL_INVALID +Language=English +While validating that %2 was really a serial port, the baud rate register could not be set consistantly. +The device is assumed not to be a serial port and will be deleted. +. + +MessageId=0x0011 Facility=Serial Severity=Error SymbolicName=SERIAL_NOT_ENOUGH_CONFIG_INFO +Language=English +Some firmware configuration information was incomplete. +. + +MessageId=0x0012 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_PARAMETERS_INFO +Language=English +No Parameters subkey was found for user defined data. This is odd, and it also means no user configuration can be found. +. + +MessageId=0x0013 Facility=Serial Severity=Error SymbolicName=SERIAL_UNABLE_TO_ACCESS_CONFIG +Language=English +Specific user configuration data is unretrievable. +. + +MessageId=0x0014 Facility=Serial Severity=Error SymbolicName=SERIAL_INVALID_PORT_INDEX +Language=English +On parameter %2 which indicates a multiport card, must have a port index specified greater than 0. +. + +MessageId=0x0015 Facility=Serial Severity=Error SymbolicName=SERIAL_PORT_INDEX_TOO_HIGH +Language=English +On parameter %2 which indicates a multiport card, the port index for the multiport card is too large. +. + +MessageId=0x0016 Facility=Serial Severity=Error SymbolicName=SERIAL_UNKNOWN_BUS +Language=English +The bus type for %2 is not recognizable. +. + +MessageId=0x0017 Facility=Serial Severity=Error SymbolicName=SERIAL_BUS_NOT_PRESENT +Language=English +The bus type for %2 is not available on this computer. +. + +MessageId=0x0018 Facility=Serial Severity=Error SymbolicName=SERIAL_BUS_INTERRUPT_CONFLICT +Language=English +The bus specified for %2 does not support the specified method of interrupt. +. + +MessageId=0x0019 Facility=Serial Severity=Error SymbolicName=SERIAL_INVALID_USER_CONFIG +Language=English +User configuration for parameter %2 must have %3. +. + +MessageId=0x001A Facility=Serial Severity=Error SymbolicName=SERIAL_DEVICE_TOO_HIGH +Language=English +The user specified port for %2 is way too high in physical memory. +. + +MessageId=0x001B Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_TOO_HIGH +Language=English +The status port for %2 is way too high in physical memory. +. + +MessageId=0x001C Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_CONTROL_CONFLICT +Language=English +The status port for %2 overlaps the control registers for the device. +. + +MessageId=0x001D Facility=Serial Severity=Error SymbolicName=SERIAL_CONTROL_OVERLAP +Language=English +The control registers for %2 overlaps with the %3 control registers. +. + +MessageId=0x001E Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_OVERLAP +Language=English +The status register for %2 overlaps the %3 control registers. +. + +MessageId=0x001F Facility=Serial Severity=Error SymbolicName=SERIAL_STATUS_STATUS_OVERLAP +Language=English +The status register for %2 overlaps with the %3 status register. +. + +MessageId=0x0020 Facility=Serial Severity=Error SymbolicName=SERIAL_CONTROL_STATUS_OVERLAP +Language=English +The control registers for %2 overlaps the %3 status register. +. + +MessageId=0x0021 Facility=Serial Severity=Error SymbolicName=SERIAL_MULTI_INTERRUPT_CONFLICT +Language=English +Two ports, %2 and %3, on a single multiport card can't have two different interrupts. +. + +MessageId=0x0022 Facility=Serial Severity=Informational SymbolicName=SERIAL_DISABLED_PORT +Language=English +Disabling %2 as requested by the configuration data. +. + +MessageId=0x0023 Facility=Serial Severity=Error SymbolicName=SERIAL_GARBLED_PARAMETER +Language=English +Parameter %2 data is unretrievable from the registry. +. + +MessageId=0x0024 Facility=Serial Severity=Error SymbolicName=SERIAL_DLAB_INVALID +Language=English +While validating that %2 was really a serial port, the contents of the divisor latch register was identical to the interrupt enable and the receive registers. +The device is assumed not to be a serial port and will be deleted. +. + +MessageId=0x0025 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_TRANSLATE_PORT +Language=English +Could not translate the user reported I/O port for %2. +. + +MessageId=0x0026 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_GET_INTERRUPT +Language=English +Could not get the user reported interrupt for %2 from the HAL. +. + +MessageId=0x0027 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_TRANSLATE_ISR +Language=English +Could not translate the user reported Interrupt Status Register for %2. +. + +MessageId=0x0028 Facility=Serial Severity=Error SymbolicName=SERIAL_NO_DEVICE_REPORT +Language=English +Could not report the discovered legacy device %2 to the IO subsystem. +. + +MessageId=0x0029 Facility=Serial Severity=Error SymbolicName=SERIAL_REGISTRY_WRITE_FAILED +Language=English +Error writing to the registry. +. + +MessageId=0x002A Facility=Serial Severity=Warning SymbolicName=SERIAL_MOUSE_CONFLICT_IRQ +Language=English +There is a serial mouse using the same interrupt as %2. Therefore, %2 will not be started. +. + +MessageId=0x002B Facility=Serial Severity=Warning SymbolicName=SERIAL_MOUSE_ON_PORT +Language=English +There was a serial mouse found on %2. Therefore, %2 will be assigned to the mouse. +. + +MessageId=0x002C Facility=Serial Severity=Error SymbolicName=SERIAL_NO_DEVICE_REPORT_RES +Language=English +Could not report device %2 to IO subsystem due to a resource conflict. +. + +MessageId=0x002D Facility=Serial Severity=Error SymbolicName=SERIAL_HARDWARE_FAILURE +Language=English +The serial driver detected a hardware failure on device %2 and will disable this device. +. + +;#endif /* _NTIOLOGC_ */ + diff --git a/tests/projects/windows/driver/kmdf/serial/trace.h b/tests/projects/windows/driver/kmdf/serial/trace.h new file mode 100644 index 000000000..5bd9d50ca --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/trace.h @@ -0,0 +1,118 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + TRACE.h + +Abstract: + + Header file for the debug tracing related function defintions and macros. + +Environment: + + Kernel mode + +--*/ + +#include // For TRACE_LEVEL definitions + +#if !defined(EVENT_TRACING) + +// +// TODO: These defines are missing in evntrace.h +// in some DDK build environments (XP). +// +#if !defined(TRACE_LEVEL_NONE) + #define TRACE_LEVEL_NONE 0 + #define TRACE_LEVEL_CRITICAL 1 + #define TRACE_LEVEL_FATAL 1 + #define TRACE_LEVEL_ERROR 2 + #define TRACE_LEVEL_WARNING 3 + #define TRACE_LEVEL_INFORMATION 4 + #define TRACE_LEVEL_VERBOSE 5 + #define TRACE_LEVEL_RESERVED6 6 + #define TRACE_LEVEL_RESERVED7 7 + #define TRACE_LEVEL_RESERVED8 8 + #define TRACE_LEVEL_RESERVED9 9 +#endif + + +// +// Define Debug Flags +// +#define DBG_INIT 0x00000001 +#define DBG_PNP 0x00000002 +#define DBG_POWER 0x00000004 +#define DBG_WMI 0x00000008 +#define DBG_CREATE_CLOSE 0x00000010 +#define DBG_IOCTLS 0x00000020 +#define DBG_WRITE 0x00000040 +#define DBG_READ 0x00000080 +#define DBG_DPC 0x00000100 +#define DBG_INTERRUPT 0x00000200 +#define DBG_LOCKS 0x00000400 +#define DBG_QUEUEING 0x00000800 +#define DBG_HW_ACCESS 0x00001000 + +VOID +TraceEvents ( + IN ULONG DebugPrintLevel, + IN ULONG DebugPrintFlag, + IN PCCHAR DebugMessage, + ... + ); + +#define WPP_INIT_TRACING(DriverObject, RegistryPath) +#define WPP_CLEANUP(DriverObject) + +#else +// +// If software tracing is defined in the sources file.. +// WPP_DEFINE_CONTROL_GUID specifies the GUID used for this driver. +// *** REPLACE THE GUID WITH YOUR OWN UNIQUE ID *** +// WPP_DEFINE_BIT allows setting debug bit masks to selectively print. +// The names defined in the WPP_DEFINE_BIT call define the actual names +// that are used to control the level of tracing for the control guid +// specified. +// +// Name of the logger is Serial and the guid is +// {F3A79AB6-9827-4419-9465-45CF949EF659} +// (0xf3a79ab6, 0x9827, 0x4419, 0x94, 0x65, 0x45, 0xcf, 0x94, 0x9e, 0xf6, 0x59); +// + +#define WPP_CHECK_FOR_NULL_STRING //to prevent exceptions due to NULL strings + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID(SerialTraceGuid,(bc6c9364,fc67,42c5,acf7,abed3b12ecc6), \ + WPP_DEFINE_BIT(DBG_INIT) /* bit 0 = 0x00000001 */ \ + WPP_DEFINE_BIT(DBG_PNP) /* bit 1 = 0x00000002 */ \ + WPP_DEFINE_BIT(DBG_POWER) /* bit 2 = 0x00000004 */ \ + WPP_DEFINE_BIT(DBG_WMI) /* bit 3 = 0x00000008 */ \ + WPP_DEFINE_BIT(DBG_CREATE_CLOSE) /* bit 4 = 0x00000010 */ \ + WPP_DEFINE_BIT(DBG_IOCTLS) /* bit 5 = 0x00000020 */ \ + WPP_DEFINE_BIT(DBG_WRITE) /* bit 6 = 0x00000040 */ \ + WPP_DEFINE_BIT(DBG_READ) /* bit 7 = 0x00000080 */ \ + WPP_DEFINE_BIT(DBG_DPC) /* bit 8 = 0x00000100 */ \ + WPP_DEFINE_BIT(DBG_INTERRUPT) /* bit 9 = 0x00000200 */ \ + WPP_DEFINE_BIT(DBG_LOCKS) /* bit 10 = 0x00000400 */ \ + WPP_DEFINE_BIT(DBG_QUEUEING) /* bit 11 = 0x00000800 */ \ + WPP_DEFINE_BIT(DBG_HW_ACCESS) /* bit 12 = 0x00001000 */ \ + /* You can have up to 32 defines. If you want more than that,\ + you have to provide another trace control GUID */\ + ) + + +#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags) +#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl) + + +#endif + + diff --git a/tests/projects/windows/driver/kmdf/serial/utils.c b/tests/projects/windows/driver/kmdf/serial/utils.c new file mode 100644 index 000000000..a84136efe --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/utils.c @@ -0,0 +1,1946 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + utils.c + +Abstract: + + This module contains code that perform queueing and completion + manipulation on requests. Also module generic functions such + as error logging. + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "utils.tmh" +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGESRP0,SerialMemCompare) +#pragma alloc_text(PAGESRP0,SerialLogError) +#pragma alloc_text(PAGESRP0,SerialMarkHardwareBroken) +#endif // ALLOC_PRAGMA + + +VOID +SerialRundownIrpRefs( + IN WDFREQUEST *CurrentOpRequest, + IN WDFTIMER IntervalTimer, + IN WDFTIMER TotalTimer, + IN PSERIAL_DEVICE_EXTENSION PDevExt, + IN LONG RefType + ); + +static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; + +VOID +SerialPurgeRequests( + IN WDFQUEUE QueueToClean, + IN WDFREQUEST *CurrentOpRequest + ) + +/*++ + +Routine Description: + + This function is used to cancel all queued and the current irps + for reads or for writes. Called at DPC level. + +Arguments: + + QueueToClean - A pointer to the queue which we're going to clean out. + + CurrentOpRequest - Pointer to a pointer to the current request. + +Return Value: + + None. + +--*/ + +{ + NTSTATUS status; + PREQUEST_CONTEXT reqContext; + + WdfIoQueuePurge(QueueToClean, WDF_NO_EVENT_CALLBACK, WDF_NO_CONTEXT); + + // + // The queue is clean. Now go after the current if + // it's there. + // + + if (*CurrentOpRequest) { + + PFN_WDF_REQUEST_CANCEL CancelRoutine; + + reqContext = SerialGetRequestContext(*CurrentOpRequest); + CancelRoutine = reqContext->CancelRoutine; + // + // Clear the common cancel routine but don't clear the reference because the + // request specific cancel routine called below will clear the reference. + // + status = SerialClearCancelRoutine(*CurrentOpRequest, FALSE); + if (NT_SUCCESS(status)) { + // + // Let us just call the CancelRoutine to start the next request. + // + if(CancelRoutine) { + CancelRoutine(*CurrentOpRequest); + } + } + } +} + +VOID +SerialFlushRequests( + IN WDFQUEUE QueueToClean, + IN WDFREQUEST *CurrentOpRequest + ) + +/*++ + +Routine Description: + + This function is used to cancel all queued and the current irps + for reads or for writes. Called at DPC level. + +Arguments: + + QueueToClean - A pointer to the queue which we're going to clean out. + + CurrentOpRequest - Pointer to a pointer to the current request. + +Return Value: + + None. + +--*/ + +{ + SerialPurgeRequests(QueueToClean, CurrentOpRequest); + + // + // Since purge puts the queue state to fail requests, we have to explicitly + // change the queue state to accept requests. + // + WdfIoQueueStart(QueueToClean); + +} + + +VOID +SerialGetNextRequest( + IN WDFREQUEST * CurrentOpRequest, + IN WDFQUEUE QueueToProcess, + OUT WDFREQUEST * NextRequest, + IN BOOLEAN CompleteCurrent, + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + This function is used to make the head of the particular + queue the current request. It also completes the what + was the old current request if desired. + +Arguments: + + CurrentOpRequest - Pointer to a pointer to the currently active + request for the particular work list. Note that + this item is not actually part of the list. + + QueueToProcess - The list to pull the new item off of. + + NextIrp - The next Request to process. Note that CurrentOpRequest + will be set to this value under protection of the + cancel spin lock. However, if *NextIrp is NULL when + this routine returns, it is not necessaryly true the + what is pointed to by CurrentOpRequest will also be NULL. + The reason for this is that if the queue is empty + when we hold the cancel spin lock, a new request may come + in immediately after we release the lock. + + CompleteCurrent - If TRUE then this routine will complete the + request pointed to by the pointer argument + CurrentOpRequest. + +Return Value: + + None. + +--*/ + +{ + WDFREQUEST oldRequest = NULL; + PREQUEST_CONTEXT reqContext; + NTSTATUS status; + + UNREFERENCED_PARAMETER(Extension); + + oldRequest = *CurrentOpRequest; + *CurrentOpRequest = NULL; + + // + // Check to see if there is a new request to start up. + // + + status = WdfIoQueueRetrieveNextRequest( + QueueToProcess, + CurrentOpRequest + ); + + if(!NT_SUCCESS(status)) { + ASSERTMSG("WdfIoQueueRetrieveNextRequest failed", + status == STATUS_NO_MORE_ENTRIES); + } + + *NextRequest = *CurrentOpRequest; + + if (CompleteCurrent) { + + if (oldRequest) { + + reqContext = SerialGetRequestContext(oldRequest); + + SerialCompleteRequest(oldRequest, + reqContext->Status, + reqContext->Information); + } + } +} + +VOID +SerialTryToCompleteCurrent( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN PFN_WDF_INTERRUPT_SYNCHRONIZE SynchRoutine OPTIONAL, + IN NTSTATUS StatusToUse, + IN WDFREQUEST *CurrentOpRequest, + IN WDFQUEUE QueueToProcess OPTIONAL, + IN WDFTIMER IntervalTimer OPTIONAL, + IN WDFTIMER TotalTimer OPTIONAL, + IN PSERIAL_START_ROUTINE Starter OPTIONAL, + IN PSERIAL_GET_NEXT_ROUTINE GetNextRequest OPTIONAL, + IN LONG RefType + ) + +/*++ + +Routine Description: + + This routine attempts to remove all of the reasons there are + references on the current read/write. If everything can be completed + it will complete this read/write and try to start another. + + NOTE: This routine assumes that it is called with the cancel + spinlock held. + +Arguments: + + Extension - Simply a pointer to the device extension. + + SynchRoutine - A routine that will synchronize with the isr + and attempt to remove the knowledge of the + current request from the isr. NOTE: This pointer + can be null. + + IrqlForRelease - This routine is called with the cancel spinlock held. + This is the irql that was current when the cancel + spinlock was acquired. + + StatusToUse - The request's status field will be set to this value, if + this routine can complete the request. + + +Return Value: + + None. + +--*/ + +{ + PREQUEST_CONTEXT reqContext; + + ASSERTMSG("SerialTryToCompleteCurrent: CurrentOpRequest is NULL", *CurrentOpRequest); + + reqContext = SerialGetRequestContext(*CurrentOpRequest); + + if(RefType == SERIAL_REF_ISR || RefType == SERIAL_REF_XOFF_REF) { + // + // We can decrement the reference to "remove" the fact + // that the caller no longer will be accessing this request. + // + + SERIAL_CLEAR_REFERENCE( + reqContext, + RefType + ); + } + + if (SynchRoutine) { + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SynchRoutine, + Extension + ); + + } + + // + // Try to run down all other references to this request. + // + + SerialRundownIrpRefs( + CurrentOpRequest, + IntervalTimer, + TotalTimer, + Extension, + RefType + ); + + if(StatusToUse == STATUS_CANCELLED) { + // + // This function is called from a cancelroutine. So mark + // the request as cancelled. We need to do this because + // we may not complete the request below if somebody + // else has a reference to it. + // This state variable was added to avoid calling + // WdfRequestMarkCancelable second time on a request that + // has cancelled but wasn't completed in the cancel routine. + // + reqContext->Cancelled = TRUE; + } + + // + // See if the ref count is zero after trying to complete everybody else. + // + + if (!SERIAL_REFERENCE_COUNT(reqContext)) { + + WDFREQUEST newRequest; + + + // + // The ref count was zero so we should complete this + // request. + // + // The following call will also cause the current request to be + // completed. + // + + reqContext->Status = StatusToUse; + + if (StatusToUse == STATUS_CANCELLED) { + + reqContext->Information = 0; + + } + + if (GetNextRequest) { + + GetNextRequest( + CurrentOpRequest, + QueueToProcess, + &newRequest, + TRUE, + Extension + ); + + if (newRequest) { + + Starter(Extension); + + } + + } else { + + WDFREQUEST oldRequest = *CurrentOpRequest; + + // + // There was no get next routine. We will simply complete + // the request. We should make sure that we null out the + // pointer to the pointer to this request. + // + + *CurrentOpRequest = NULL; + + SerialCompleteRequest(oldRequest, + reqContext->Status, + reqContext->Information); + } + + } else { + + + } + +} + + +VOID +SerialEvtIoStop( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN ULONG ActionFlags + ) +/*++ + +Routine Description: + + This callback is invoked for every request pending in the driver (not queue) - + in-flight request. The Action parameter tells us why the callback is invoked - + because the device is being stopped, removed or suspended. In this + driver, we have told the framework not to stop or remove when there + are pending requests, so only reason for this callback is when the system is + suspending. + +Arguments: + + Queue - Queue the request currently belongs to + Request - Request that is currently out of queue and being processed by the driver + Action - Reason for this callback + +Return Value: + + None. Acknowledge the request so that framework can contiue suspending the + device. + +--*/ +{ + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Queue); + + reqContext = SerialGetRequestContext(Request); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, + "--> SerialEvtIoStop %x %p\n", ActionFlags, Request); + + // + // System suspends all the timers before asking the driver to goto + // sleep. So let us not worry about cancelling the timers. Also the + // framework will disconnect the interrupt before calling our + // D0Exit handler so we can be sure that nobody will touch the hardware. + // So just acknowledge callback to say that we are okay to stop due to + // system suspend. Please note that since we have taken a power reference + // we will never idle out when there is an open handle. Also we have told + // the framework to not stop for resource rebalancing or remove when there are + // open handles, so let us not worry about that either. + // + if (ActionFlags & WdfRequestStopRequestCancelable) { + PFN_WDF_REQUEST_CANCEL cancelRoutine; + + // + // Request is in a cancelable state. So unmark cancelable before you + // acknowledge. We will mark the request cancelable when we resume. + // + cancelRoutine = reqContext->CancelRoutine; + + SerialClearCancelRoutine(Request, TRUE); + + // + // SerialClearCancelRoutine clears the cancel-routine. So set it back + // in the context. We will need that when we resume. + // + reqContext->CancelRoutine = cancelRoutine; + + reqContext->MarkCancelableOnResume = TRUE; + + ActionFlags &= ~WdfRequestStopRequestCancelable; + } + + ASSERT(ActionFlags == WdfRequestStopActionSuspend); + + WdfRequestStopAcknowledge(Request, FALSE); // Don't requeue the request + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, + "<-- SerialEvtIoStop \n"); +} + +VOID +SerialEvtIoResume( + IN WDFQUEUE Queue, + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + This callback is invoked for every request pending in the driver - in-flight + request - to notify that the hardware is ready for contiuing the processing + of the request. + +Arguments: + + Queue - Queue the request currently belongs to + Request - Request that is currently out of queue and being processed by the driver + +Return Value: + + None. + +--*/ +{ + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Queue); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, + "--> SerialEvtIoResume %p \n", Request); + + reqContext = SerialGetRequestContext(Request); + + // + // If we unmarked cancelable on suspend, let us mark it cancelable again. + // + if (reqContext->MarkCancelableOnResume) { + SerialSetCancelRoutine(Request, reqContext->CancelRoutine); + reqContext->MarkCancelableOnResume = FALSE; + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, + "<-- SerialEvtIoResume \n"); +} + +VOID +SerialRundownIrpRefs( + IN WDFREQUEST *CurrentOpRequest, + IN WDFTIMER IntervalTimer OPTIONAL, + IN WDFTIMER TotalTimer OPTIONAL, + IN PSERIAL_DEVICE_EXTENSION PDevExt, + IN LONG RefType + ) + +/*++ + +Routine Description: + + This routine runs through the various items that *could* + have a reference to the current read/write. It try's to remove + the reason. If it does succeed in removing the reason it + will decrement the reference count on the request. + + NOTE: This routine assumes that it is called with the cancel + spin lock held. + +Arguments: + + CurrentOpRequest - Pointer to a pointer to current request for the + particular operation. + + IntervalTimer - Pointer to the interval timer for the operation. + NOTE: This could be null. + + TotalTimer - Pointer to the total timer for the operation. + NOTE: This could be null. + + PDevExt - Pointer to device extension + +Return Value: + + None. + +--*/ + + +{ + PREQUEST_CONTEXT reqContext; + WDFREQUEST request = *CurrentOpRequest; + + reqContext = SerialGetRequestContext(request); + + if(RefType == SERIAL_REF_CANCEL) { + // + // Caller is a cancel routine. So just clear the reference. + // + SERIAL_CLEAR_REFERENCE( reqContext, SERIAL_REF_CANCEL ); + reqContext->CancelRoutine = NULL; + + } else { + // + // Try to clear the cancelable state. + // + SerialClearCancelRoutine(request, TRUE); + } + if (IntervalTimer) { + + // + // Try to cancel the operations interval timer. If the operation + // returns true then the timer did have a reference to the + // request. Since we've canceled this timer that reference is + // no longer valid and we can decrement the reference count. + // + // If the cancel returns false then this means either of two things: + // + // a) The timer has already fired. + // + // b) There never was an interval timer. + // + // In the case of "b" there is no need to decrement the reference + // count since the "timer" never had a reference to it. + // + // In the case of "a", then the timer itself will be coming + // along and decrement it's reference. Note that the caller + // of this routine might actually be the this timer, so + // decrement the reference. + // + + if (SerialCancelTimer(IntervalTimer, PDevExt)) { + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_INT_TIMER + ); + + } else if(RefType == SERIAL_REF_INT_TIMER) { // caller is the timer + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_INT_TIMER + ); + } + + } + + if (TotalTimer) { + + // + // Try to cancel the operations total timer. If the operation + // returns true then the timer did have a reference to the + // request. Since we've canceled this timer that reference is + // no longer valid and we can decrement the reference count. + // + // If the cancel returns false then this means either of two things: + // + // a) The timer has already fired. + // + // b) There never was an total timer. + // + // In the case of "b" there is no need to decrement the reference + // count since the "timer" never had a reference to it. + // + // In the case of "a", then the timer itself will be coming + // along and decrement it's reference. Note that the caller + // of this routine might actually be the this timer, so + // decrement the reference. + // + + if (SerialCancelTimer(TotalTimer, PDevExt)) { + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_TOTAL_TIMER + ); + + } else if(RefType == SERIAL_REF_TOTAL_TIMER) { // caller is the timer + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_TOTAL_TIMER + ); + } + } +} + + +VOID +SerialStartOrQueue( + IN PSERIAL_DEVICE_EXTENSION Extension, + IN WDFREQUEST Request, + IN WDFQUEUE QueueToExamine, + IN WDFREQUEST *CurrentOpRequest, + IN PSERIAL_START_ROUTINE Starter + ) + +/*++ + +Routine Description: + + This routine is used to either start or queue any requst + that can be queued in the driver. + +Arguments: + + Extension - Points to the serial device extension. + + Request - The request to either queue or start. In either + case the request will be marked pending. + + QueueToExamine - The queue the request will be place on if there + is already an operation in progress. + + CurrentOpRequest - Pointer to a pointer to the request the is current + for the queue. The pointer pointed to will be + set with to Request if what CurrentOpRequest points to + is NULL. + + Starter - The routine to call if the queue is empty. + +Return Value: + + +--*/ + +{ + + NTSTATUS status; + PREQUEST_CONTEXT reqContext; + WDF_REQUEST_PARAMETERS params; + + reqContext = SerialGetRequestContext(Request); + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + + WdfRequestGetParameters( + Request, + ¶ms); + + // + // If this is a write request then take the amount of characters + // to write and add it to the count of characters to write. + // + + if (params.Type == WdfRequestTypeWrite) { + + Extension->TotalCharsQueued += reqContext->Length; + + } else if ((params.Type == WdfRequestTypeDeviceControl) && + ((params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) || + (params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER))) { + + reqContext->IoctlCode = params.Parameters.DeviceIoControl.IoControlCode; // We need this in the destroy callback + + Extension->TotalCharsQueued++; + + } + + if (IsQueueEmpty(QueueToExamine) && !(*CurrentOpRequest)) { + + // + // There were no current operation. Mark this one as + // current and start it up. + // + + *CurrentOpRequest = Request; + + Starter(Extension); + + return; + + } else { + + // + // We don't know how long the request will be in the + // queue. If it gets cancelled while waiting in the queue, we will + // be notified by EvtCanceledOnQueue callback so that we can readjust + // the lenght or free the buffer. + // + reqContext->Extension = Extension; // We need this in the destroy callback + + status = WdfRequestForwardToIoQueue(Request, QueueToExamine); + if(!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestForwardToIoQueue failed%X\n", status); + ASSERTMSG("WdfRequestForwardToIoQueue failed ", FALSE); + SerialCompleteRequest(Request, status, 0); + } + + return; + } +} + +VOID +SerialEvtCanceledOnQueue( + IN WDFQUEUE Queue, + IN WDFREQUEST Request + ) + +/*++ + +Routine Description: + + Called when the request is cancelled while it's waiting + on the queue. This callback is used instead of EvtCleanupCallback + on the request because this one will be called with the + presentation lock held. + + +Arguments: + + Queue - Queue in which the request currently waiting + Request - Request being cancelled + + +Return Value: + + None. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION extension = NULL; + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Queue); + + reqContext = SerialGetRequestContext(Request); + + extension = reqContext->Extension; + + // + // If this is a write request then take the amount of characters + // to write and subtract it from the count of characters to write. + // + + if (reqContext->MajorFunction == IRP_MJ_WRITE) { + + extension->TotalCharsQueued -= reqContext->Length; + + } else if (reqContext->MajorFunction == IRP_MJ_DEVICE_CONTROL) { + + // + // If it's an immediate then we need to decrement the + // count of chars queued. If it's a resize then we + // need to deallocate the pool that we're passing on + // to the "resizing" routine. + // + + if (( reqContext->IoctlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) || + (reqContext->IoctlCode == IOCTL_SERIAL_XOFF_COUNTER)) { + + extension->TotalCharsQueued--; + + } else if (reqContext->IoctlCode == IOCTL_SERIAL_SET_QUEUE_SIZE) { + + // + // We shoved the pointer to the memory into the + // the type 3 buffer pointer which we KNOW we + // never use. + // + + ASSERT(reqContext->Type3InputBuffer); + + ExFreePool(reqContext->Type3InputBuffer); + + reqContext->Type3InputBuffer = NULL; + + } + + } + + SerialCompleteRequest(Request, WdfRequestGetStatus(Request), 0); +} + + +NTSTATUS +SerialCompleteIfError( + PSERIAL_DEVICE_EXTENSION extension, + WDFREQUEST Request + ) + +/*++ + +Routine Description: + + If the current request is not an IOCTL_SERIAL_GET_COMMSTATUS request and + there is an error and the application requested abort on errors, + then cancel the request. + +Arguments: + + extension - Pointer to the device context + + Request - Pointer to the WDFREQUEST to test. + +Return Value: + + STATUS_SUCCESS or STATUS_CANCELLED. + +--*/ + +{ + + WDF_REQUEST_PARAMETERS params; + NTSTATUS status = STATUS_SUCCESS; + + if ((extension->HandFlow.ControlHandShake & + SERIAL_ERROR_ABORT) && extension->ErrorWord) { + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + + WdfRequestGetParameters( + Request, + ¶ms + ); + + + // + // There is a current error in the driver. No requests should + // come through except for the GET_COMMSTATUS. + // + + if ((params.Type != WdfRequestTypeDeviceControl) || + (params.Parameters.DeviceIoControl.IoControlCode != IOCTL_SERIAL_GET_COMMSTATUS)) { + status = STATUS_CANCELLED; + SerialCompleteRequest(Request, status, 0); + } + + } + + return status; + +} + +NTSTATUS +SerialCreateTimersAndDpcs( + IN PSERIAL_DEVICE_EXTENSION pDevExt + ) +/*++ + +Routine Description: + + This function creates all the timers and DPC objects. All the objects + are associated with the WDFDEVICE and the callbacks are serialized + with the device callbacks. Also these objects will be deleted automatically + when the device is deleted, so there is no need for the driver to explicitly + delete the objects. + +Arguments: + + PDevExt - Pointer to the device extension for the device + +Return Value: + + return NTSTATUS + +--*/ +{ + WDF_DPC_CONFIG dpcConfig; + WDF_TIMER_CONFIG timerConfig; + NTSTATUS status; + WDF_OBJECT_ATTRIBUTES dpcAttributes; + WDF_OBJECT_ATTRIBUTES timerAttributes; + + // + // Initialize all the timers used to timeout operations. + // + // + // This timer dpc is fired off if the timer for the total timeout + // for the read expires. It will cause the current read to complete. + // + + WDF_TIMER_CONFIG_INIT(&timerConfig, SerialReadTimeout); + + timerConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfTimerCreate(&timerConfig, + &timerAttributes, + &pDevExt->ReadRequestTotalTimer); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ReadRequestTotalTimer) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if the timer for the interval timeout + // expires. If no more characters have been read then the + // dpc routine will cause the read to complete. However, if + // more characters have been read then the dpc routine will + // resubmit the timer. + // + WDF_TIMER_CONFIG_INIT(&timerConfig, SerialIntervalReadTimeout); + + timerConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfTimerCreate(&timerConfig, + &timerAttributes, + &pDevExt->ReadRequestIntervalTimer); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ReadRequestIntervalTimer) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if the timer for the total timeout + // for the write expires. It will queue a dpc routine that + // will cause the current write to complete. + // + // + + WDF_TIMER_CONFIG_INIT(&timerConfig, SerialWriteTimeout); + + timerConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfTimerCreate(&timerConfig, + &timerAttributes, + &pDevExt->WriteRequestTotalTimer); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(WriteRequestTotalTimer) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if the transmit immediate char + // character times out. The dpc routine will "grab" the + // request from the isr and time it out. + // + WDF_TIMER_CONFIG_INIT(&timerConfig, SerialTimeoutImmediate); + + timerConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfTimerCreate(&timerConfig, + &timerAttributes, + &pDevExt->ImmediateTotalTimer); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(ImmediateTotalTimer) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if the timer used to "timeout" counting + // the number of characters received after the Xoff ioctl is started + // expired. + // + + WDF_TIMER_CONFIG_INIT(&timerConfig, SerialTimeoutXoff); + + timerConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfTimerCreate(&timerConfig, + &timerAttributes, + &pDevExt->XoffCountTimer); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(XoffCountTimer) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off when a timer expires (after one + // character time), so that code can be invoked that will + // check to see if we should lower the RTS line when + // doing transmit toggling. + // + WDF_TIMER_CONFIG_INIT(&timerConfig, SerialInvokePerhapsLowerRTS); + + timerConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfTimerCreate(&timerConfig, + &timerAttributes, + &pDevExt->LowerRTSTimer); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfTimerCreate(LowerRTSTimer) failed [%#08lx]\n", status); + return status; + } + + // + // Create a DPC to complete read requests. + // + + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteWrite); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->CompleteWriteDpc); + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteWriteDpc) failed [%#08lx]\n", status); + return status; + } + + + // + // Create a DPC to complete read requests. + // + + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteRead); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->CompleteReadDpc); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteReadDpc) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if a comm error occurs. It will + // cancel all pending reads and writes. + // + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCommError); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->CommErrorDpc); + + + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CommErrorDpc) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off when the transmit immediate char + // character is given to the hardware. It will simply complete + // the request. + // + + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteImmediate); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->CompleteImmediateDpc); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CompleteImmediateDpc) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if an event occurs and there was + // a request waiting on that event. A dpc routine will execute + // that completes the request. + // + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteWait); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->CommWaitDpc); + if (!NT_SUCCESS(status)) { + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(CommWaitDpc) failed [%#08lx]\n", status); + return status; + } + + // + // This dpc is fired off if the xoff counter actually runs down + // to zero. + // + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialCompleteXoff); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->XoffCountCompleteDpc); + + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(XoffCountCompleteDpc) failed [%#08lx]\n", status); + return status; + } + + + // + // This dpc is fired off only from device level to start off + // a timer that will queue a dpc to check if the RTS line + // should be lowered when we are doing transmit toggling. + // + WDF_DPC_CONFIG_INIT(&dpcConfig, SerialStartTimerLowerRTS); + + dpcConfig.AutomaticSerialization = TRUE; + + WDF_OBJECT_ATTRIBUTES_INIT(&dpcAttributes); + dpcAttributes.ParentObject = pDevExt->WdfDevice; + + status = WdfDpcCreate(&dpcConfig, + &dpcAttributes, + &pDevExt->StartTimerLowerRTSDpc); + if (!NT_SUCCESS(status)) { + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_PNP, "WdfDpcCreate(StartTimerLowerRTSDpc) failed [%#08lx]\n", status); + return status; + } + + return status; +} + + + + +BOOLEAN +SerialInsertQueueDpc(IN WDFDPC PDpc) +/*++ + +Routine Description: + + This function must be called to queue DPC's for the serial driver. + +Arguments: + + PDpc - Pointer to the Dpc object + +Return Value: + + Kicks up return value from KeInsertQueueDpc() + +--*/ +{ + // + // If the specified DPC object is not currently in the queue, WdfDpcEnqueue + // queues the DPC and returns TRUE. + // + + return WdfDpcEnqueue(PDpc); +} + + + +BOOLEAN +SerialSetTimer(IN WDFTIMER Timer, IN LARGE_INTEGER DueTime) +/*++ + +Routine Description: + + This function must be called to set timers for the serial driver. + +Arguments: + + Timer - pointer to timer dispatcher object + + DueTime - time at which the timer should expire + + +Return Value: + + Kicks up return value from KeSetTimerEx() + +--*/ +{ + BOOLEAN result; + // + // If the timer object was already in the system timer queue, WdfTimerStart returns TRUE + // + result = WdfTimerStart(Timer, DueTime.QuadPart); + + return result; + +} + + +VOID +SerialDrainTimersAndDpcs( + IN PSERIAL_DEVICE_EXTENSION PDevExt + ) +/*++ + +Routine Description: + + This function cancels all the timers and Dpcs and waits for them + to run to completion if they are already fired. + +Arguments: + + PDevExt - Pointer to the device extension for the device that needs to + set a timer + +Return Value: + +--*/ +{ + WdfTimerStop(PDevExt->ReadRequestTotalTimer, TRUE); + + WdfTimerStop(PDevExt->ReadRequestIntervalTimer, TRUE); + + WdfTimerStop(PDevExt->WriteRequestTotalTimer, TRUE); + + WdfTimerStop(PDevExt->ImmediateTotalTimer, TRUE); + + WdfTimerStop(PDevExt->XoffCountTimer, TRUE); + + WdfTimerStop(PDevExt->LowerRTSTimer, TRUE); + + WdfDpcCancel(PDevExt->CompleteWriteDpc, TRUE); + + WdfDpcCancel(PDevExt->CompleteReadDpc, TRUE); + + WdfDpcCancel(PDevExt->CommErrorDpc, TRUE); + + WdfDpcCancel(PDevExt->CompleteImmediateDpc, TRUE); + + WdfDpcCancel(PDevExt->CommWaitDpc, TRUE); + + WdfDpcCancel(PDevExt->XoffCountCompleteDpc, TRUE); + + WdfDpcCancel(PDevExt->StartTimerLowerRTSDpc, TRUE); + + return; +} + + + +BOOLEAN +SerialCancelTimer( + IN WDFTIMER Timer, + IN PSERIAL_DEVICE_EXTENSION PDevExt + ) +/*++ + +Routine Description: + + This function must be called to cancel timers for the serial driver. + +Arguments: + + Timer - pointer to timer dispatcher object + + PDevExt - Pointer to the device extension for the device that needs to + set a timer + +Return Value: + + True if timer was cancelled + +--*/ +{ + UNREFERENCED_PARAMETER(PDevExt); + + return WdfTimerStop(Timer, FALSE); +} + +SERIAL_MEM_COMPARES +SerialMemCompare( + IN PHYSICAL_ADDRESS A, + IN ULONG SpanOfA, + IN PHYSICAL_ADDRESS B, + IN ULONG SpanOfB + ) +/*++ + +Routine Description: + + Compare two phsical address. + +Arguments: + + A - One half of the comparison. + + SpanOfA - In units of bytes, the span of A. + + B - One half of the comparison. + + SpanOfB - In units of bytes, the span of B. + + +Return Value: + + The result of the comparison. + +--*/ +{ + LARGE_INTEGER a; + LARGE_INTEGER b; + + LARGE_INTEGER lower; + ULONG lowerSpan; + LARGE_INTEGER higher; + + PAGED_CODE(); + + a = A; + b = B; + + if (a.QuadPart == b.QuadPart) { + + return AddressesAreEqual; + + } + + if (a.QuadPart > b.QuadPart) { + + higher = a; + lower = b; + lowerSpan = SpanOfB; + + } else { + + higher = b; + lower = a; + lowerSpan = SpanOfA; + + } + + if ((higher.QuadPart - lower.QuadPart) >= lowerSpan) { + + return AddressesAreDisjoint; + + } + + return AddressesOverlap; + +} + + +VOID +SerialLogError( + _In_ PDRIVER_OBJECT DriverObject, + _In_opt_ PDEVICE_OBJECT DeviceObject, + _In_ PHYSICAL_ADDRESS P1, + _In_ PHYSICAL_ADDRESS P2, + _In_ ULONG SequenceNumber, + _In_ UCHAR MajorFunctionCode, + _In_ UCHAR RetryCount, + _In_ ULONG UniqueErrorValue, + _In_ NTSTATUS FinalStatus, + _In_ NTSTATUS SpecificIOStatus, + _In_ ULONG LengthOfInsert1, + _In_reads_bytes_opt_(LengthOfInsert1) PWCHAR Insert1, + _In_ ULONG LengthOfInsert2, + _In_reads_bytes_opt_(LengthOfInsert2) PWCHAR Insert2 + ) +/*++ + +Routine Description: + + This routine allocates an error log entry, copies the supplied data + to it, and requests that it be written to the error log file. + +Arguments: + + DriverObject - A pointer to the driver object for the device. + + DeviceObject - A pointer to the device object associated with the + device that had the error, early in initialization, one may not + yet exist. + + P1,P2 - If phyical addresses for the controller ports involved + with the error are available, put them through as dump data. + + SequenceNumber - A ulong value that is unique to an WDFREQUEST over the + life of the request in this driver - 0 generally means an error not + associated with an request. + + MajorFunctionCode - If there is an error associated with the request, + this is the major function code of that request. + + RetryCount - The number of times a particular operation has been + retried. + + UniqueErrorValue - A unique long word that identifies the particular + call to this function. + + FinalStatus - The final status given to the request that was associated + with this error. If this log entry is being made during one of + the retries this value will be STATUS_SUCCESS. + + SpecificIOStatus - The IO status for a particular error. + + LengthOfInsert1 - The length in bytes (including the terminating NULL) + of the first insertion string. + + Insert1 - The first insertion string. + + LengthOfInsert2 - The length in bytes (including the terminating NULL) + of the second insertion string. NOTE, there must + be a first insertion string for their to be + a second insertion string. + + Insert2 - The second insertion string. + +Return Value: + + None. + +--*/ + +{ + PIO_ERROR_LOG_PACKET errorLogEntry; + + PVOID objectToUse; + SHORT dumpToAllocate = 0; + PUCHAR ptrToFirstInsert; + PUCHAR ptrToSecondInsert; + + PAGED_CODE(); + + if (Insert1 == NULL) { + LengthOfInsert1 = 0; + } + + if (Insert2 == NULL) { + LengthOfInsert2 = 0; + } + + + if (ARGUMENT_PRESENT(DeviceObject)) { + + objectToUse = DeviceObject; + + } else { + + objectToUse = DriverObject; + + } + + if (SerialMemCompare( + P1, + (ULONG)1, + SerialPhysicalZero, + (ULONG)1 + ) != AddressesAreEqual) { + + dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS); + + } + + if (SerialMemCompare( + P2, + (ULONG)1, + SerialPhysicalZero, + (ULONG)1 + ) != AddressesAreEqual) { + + dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS); + + } + + errorLogEntry = IoAllocateErrorLogEntry( + objectToUse, + (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + + dumpToAllocate + + LengthOfInsert1 + + LengthOfInsert2) + ); + + if ( errorLogEntry != NULL ) { + + errorLogEntry->ErrorCode = SpecificIOStatus; + errorLogEntry->SequenceNumber = SequenceNumber; + errorLogEntry->MajorFunctionCode = MajorFunctionCode; + errorLogEntry->RetryCount = RetryCount; + errorLogEntry->UniqueErrorValue = UniqueErrorValue; + errorLogEntry->FinalStatus = FinalStatus; + errorLogEntry->DumpDataSize = dumpToAllocate; + + if (dumpToAllocate) { + + RtlCopyMemory( + &errorLogEntry->DumpData[0], + &P1, + sizeof(PHYSICAL_ADDRESS) + ); + + if (dumpToAllocate > sizeof(PHYSICAL_ADDRESS)) { + + RtlCopyMemory( + ((PUCHAR)&errorLogEntry->DumpData[0]) + +sizeof(PHYSICAL_ADDRESS), + &P2, + sizeof(PHYSICAL_ADDRESS) + ); + + ptrToFirstInsert = + ((PUCHAR)&errorLogEntry->DumpData[0])+(2*sizeof(PHYSICAL_ADDRESS)); + + } else { + + ptrToFirstInsert = + ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS); + + + } + + } else { + + ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0]; + + } + + ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1; + + if (LengthOfInsert1) { + + errorLogEntry->NumberOfStrings = 1; + errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert - + (PUCHAR)errorLogEntry); + RtlCopyMemory( + ptrToFirstInsert, + Insert1, + LengthOfInsert1 + ); + + if (LengthOfInsert2) { + + errorLogEntry->NumberOfStrings = 2; + RtlCopyMemory( + ptrToSecondInsert, + Insert2, + LengthOfInsert2 + ); + + } + + } + + IoWriteErrorLogEntry(errorLogEntry); + + } + +} + +VOID +SerialMarkHardwareBroken(IN PSERIAL_DEVICE_EXTENSION PDevExt) +/*++ + +Routine Description: + + Marks a UART as broken. This causes the driver stack to stop accepting + requests and eventually be removed. + +Arguments: + PDevExt - Device extension attached to PDevObj + +Return Value: + + None. + +--*/ +{ + PAGED_CODE(); + + // + // Write a log entry + // + + SerialLogError(PDevExt->DriverObject, NULL, SerialPhysicalZero, + SerialPhysicalZero, 0, 0, 0, 88, STATUS_SUCCESS, + SERIAL_HARDWARE_FAILURE, PDevExt->DeviceName.Length + + sizeof(WCHAR), PDevExt->DeviceName.Buffer, 0, NULL); + + SerialDbgPrintEx(TRACE_LEVEL_ERROR, DBG_INIT, "Device is broken. Request a restart...\n"); + WdfDeviceSetFailed(PDevExt->WdfDevice, WdfDeviceFailedAttemptRestart); +} + +NTSTATUS +SerialGetDivisorFromBaud( + IN ULONG ClockRate, + IN LONG DesiredBaud, + OUT PSHORT AppropriateDivisor + ) + +/*++ + +Routine Description: + + This routine will determine a divisor based on an unvalidated + baud rate. + +Arguments: + + ClockRate - The clock input to the controller. + + DesiredBaud - The baud rate for whose divisor we seek. + + AppropriateDivisor - Given that the DesiredBaud is valid, the + LONG pointed to by this parameter will be set to the appropriate + value. NOTE: The long is undefined if the DesiredBaud is not + supported. + +Return Value: + + This function will return STATUS_SUCCESS if the baud is supported. + If the value is not supported it will return a status such that + NT_ERROR(Status) == FALSE. + +--*/ + +{ + + NTSTATUS status = STATUS_SUCCESS; + SHORT calculatedDivisor; + ULONG denominator; + ULONG remainder; + + // + // Allow up to a 1 percent error + // + + ULONG maxRemain18 = 18432; + ULONG maxRemain30 = 30720; + ULONG maxRemain42 = 42336; + ULONG maxRemain80 = 80000; + ULONG maxRemain; + + + + // + // Reject any non-positive bauds. + // + + denominator = DesiredBaud*(ULONG)16; + + if (DesiredBaud <= 0) { + + *AppropriateDivisor = -1; + + } else if ((LONG)denominator < DesiredBaud) { + + // + // If the desired baud was so huge that it cause the denominator + // calculation to wrap, don't support it. + // + + *AppropriateDivisor = -1; + + } else { + + if (ClockRate == 1843200) { + maxRemain = maxRemain18; + } else if (ClockRate == 3072000) { + maxRemain = maxRemain30; + } else if (ClockRate == 4233600) { + maxRemain = maxRemain42; + } else { + maxRemain = maxRemain80; + } + + calculatedDivisor = (SHORT)(ClockRate / denominator); + remainder = ClockRate % denominator; + + // + // Round up. + // + + if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) { + + calculatedDivisor++; + } + + + // + // Only let the remainder calculations effect us if + // the baud rate is > 9600. + // + + if (DesiredBaud >= 9600) { + + // + // If the remainder is less than the maximum remainder (wrt + // the ClockRate) or the remainder + the maximum remainder is + // greater than or equal to the ClockRate then assume that the + // baud is ok. + // + + if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) { + calculatedDivisor = -1; + } + + } + + // + // Don't support a baud that causes the denominator to + // be larger than the clock. + // + + if (denominator > ClockRate) { + + calculatedDivisor = -1; + + } + + // + // Ok, Now do some special casing so that things can actually continue + // working on all platforms. + // + + if (ClockRate == 1843200) { + + if (DesiredBaud == 56000) { + calculatedDivisor = 2; + } + + } else if (ClockRate == 3072000) { + + if (DesiredBaud == 14400) { + calculatedDivisor = 13; + } + + } else if (ClockRate == 4233600) { + + if (DesiredBaud == 9600) { + calculatedDivisor = 28; + } else if (DesiredBaud == 14400) { + calculatedDivisor = 18; + } else if (DesiredBaud == 19200) { + calculatedDivisor = 14; + } else if (DesiredBaud == 38400) { + calculatedDivisor = 7; + } else if (DesiredBaud == 56000) { + calculatedDivisor = 5; + } + + } else if (ClockRate == 8000000) { + + if (DesiredBaud == 14400) { + calculatedDivisor = 35; + } else if (DesiredBaud == 56000) { + calculatedDivisor = 9; + } + + } + + *AppropriateDivisor = calculatedDivisor; + + } + + + if (*AppropriateDivisor == -1) { + + status = STATUS_INVALID_PARAMETER; + + } + + return status; + +} + + +BOOLEAN +IsQueueEmpty( + IN WDFQUEUE Queue + ) +{ + WDF_IO_QUEUE_STATE queueStatus; + + queueStatus = WdfIoQueueGetState( Queue, NULL, NULL ); + + return (WDF_IO_QUEUE_IDLE(queueStatus)) ? TRUE : FALSE; +} + +VOID +SerialSetCancelRoutine( + IN WDFREQUEST Request, + IN PFN_WDF_REQUEST_CANCEL CancelRoutine) +{ + PREQUEST_CONTEXT reqContext = SerialGetRequestContext(Request); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "-->SerialSetCancelRoutine %p \n", Request); + + WdfRequestMarkCancelable(Request, CancelRoutine); + SERIAL_SET_REFERENCE(reqContext, SERIAL_REF_CANCEL); + reqContext->CancelRoutine = CancelRoutine; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "<-- SerialSetCancelRoutine \n"); + + return; +} + +NTSTATUS +SerialClearCancelRoutine( + IN WDFREQUEST Request, + IN BOOLEAN ClearReference + ) +{ + NTSTATUS status = STATUS_SUCCESS; + PREQUEST_CONTEXT reqContext = SerialGetRequestContext(Request); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "-->SerialClearCancelRoutine %p %x\n", + Request, ClearReference); + + if(SERIAL_TEST_REFERENCE(reqContext, SERIAL_REF_CANCEL)) + { + status = WdfRequestUnmarkCancelable(Request); + if (NT_SUCCESS(status)) { + + reqContext->CancelRoutine = NULL; + if(ClearReference) { + + SERIAL_CLEAR_REFERENCE( reqContext, SERIAL_REF_CANCEL ); + + } + } else { + ASSERT(status == STATUS_CANCELLED); + } + } + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "-->SerialClearCancelRoutine %p\n", Request); + + return status; +} + + +VOID +SerialCompleteRequest( + IN WDFREQUEST Request, + IN NTSTATUS Status, + IN ULONG_PTR Info + ) +{ + PREQUEST_CONTEXT reqContext; + + reqContext = SerialGetRequestContext(Request); + + ASSERT(reqContext->RefCount == 0); + + SerialDbgPrintEx(TRACE_LEVEL_VERBOSE, DBG_PNP, + "Complete Request: %p %X 0x%I64x\n", + (Request), (Status), (Info)); + + WdfRequestCompleteWithInformation((Request), (Status), (Info)); + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/waitmask.c b/tests/projects/windows/driver/kmdf/serial/waitmask.c new file mode 100644 index 000000000..c3139679e --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/waitmask.c @@ -0,0 +1,574 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + waitmask.c + +Abstract: + + This module contains the code that is very specific to get/set/wait + on event mask operations in the serial driver + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "waitmask.tmh" +#endif + +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabWaitFromIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGiveWaitToIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialFinishOldWait; + + +VOID +SerialStartMask( + IN PSERIAL_DEVICE_EXTENSION Extension + ) + +/*++ + +Routine Description: + + This routine is used to process the set mask and wait + mask ioctls. Calls to this routine are serialized by + placing irps in the list under the protection of the + cancel spin lock. + +Arguments: + + Extension - A pointer to the serial device extension. + +Return Value: + + Will return pending for everything put the first + request that we actually process. Even in that + case it will return pending unless it can complete + it right away. + + +--*/ + +{ + + + WDFREQUEST NewRequest; + PREQUEST_CONTEXT reqContext; + WDF_REQUEST_PARAMETERS params; + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "In SerialStartMask\n"); + + ASSERT(Extension->CurrentMaskRequest); + + + do { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "STARTMASK - CurrentMaskRequest: %p\n", + Extension->CurrentMaskRequest); + + WDF_REQUEST_PARAMETERS_INIT(¶ms); + + WdfRequestGetParameters( + Extension->CurrentMaskRequest, + ¶ms + ); + + + reqContext = SerialGetRequestContext(Extension->CurrentMaskRequest); + + ASSERT((params.Parameters.DeviceIoControl.IoControlCode == + IOCTL_SERIAL_WAIT_ON_MASK) || + (params.Parameters.DeviceIoControl.IoControlCode == + IOCTL_SERIAL_SET_WAIT_MASK)); + + if (params.Parameters.DeviceIoControl.IoControlCode == + IOCTL_SERIAL_SET_WAIT_MASK) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "SERIAL - %p is a SETMASK request\n", + Extension->CurrentMaskRequest); + + // + // Complete the old wait if there is one. + // + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialFinishOldWait, + Extension + ); + + // + // Any current waits should be on its way to completion + // at this point. There certainly shouldn't be any + // request mask location. + // + + ASSERT(!Extension->IrpMaskLocation); + + reqContext->Status = STATUS_SUCCESS; + + // + // The following call will also cause the current + // call to be completed. + // + + SerialGetNextRequest( + &Extension->CurrentMaskRequest, + Extension->MaskQueue, + &NewRequest, + TRUE, + Extension + ); + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Perhaps another mask request was found in " + "the queue\n" + "------- %p/%p <- values should be the same\n", + Extension->CurrentMaskRequest, NewRequest); + + + } else { + + // + // First make sure that we have a non-zero mask. + // If the app queues a wait on a zero mask it can't + // be statisfied so it makes no sense to start it. + // + + if ((!Extension->IsrWaitMask) || (Extension->CurrentWaitRequest)) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "WaitIrp is invalid\n" + "------- IsrWaitMask: %x\n" + "------- CurrentWaitRequest: %p\n", + Extension->IsrWaitMask, + Extension->CurrentWaitRequest); + + reqContext->Status = STATUS_INVALID_PARAMETER; + + SerialGetNextRequest(&Extension->CurrentMaskRequest, + Extension->MaskQueue, &NewRequest, TRUE, + Extension); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Perhaps another mask request was found " + "in the queue\n" + "------- %p/%p <- values should be the same\n", + Extension->CurrentMaskRequest,NewRequest); + + } else { + + // + // Make the current mask request the current wait request and + // get a new current mask request. Note that when we get + // the new current mask request we DO NOT complete the + // old current mask request (which is now the current wait + // request. + // + // Then under the protection of the cancel spin lock + // we check to see if the current wait request needs to + // be canceled + // + + SERIAL_INIT_REFERENCE(reqContext); + + SerialSetCancelRoutine(Extension->CurrentMaskRequest, + SerialCancelWait); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "%p will become the current " + "wait request\n", + Extension->CurrentMaskRequest); + // + // There should never be a mask location when + // there isn't a current wait request. At this point + // there shouldn't be a current wait request also. + // + + ASSERT(!Extension->IrpMaskLocation); + ASSERT(!Extension->CurrentWaitRequest); + + Extension->CurrentWaitRequest = Extension->CurrentMaskRequest; + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGiveWaitToIsr, + Extension + ); + + // + // Since it isn't really the mask request anymore, + // null out that pointer. + // + Extension->CurrentMaskRequest = NULL; + + // + // This will release the cancel spinlock for us + // + + SerialGetNextRequest(&Extension->CurrentMaskRequest, + Extension->MaskQueue, &NewRequest, + FALSE, Extension); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Perhaps another mask request was " + "found in the queue\n" + "------- %p/%p <- values should be the " + "same\n", Extension->CurrentMaskRequest, + NewRequest); + } + + } + + } while (NewRequest); + + return; + +} + +BOOLEAN +SerialGrabWaitFromIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine will check to see if the ISR still knows about + a wait request by checking to see if the IrpMaskLocation is non-null. + If it is then it will zero the Irpmasklocation (which in effect + grabs the request away from the isr). This routine is only called + buy the cancel code for the wait. + + NOTE: This is called by WdfInterruptSynchronize. + +Arguments: + + Context - A pointer to the device extension + +Return Value: + + Always FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = Context; + + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "In SerialGrabWaitFromIsr\n"); + + if (Extension->IrpMaskLocation) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "The isr still owns the request %p, mask " + "location is %p\n" + "------- and system buffer is %p\n", + Extension->CurrentWaitRequest,Extension->IrpMaskLocation, + reqContext->SystemBuffer); + + // + // The isr still "owns" the request. + // + + *Extension->IrpMaskLocation = 0; + Extension->IrpMaskLocation = NULL; + + reqContext->Information = sizeof(ULONG); + + // + // Since the isr no longer references the request we need to + // decrement the reference count. + // + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + } + + return FALSE; +} + +BOOLEAN +SerialGiveWaitToIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine simply sets a variable in the device extension + so that the isr knows that we have a wait request. + + NOTE: This is called by WdfInterruptSynchronize. + + NOTE: This routine assumes that it is called with the + cancel spinlock held. + +Arguments: + + Context - Simply a pointer to the device extension. + +Return Value: + + Always FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "In SerialGiveWaitToIsr\n"); + // + // There certainly shouldn't be a current mask location at + // this point since we have a new current wait request. + // + + ASSERT(!Extension->IrpMaskLocation); + + // + // The isr may or may not actually reference this request. It + // won't if the wait can be satisfied immediately. However, + // since it will then go through the normal completion sequence, + // we need to have an incremented reference count anyway. + // + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + if (!Extension->HistoryMask) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "No events occured prior to the wait call" + "\n"); + + // + // Although this wait might not be for empty transmit + // queue, it doesn't hurt anything to set it to false. + // + + Extension->EmptiedTransmit = FALSE; + + // + // Record where the "completion mask" should be set. + // + + Extension->IrpMaskLocation = reqContext->SystemBuffer; + SerialDbgPrintEx( TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "The isr owns the request %p, mask location is " + "%p\n" + "------- and system buffer is %p\n", + Extension->CurrentWaitRequest,Extension->IrpMaskLocation, + reqContext->SystemBuffer); + + } else { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "%x occurred prior to the wait - starting " + "the\n" + "------- completion code for %p\n", + Extension->HistoryMask,Extension->CurrentWaitRequest); + + *((ULONG *)reqContext->SystemBuffer) = + Extension->HistoryMask; + Extension->HistoryMask = 0; + reqContext->Information = sizeof(ULONG); + reqContext->Status = STATUS_SUCCESS; + + SerialInsertQueueDpc(Extension->CommWaitDpc); + + } + + return FALSE; +} + +BOOLEAN +SerialFinishOldWait( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine will check to see if the ISR still knows about + a wait request by checking to see if the Irpmasklocation is non-null. + If it is then it will zero the Irpmasklocation (which in effect + grabs the request away from the isr). This routine is only called + buy the cancel code for the wait. + + NOTE: This is called by WdfInterruptSynchronize. + +Arguments: + + Context - A pointer to the device extension + +Return Value: + + Always FALSE. + +--*/ + +{ + PSERIAL_DEVICE_EXTENSION Extension = Context; + + PREQUEST_CONTEXT reqContext = NULL; + PREQUEST_CONTEXT reqContextMask; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContextMask = SerialGetRequestContext(Extension->CurrentMaskRequest); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "In SerialFinishOldWait\n"); + + if (Extension->IrpMaskLocation) { + + reqContext = SerialGetRequestContext(Extension->CurrentWaitRequest); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "The isr still owns the request %p, mask " + "location is %p\n" + "------- and system buffer is %p\n", + Extension->CurrentWaitRequest,Extension->IrpMaskLocation, + reqContext->SystemBuffer); + // + // The isr still "owns" the request. + // + + *Extension->IrpMaskLocation = 0; + Extension->IrpMaskLocation = NULL; + + reqContext->Information = sizeof(ULONG); + + // + // We don't decrement the reference since the completion routine + // will do that. + // + + SerialInsertQueueDpc(Extension->CommWaitDpc); + + } + + // + // Don't wipe out any historical data we are still interested in. + // + + Extension->HistoryMask &= *((ULONG *)reqContextMask->SystemBuffer); + + Extension->IsrWaitMask = *((ULONG *)reqContextMask->SystemBuffer); + SerialDbgPrintEx( TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Set mask location of %p, in request %p, with " + "system buffer of %p\n", + Extension->IrpMaskLocation, Extension->CurrentMaskRequest, + reqContextMask->SystemBuffer); + return FALSE; +} + +VOID +SerialCancelWait( + IN WDFREQUEST Request + ) + +/*++ + +Routine Description: + + This routine is used to cancel a request that is waiting on + a comm event. + +Arguments: + + Device - Wdf handle for the device + + Request - Pointer to the WDFREQUEST for the current request + +Return Value: + + None. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension; + WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); + + UNREFERENCED_PARAMETER(Request); + + Extension = SerialGetDeviceExtension(device); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Canceling wait for request %p\n", + Extension->CurrentWaitRequest); + + SerialTryToCompleteCurrent(Extension, + SerialGrabWaitFromIsr, + STATUS_CANCELLED, + &Extension->CurrentWaitRequest, + NULL, NULL, NULL, + NULL, NULL, SERIAL_REF_CANCEL); + +} + + +VOID +SerialCompleteWait( + IN WDFDPC Dpc + ) + +{ + + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + ">SerialCompleteWait(%p)\n", + Extension); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + "Completing wait for request %p\n", + Extension->CurrentWaitRequest); + + SerialTryToCompleteCurrent(Extension, NULL, STATUS_SUCCESS, + &Extension->CurrentWaitRequest, NULL, NULL, NULL, + NULL, NULL, SERIAL_REF_ISR); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, + " + +#if defined(EVENT_TRACING) +#include "wmi.tmh" +#endif + +EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortName; +EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortCommData; +EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortHWData; +EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortPerfData; +EVT_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiQueryPortPropData; + +NTSTATUS +SerialWmiRegisterInstance( + WDFDEVICE Device, + const GUID* Guid, + ULONG MinInstanceBufferSize, + PFN_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceQueryInstance + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGESRP0, SerialWmiRegistration) +#pragma alloc_text(PAGESRP0, SerialWmiRegisterInstance) +#pragma alloc_text(PAGESRP0, EvtWmiQueryPortName) +#pragma alloc_text(PAGESRP0, EvtWmiQueryPortCommData) +#pragma alloc_text(PAGESRP0, EvtWmiQueryPortHWData) +#pragma alloc_text(PAGESRP0, EvtWmiQueryPortPerfData) +#pragma alloc_text(PAGESRP0, EvtWmiQueryPortPropData) +#endif + +NTSTATUS +SerialWmiRegisterInstance( + WDFDEVICE Device, + const GUID* Guid, + ULONG MinInstanceBufferSize, + PFN_WDF_WMI_INSTANCE_QUERY_INSTANCE EvtWmiInstanceQueryInstance + ) +{ + WDF_WMI_PROVIDER_CONFIG providerConfig; + WDF_WMI_INSTANCE_CONFIG instanceConfig; + + PAGED_CODE(); + + // + // Create and register WMI providers and instances blocks + // + WDF_WMI_PROVIDER_CONFIG_INIT(&providerConfig, Guid); + providerConfig.MinInstanceBufferSize = MinInstanceBufferSize; + + WDF_WMI_INSTANCE_CONFIG_INIT_PROVIDER_CONFIG(&instanceConfig, &providerConfig); + instanceConfig.Register = TRUE; + instanceConfig.EvtWmiInstanceQueryInstance = EvtWmiInstanceQueryInstance; + + return WdfWmiInstanceCreate(Device, + &instanceConfig, + WDF_NO_OBJECT_ATTRIBUTES, + WDF_NO_HANDLE); +} + +NTSTATUS +SerialWmiRegistration( + WDFDEVICE Device +) +/*++ +Routine Description + + Registers with WMI as a data provider for this + instance of the device + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PSERIAL_DEVICE_EXTENSION pDevExt; + + PAGED_CODE(); + + pDevExt = SerialGetDeviceExtension (Device); + + // + // Fill in wmi perf data (all zero's) + // + RtlZeroMemory(&pDevExt->WmiPerfData, sizeof(pDevExt->WmiPerfData)); + + status = SerialWmiRegisterInstance(Device, + &MSSerial_PortName_GUID, + 0, + EvtWmiQueryPortName); + if (!NT_SUCCESS(status)) { + return status; + } + + status = SerialWmiRegisterInstance(Device, + &MSSerial_CommInfo_GUID, + sizeof(SERIAL_WMI_COMM_DATA), + EvtWmiQueryPortCommData); + if (!NT_SUCCESS(status)) { + return status; + } + + status = SerialWmiRegisterInstance(Device, + &MSSerial_HardwareConfiguration_GUID, + sizeof(SERIAL_WMI_HW_DATA), + EvtWmiQueryPortHWData); + if (!NT_SUCCESS(status)) { + return status; + } + + status = SerialWmiRegisterInstance(Device, + &MSSerial_PerformanceInformation_GUID, + sizeof(SERIAL_WMI_PERF_DATA), + EvtWmiQueryPortPerfData); + if (!NT_SUCCESS(status)) { + return status; + } + + status = SerialWmiRegisterInstance(Device, + &MSSerial_CommProperties_GUID, + sizeof(SERIAL_COMMPROP) + sizeof(ULONG), + EvtWmiQueryPortPropData); + + if (!NT_SUCCESS(status)) { + return status; + } + + return status; +} + +// +// WMI Call back functions +// + +NTSTATUS +EvtWmiQueryPortName( + IN WDFWMIINSTANCE WmiInstance, + IN ULONG OutBufferSize, + IN PVOID OutBuffer, + OUT PULONG BufferUsed + ) +{ + WDFDEVICE device; + WCHAR pRegName[SYMBOLIC_NAME_LENGTH]; + UNICODE_STRING string; + USHORT nameSize = sizeof(pRegName); + NTSTATUS status; + + PAGED_CODE(); + + device = WdfWmiInstanceGetDevice(WmiInstance); + + status = SerialReadSymName(device, pRegName, &nameSize); + if (!NT_SUCCESS(status)) { + return status; + } + + RtlInitUnicodeString(&string, pRegName); + + return WDF_WMI_BUFFER_APPEND_STRING(OutBuffer, + OutBufferSize, + &string, + BufferUsed); +} + +NTSTATUS +EvtWmiQueryPortCommData( + IN WDFWMIINSTANCE WmiInstance, + IN ULONG OutBufferSize, + IN PVOID OutBuffer, + OUT PULONG BufferUsed + ) +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + + UNREFERENCED_PARAMETER(OutBufferSize); + + PAGED_CODE(); + + pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); + + *BufferUsed = sizeof(SERIAL_WMI_COMM_DATA); + + if (OutBufferSize < *BufferUsed) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + *(PSERIAL_WMI_COMM_DATA)OutBuffer = pDevExt->WmiCommData; + + return STATUS_SUCCESS; +} + +NTSTATUS +EvtWmiQueryPortHWData( + IN WDFWMIINSTANCE WmiInstance, + IN ULONG OutBufferSize, + IN PVOID OutBuffer, + OUT PULONG BufferUsed + ) +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + + UNREFERENCED_PARAMETER(OutBufferSize); + + PAGED_CODE(); + + pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); + + *BufferUsed = sizeof(SERIAL_WMI_HW_DATA); + + if (OutBufferSize < *BufferUsed) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + *(PSERIAL_WMI_HW_DATA)OutBuffer = pDevExt->WmiHwData; + + return STATUS_SUCCESS; +} + +NTSTATUS +EvtWmiQueryPortPerfData( + IN WDFWMIINSTANCE WmiInstance, + IN ULONG OutBufferSize, + IN PVOID OutBuffer, + OUT PULONG BufferUsed + ) +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + + UNREFERENCED_PARAMETER(OutBufferSize); + + PAGED_CODE(); + + pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); + + *BufferUsed = sizeof(SERIAL_WMI_PERF_DATA); + + if (OutBufferSize < *BufferUsed) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + *(PSERIAL_WMI_PERF_DATA)OutBuffer = pDevExt->WmiPerfData; + + return STATUS_SUCCESS; +} + +NTSTATUS +EvtWmiQueryPortPropData( + IN WDFWMIINSTANCE WmiInstance, + IN ULONG OutBufferSize, + IN PVOID OutBuffer, + OUT PULONG BufferUsed + ) +{ + PSERIAL_DEVICE_EXTENSION pDevExt; + + UNREFERENCED_PARAMETER(OutBufferSize); + + PAGED_CODE(); + + pDevExt = SerialGetDeviceExtension (WdfWmiInstanceGetDevice(WmiInstance)); + + *BufferUsed = sizeof(SERIAL_COMMPROP) + sizeof(ULONG); + + if (OutBufferSize < *BufferUsed) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + SerialGetProperties( + pDevExt, + (PSERIAL_COMMPROP)OutBuffer + ); + + *((PULONG)(((PSERIAL_COMMPROP)OutBuffer)->ProvChar)) = 0; + + return STATUS_SUCCESS; +} + diff --git a/tests/projects/windows/driver/kmdf/serial/write.c b/tests/projects/windows/driver/kmdf/serial/write.c new file mode 100644 index 000000000..c67c062b4 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/write.c @@ -0,0 +1,1195 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + write.c + +Abstract: + + This module contains the code that is very specific to write + operations in the serial driver + +Environment: + + Kernel mode + +--*/ + +#include "precomp.h" + +#if defined(EVENT_TRACING) +#include "write.tmh" +#endif + +EVT_WDF_REQUEST_CANCEL SerialCancelCurrentWrite; +EVT_WDF_REQUEST_CANCEL SerialCancelCurrentXoff; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGiveWriteToIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGiveXoffToIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabWriteFromIsr; +EVT_WDF_INTERRUPT_SYNCHRONIZE SerialGrabXoffFromIsr; + + +VOID +SerialEvtIoWrite( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t Length + ) + +/*++ + +Routine Description: + + This is the dispatch routine for write. It validates the parameters + for the write request and if all is ok then it places the request + on the work queue. + +Arguments: + + Queue - Handle to the framework queue object that is associated + with the I/O request. + Request - Pointer to the WDFREQUEST for the current request + + Length - Length of the IO operation + The default property of the queue is to not dispatch + zero lenght read & write requests to the driver and + complete is with status success. So we will never get + a zero length request. + +Return Value: + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION extension; + NTSTATUS status; + WDFDEVICE hDevice; + WDF_REQUEST_PARAMETERS params; + PREQUEST_CONTEXT reqContext; + size_t bufLen; + + hDevice = WdfIoQueueGetDevice(Queue); + extension = SerialGetDeviceExtension(hDevice); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, + ">SerialEvtIoWrite(%p, 0x%I64x)\n", Request, Length); + + if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) { + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "MajorFunction = params.Type; + reqContext->Length = (ULONG) Length; + + status = WdfRequestRetrieveInputBuffer (Request, Length, &reqContext->SystemBuffer, &bufLen); + + if (!NT_SUCCESS (status)) { + + SerialCompleteRequest(Request , status, 0); + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "WriteQueue, + &extension->CurrentWriteRequest, + SerialStartWrite); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialStartWrite(%p)\n", Extension); + + TotalTime.QuadPart = 0; + + do { + + reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); + + // + // If there is an xoff counter then complete it. + // + + // + // We see if there is a actually an Xoff counter request. + // + // If there is, we put the write request back on the head + // of the write list. We then complete the xoff counter. + // The xoff counter completing code will actually make the + // xoff counter back into the current write request, and + // in the course of completing the xoff (which is now + // the current write) we will restart this request. + // + + if (Extension->CurrentXoffRequest) { + + reqContextXoff = + SerialGetRequestContext(Extension->CurrentXoffRequest); + + if (SERIAL_REFERENCE_COUNT(reqContextXoff)) { + + // + // The reference count is non-zero. This implies that + // the xoff request has not made it through the completion + // path yet. We will increment the reference count + // and attempt to complete it ourseleves. + // + + SERIAL_SET_REFERENCE( + reqContextXoff, + SERIAL_REF_XOFF_REF + ); + + reqContextXoff->Information = 0; + + // + // The following call will actually release the + // cancel spin lock. + // + + SerialTryToCompleteCurrent( + Extension, + SerialGrabXoffFromIsr, + STATUS_SERIAL_MORE_WRITES, + &Extension->CurrentXoffRequest, + NULL, + NULL, + Extension->XoffCountTimer, + NULL, + NULL, + SERIAL_REF_XOFF_REF + ); + + } else { + + // + // The request is well on its way to being finished. + // We can let the regular completion code do the + // work. Just release the spin lock. + // + + } + + } + + UseATimer = FALSE; + + // + // Calculate the timeout value needed for the + // request. Note that the values stored in the + // timeout record are in milliseconds. Note that + // if the timeout values are zero then we won't start + // the timer. + // + + Timeouts = Extension->Timeouts; + + if (Timeouts.WriteTotalTimeoutConstant || + Timeouts.WriteTotalTimeoutMultiplier) { + + UseATimer = TRUE; + + // + // We have some timer values to calculate. + // + // Take care, we might have an xoff counter masquerading + // as a write. + // + + TotalTime.QuadPart = + ((LONGLONG)((UInt32x32To64( + (reqContext->MajorFunction == IRP_MJ_WRITE)? + (reqContext->Length) : (1), + Timeouts.WriteTotalTimeoutMultiplier + ) + + Timeouts.WriteTotalTimeoutConstant))) + * -10000; + + } + + // + // The request may be going to the isr shortly. Now + // is a good time to initialize its reference counts. + // + + SERIAL_INIT_REFERENCE(reqContext); + + // + // We give the request to to the isr to write out. + // We set a cancel routine that knows how to + // grab the current write away from the isr. + // + SerialSetCancelRoutine(Extension->CurrentWriteRequest, + SerialCancelCurrentWrite); + + if (UseATimer) { + BOOLEAN result; + + result = SerialSetTimer( + Extension->WriteRequestTotalTimer, + TotalTime + ); + if(result == FALSE) { + // + // This timer now has a reference to the request. + // + + SERIAL_SET_REFERENCE( reqContext, SERIAL_REF_TOTAL_TIMER ); + } + } + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGiveWriteToIsr, + Extension + ); + + } WHILE (FALSE); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialGetNextWrite\n"); + + + do { + + reqContext = SerialGetRequestContext(*CurrentOpRequest); + + // + // We could be completing a flush. + // + + if (reqContext->MajorFunction == IRP_MJ_WRITE) { + + ASSERT(Extension->TotalCharsQueued >= reqContext->Length); + + Extension->TotalCharsQueued -= reqContext->Length; + + } else if (reqContext->MajorFunction == IRP_MJ_DEVICE_CONTROL) { + + WDFREQUEST request = *CurrentOpRequest; + PSERIAL_XOFF_COUNTER Xc; + + Xc = reqContext->SystemBuffer; + + // + // We should never have a xoff counter when we + // get to this point. + // + + ASSERT(!Extension->CurrentXoffRequest); + + // + // This could only be a xoff counter masquerading as + // a write request. + // + + Extension->TotalCharsQueued--; + + // + // Check to see of the xoff request has been set with success. + // This means that the write completed normally. If that + // is the case, and it hasn't been set to cancel in the + // meanwhile, then go on and make it the CurrentXoffRequest. + // + + if (reqContext->Status != STATUS_SUCCESS || reqContext->Cancelled) { + + // TODO: I see Xoff request getting abandoned due to loss of + // Total timer - SERIAL_REF_TOTAL_TIMER + // + // Oh well, we can just finish it off. + // + NOTHING; + + } else { + + SerialSetCancelRoutine(request, SerialCancelCurrentXoff); + + // + // We don't want to complete the current request now. This + // will now get completed by the Xoff counter code. + // + + CompleteCurrent = FALSE; + + // + // Give the counter to the isr. + // + + Extension->CurrentXoffRequest = request; + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialGiveXoffToIsr, + Extension + ); + + // + // Start the timer for the counter and increment + // the reference count since the timer has a + // reference to the request. + // + + if (Xc->Timeout) { + + LARGE_INTEGER delta; + BOOLEAN result; + + delta.QuadPart = -((LONGLONG)UInt32x32To64( + 1000, + Xc->Timeout + )); + + result = SerialSetTimer( + Extension->XoffCountTimer, + delta + + ); + if(result == FALSE) { + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_TOTAL_TIMER + ); + } + } + + } + + + } + + // + // Note that the following call will (probably) also cause + // the current request to be completed. + // + + SerialGetNextRequest( + CurrentOpRequest, + QueueToProcess, + NewRequest, + CompleteCurrent, + Extension + ); + + if (!*NewRequest) { + + + WdfInterruptSynchronize( + Extension->WdfInterrupt, + SerialProcessEmptyTransmit, + Extension + ); + + break; + + } else if (SerialGetRequestContext(*NewRequest)->MajorFunction + == IRP_MJ_FLUSH_BUFFERS) { + + // + // If we encounter a flush request we just want to get + // the next request and complete the flush. + // + // Note that if NewRequest is non-null then it is also + // equal to CurrentWriteRequest. + // + + + ASSERT((*NewRequest) == (*CurrentOpRequest)); + SerialGetRequestContext(*NewRequest)->Status = STATUS_SUCCESS; + + } else { + + break; + + } + + } WHILE (TRUE); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialCompleteWrite(%p)\n", + Extension); + + + SerialTryToCompleteCurrent(Extension, NULL, STATUS_SUCCESS, + &Extension->CurrentWriteRequest, + Extension->WriteQueue, NULL, + Extension->WriteRequestTotalTimer, + SerialStartWrite, SerialGetNextWrite, + SERIAL_REF_ISR); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "IsrWaitMask && (Extension->IsrWaitMask & SERIAL_EV_TXEMPTY) && + Extension->EmptiedTransmit && (!Extension->TransmitImmediate) && + (!Extension->CurrentWriteRequest) && IsQueueEmpty(Extension->WriteQueue)) { + + Extension->HistoryMask |= SERIAL_EV_TXEMPTY; + if (Extension->IrpMaskLocation) { + + *Extension->IrpMaskLocation = Extension->HistoryMask; + Extension->IrpMaskLocation = NULL; + Extension->HistoryMask = 0; + + SerialGetRequestContext(Extension->CurrentWaitRequest)->Information = sizeof(ULONG); + SerialInsertQueueDpc( + Extension->CommWaitDpc + ); + + } + + Extension->CountOfTryingToLowerRTS++; + SerialPerhapsLowerRTS(Extension->WdfInterrupt, Extension); + + } + + return FALSE; + +} + + +BOOLEAN +SerialGiveWriteToIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + Try to start off the write by slipping it in behind + a transmit immediate char, or if that isn't available + and the transmit holding register is empty, "tickle" + the UART into interrupting with a transmit buffer + empty. + + NOTE: This routine is called by WdfInterruptSynchronize. + + NOTE: This routine assumes that it is called with the + cancel spin lock held. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + // + // The current stack location. This contains all of the + // information we need to process this particular request. + // + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentWriteRequest); + + // + // We might have a xoff counter request masquerading as a + // write. The length of these requests will always be one + // and we can get a pointer to the actual character from + // the data supplied by the user. + // + + if (reqContext->MajorFunction == IRP_MJ_WRITE) { + + Extension->WriteLength = reqContext->Length; + Extension->WriteCurrentChar = reqContext->SystemBuffer; + + } else { + + Extension->WriteLength = 1; + Extension->WriteCurrentChar = + ((PUCHAR)reqContext->SystemBuffer) + + FIELD_OFFSET( + SERIAL_XOFF_COUNTER, + XoffChar + ); + + } + + // + // The isr now has a reference to the request. + // + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + // + // Check first to see if an immediate char is transmitting. + // If it is then we'll just slip in behind it when its + // done. + // + + if (!Extension->TransmitImmediate) { + + // + // If there is no immediate char transmitting then we + // will "re-enable" the transmit holding register empty + // interrupt. The 8250 family of devices will always + // signal a transmit holding register empty interrupt + // *ANY* time this bit is set to one. By doing things + // this way we can simply use the normal interrupt code + // to start off this write. + // + // We've been keeping track of whether the transmit holding + // register is empty so it we only need to do this + // if the register is empty. + // + + if (Extension->HoldingEmpty) { + + DISABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + ENABLE_ALL_INTERRUPTS(Extension, Extension->Controller); + + } + + } + + // + // The rts line may already be up from previous writes, + // however, it won't take much additional time to turn + // on the RTS line if we are doing transmit toggling. + // + + if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == + SERIAL_TRANSMIT_TOGGLE) { + + SerialSetRTS(Extension->WdfInterrupt, Extension); + + } + + return FALSE; + +} + + +VOID +SerialCancelCurrentWrite( + IN WDFREQUEST Request + ) + +/*++ + +Routine Description: + + This routine is used to cancel the current write. + +Arguments: + + Device - Wdf handle for the device + + Request - Pointer to the WDFREQUEST to be canceled. + +Return Value: + + None. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension; + WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); + + UNREFERENCED_PARAMETER(Request); + + Extension = SerialGetDeviceExtension(device); + + SerialTryToCompleteCurrent( + Extension, + SerialGrabWriteFromIsr, + STATUS_CANCELLED, + &Extension->CurrentWriteRequest, + Extension->WriteQueue, + NULL, + Extension->WriteRequestTotalTimer, + SerialStartWrite, + SerialGetNextWrite, + SERIAL_REF_CANCEL + ); + +} + + +VOID +SerialWriteTimeout( + IN WDFTIMER Timer + ) + +/*++ + +Routine Description: + + This routine will try to timeout the current write. + +Arguments: + +Return Value: + + None. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + Extension = SerialGetDeviceExtension(WdfTimerGetParentObject(Timer)); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, ">SerialWriteTimeout(%p)\n", + Extension); + + SerialTryToCompleteCurrent(Extension, SerialGrabWriteFromIsr, + STATUS_TIMEOUT, &Extension->CurrentWriteRequest, + Extension->WriteQueue, NULL, + Extension->WriteRequestTotalTimer, + SerialStartWrite, SerialGetNextWrite, + SERIAL_REF_TOTAL_TIMER); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "CurrentWriteRequest); + + // + // Check if the write length is non-zero. If it is non-zero + // then the ISR still owns the request. We calculate the the number + // of characters written and update the information field of the + // request with the characters written. We then clear the write length + // the isr sees. + // + + if (Extension->WriteLength) { + + // + // We could have an xoff counter masquerading as a + // write request. If so, don't update the write length. + // + + if (reqContext->MajorFunction == IRP_MJ_WRITE) { + + reqContext->Information = reqContext->Length -Extension->WriteLength; + + } else { + + reqContext->Information = 0; + + } + + // + // Since the isr no longer references this request, we can + // decrement it's reference count. + // + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + Extension->WriteLength = 0; + + } + + return FALSE; + +} + + +BOOLEAN +SerialGrabXoffFromIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This routine is used to grab an xoff counter request from the + isr when it is no longer masquerading as a write request. This + routine is called by the cancel and timeout code for the + xoff counter ioctl. + + + NOTE: This routine is being called from WdfInterruptSynchronize. + + NOTE: This routine assumes that the cancel spin lock is held + when this routine is called. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + Always false. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + + PREQUEST_CONTEXT reqContext; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentXoffRequest); + + if (Extension->CountSinceXoff) { + + // + // This is only non-zero when there actually is a Xoff ioctl + // counting down. + // + + Extension->CountSinceXoff = 0; + + // + // We decrement the count since the isr no longer owns + // the request. + // + + SERIAL_CLEAR_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + } + + return FALSE; + +} + + +VOID +SerialCompleteXoff( + IN WDFDPC Dpc + ) + +/*++ + +Routine Description: + + This routine is merely used to truely complete an xoff counter request. It + assumes that the status and the information fields of the request are + already correctly filled in. + +Arguments: + + Dpc - Not Used. + + DeferredContext - Really points to the device extension. + + SystemContext1 - Not Used. + + SystemContext2 - Not Used. + +Return Value: + + None. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = NULL; + + Extension = SerialGetDeviceExtension(WdfDpcGetParentObject(Dpc)); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, ">SerialCompleteXoff(%p)\n", + Extension); + + + SerialTryToCompleteCurrent(Extension, NULL, STATUS_SUCCESS, + &Extension->CurrentXoffRequest, NULL, NULL, + Extension->XoffCountTimer, NULL, NULL, + SERIAL_REF_ISR); + + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "SerialTimeoutXoff(%p)\n", Extension); + + SerialTryToCompleteCurrent(Extension, SerialGrabXoffFromIsr, + STATUS_SERIAL_COUNTER_TIMEOUT, + &Extension->CurrentXoffRequest, NULL, NULL, NULL, + NULL, NULL, SERIAL_REF_TOTAL_TIMER); + + SerialDbgPrintEx(TRACE_LEVEL_INFORMATION, DBG_WRITE, "CurrentXoffRequest, + NULL, + NULL, + Extension->XoffCountTimer, + NULL, + NULL, + SERIAL_REF_CANCEL + ); + +} + + +BOOLEAN +SerialGiveXoffToIsr( + IN WDFINTERRUPT Interrupt, + IN PVOID Context + ) + +/*++ + +Routine Description: + + + This routine starts off the xoff counter. It merely + has to set the xoff count and increment the reference + count to denote that the isr has a reference to the request. + + NOTE: This routine is called by WdfInterruptSynchronize. + + NOTE: This routine assumes that it is called with the + cancel spin lock held. + +Arguments: + + Context - Really a pointer to the device extension. + +Return Value: + + This routine always returns FALSE. + +--*/ + +{ + + PSERIAL_DEVICE_EXTENSION Extension = Context; + PREQUEST_CONTEXT reqContext; + PSERIAL_XOFF_COUNTER Xc = NULL; + + UNREFERENCED_PARAMETER(Interrupt); + + reqContext = SerialGetRequestContext(Extension->CurrentXoffRequest); + Xc = reqContext->SystemBuffer; + + // + // The current stack location. This contains all of the + // information we need to process this particular request. + // + + ASSERT(Extension->CurrentXoffRequest); + Extension->CountSinceXoff = Xc->Counter; + + // + // The isr now has a reference to the request. + // + + SERIAL_SET_REFERENCE( + reqContext, + SERIAL_REF_ISR + ); + + return FALSE; + +} + + diff --git a/tests/projects/windows/driver/kmdf/serial/xmake.lua b/tests/projects/windows/driver/kmdf/serial/xmake.lua new file mode 100644 index 000000000..53d59c650 --- /dev/null +++ b/tests/projects/windows/driver/kmdf/serial/xmake.lua @@ -0,0 +1,9 @@ +add_rules("mode.debug", "mode.release") + +target("wdfserial") + add_rules("wdk.env.kmdf", "wdk.driver") + add_values("wdk.tracewpp.flags", "-func:SerialDbgPrintEx(LEVEL,FLAGS,MSG,...)") + add_values("wdk.mc.header", "serlog.h") + add_files("*.c", {rule = "wdk.tracewpp"}) + add_files("*.mc", "*.rc", "*.inx") + diff --git a/tests/projects/windows/driver/umdf/echo/driver/device.c b/tests/projects/windows/driver/umdf/echo/driver/device.c new file mode 100644 index 000000000..bd522565f --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/driver/device.c @@ -0,0 +1,202 @@ +/*++ + +Copyright (c) 1990-2000 Microsoft Corporation + +Module Name: + + device.c - Device handling events for example driver. + +Abstract: + + This is a C version of a very simple sample driver that illustrates + how to use the driver framework and demonstrates best practices. + +--*/ + +#include "driver.h" + +NTSTATUS +EchoDeviceCreate( + PWDFDEVICE_INIT DeviceInit + ) +/*++ + +Routine Description: + + Worker routine called to create a device and its software resources. + +Arguments: + + DeviceInit - Pointer to an opaque init structure. Memory for this + structure will be freed by the framework when the WdfDeviceCreate + succeeds. So don't access the structure after that point. + +Return Value: + + NTSTATUS + +--*/ +{ + WDF_OBJECT_ATTRIBUTES deviceAttributes; + PDEVICE_CONTEXT deviceContext; + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; + WDFDEVICE device; + NTSTATUS status; + + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); + + // + // Register pnp/power callbacks so that we can start and stop the timer as the device + // gets started and stopped. + // + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = EchoEvtDeviceSelfManagedIoStart; + pnpPowerCallbacks.EvtDeviceSelfManagedIoSuspend = EchoEvtDeviceSelfManagedIoSuspend; + + #pragma prefast(suppress: 28024, "Function used for both Init and Restart Callbacks") + pnpPowerCallbacks.EvtDeviceSelfManagedIoRestart = EchoEvtDeviceSelfManagedIoStart; + + // + // Register the PnP and power callbacks. Power policy related callbacks will be registered + // later in SotwareInit. + // + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); + + status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); + + if (NT_SUCCESS(status)) { + // + // Get the device context and initialize it. WdfObjectGet_DEVICE_CONTEXT is an + // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the + // device.h header file. This function will do the type checking and return + // the device context. If you pass a wrong object handle + // it will return NULL and assert if run under framework verifier mode. + // + deviceContext = WdfObjectGet_DEVICE_CONTEXT(device); + deviceContext->PrivateDeviceData = 0; + + // + // Create a device interface so that application can find and talk + // to us. + // + status = WdfDeviceCreateDeviceInterface( + device, + &GUID_DEVINTERFACE_ECHO, + NULL // ReferenceString + ); + + if (NT_SUCCESS(status)) { + // + // Initialize the I/O Package and any Queues + // + status = EchoQueueInitialize(device); + } + } + + return status; +} + + +NTSTATUS +EchoEvtDeviceSelfManagedIoStart( + IN WDFDEVICE Device + ) +/*++ + +Routine Description: + + This event is called by the Framework when the device is started + or restarted after a suspend operation. + + This function is not marked pageable because this function is in the + device power up path. When a function is marked pagable and the code + section is paged out, it will generate a page fault which could impact + the fast resume behavior because the client driver will have to wait + until the system drivers can service this page fault. + +Arguments: + + Device - Handle to a framework device object. + +Return Value: + + NTSTATUS - Failures will result in the device stack being torn down. + +--*/ +{ + PQUEUE_CONTEXT queueContext = QueueGetContext(WdfDeviceGetDefaultQueue(Device)); + LARGE_INTEGER DueTime; + + KdPrint(("--> EchoEvtDeviceSelfManagedIoInit\n")); + + // + // Restart the queue and the periodic timer. We stopped them before going + // into low power state. + // + WdfIoQueueStart(WdfDeviceGetDefaultQueue(Device)); + + DueTime.QuadPart = WDF_REL_TIMEOUT_IN_MS(100); + + WdfTimerStart(queueContext->Timer, DueTime.QuadPart); + + KdPrint(( "<-- EchoEvtDeviceSelfManagedIoInit\n")); + + return STATUS_SUCCESS; +} + +NTSTATUS +EchoEvtDeviceSelfManagedIoSuspend( + IN WDFDEVICE Device + ) +/*++ + +Routine Description: + + This event is called by the Framework when the device is stopped + for resource rebalance or suspended when the system is entering + Sx state. + + +Arguments: + + Device - Handle to a framework device object. + +Return Value: + + NTSTATUS - The driver is not allowed to fail this function. If it does, the + device stack will be torn down. + +--*/ +{ + PQUEUE_CONTEXT queueContext = QueueGetContext(WdfDeviceGetDefaultQueue(Device)); + + PAGED_CODE(); + + KdPrint(("--> EchoEvtDeviceSelfManagedIoSuspend\n")); + + // + // Before we stop the timer we should make sure there are no outstanding + // i/o. We need to do that because framework cannot suspend the device + // if there are requests owned by the driver. There are two ways to solve + // this issue: 1) We can wait for the outstanding I/O to be complete by the + // periodic timer 2) Register EvtIoStop callback on the queue and acknowledge + // the request to inform the framework that it's okay to suspend the device + // with outstanding I/O. In this sample we will use the 1st approach + // because it's pretty easy to do. We will restart the queue when the + // device is restarted. + // + WdfIoQueueStopSynchronously(WdfDeviceGetDefaultQueue(Device)); + + // + // Stop the watchdog timer and wait for DPC to run to completion if it's already fired. + // + WdfTimerStop(queueContext->Timer, TRUE); + + KdPrint(( "<-- EchoEvtDeviceSelfManagedIoSuspend\n")); + + return STATUS_SUCCESS; +} + + + diff --git a/tests/projects/windows/driver/umdf/echo/driver/device.h b/tests/projects/windows/driver/umdf/echo/driver/device.h new file mode 100644 index 000000000..1e2c1f28e --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/driver/device.h @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 1990-2000 Microsoft Corporation + +Module Name: + + device.h + +Abstract: + + This is a C version of a very simple sample driver that illustrates + how to use the driver framework and demonstrates best practices. + +--*/ + +#include "public.h" + +// +// The device context performs the same job as +// a WDM device extension in the driver frameworks +// +typedef struct _DEVICE_CONTEXT +{ + ULONG PrivateDeviceData; // just a placeholder + +} DEVICE_CONTEXT, *PDEVICE_CONTEXT; + +// +// This macro will generate an inline function called WdfObjectGet_DEVICE_CONTEXT +// which will be used to get a pointer to the device context memory +// in a type safe manner. +// +WDF_DECLARE_CONTEXT_TYPE(DEVICE_CONTEXT) + +// +// Function to initialize the device and its callbacks +// +NTSTATUS +EchoDeviceCreate( + PWDFDEVICE_INIT DeviceInit + ); + +// +// Device events +// +EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT EchoEvtDeviceSelfManagedIoStart; +EVT_WDF_DEVICE_SELF_MANAGED_IO_SUSPEND EchoEvtDeviceSelfManagedIoSuspend; + diff --git a/tests/projects/windows/driver/umdf/echo/driver/driver.c b/tests/projects/windows/driver/umdf/echo/driver/driver.c new file mode 100644 index 000000000..2835aa1dd --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/driver/driver.c @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 1990-2000 Microsoft Corporation + +Module Name: + + driver.c + +Abstract: + + This driver demonstrates use of a default I/O Queue, its + request start events, cancellation event, and a synchronized DPC. + + To demonstrate asynchronous operation, the I/O requests are not completed + immediately, but stored in the drivers private data structure, and a timer + will complete it next time the Timer callback runs. + + During the time the request is waiting for the timer callback to run, it is + made cancellable by the call WdfRequestMarkCancelable. This + allows the test program to cancel the request and exit instantly. + + This rather complicated set of events is designed to demonstrate + the driver frameworks synchronization of access to a device driver + data structure, and a pointer which can be a proxy for device hardware + registers or resources. + + This common data structure, or resource is accessed by new request + events arriving, the Timer callback that completes it, and cancel processing. + + Notice the lack of specific lock/unlock operations. + + Even though this example utilizes a serial queue, a parallel queue + would not need any additional explicit synchronization, just a + strategy for managing multiple requests outstanding. + +--*/ + +#include "driver.h" + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + DriverEntry initializes the driver and is the first routine called by the + system after the driver is loaded. DriverEntry specifies the other entry + points in the function driver, such as EvtDevice and DriverUnload. + +Parameters Description: + + DriverObject - represents the instance of the function driver that is loaded + into memory. DriverEntry must initialize members of DriverObject before it + returns to the caller. DriverObject is allocated by the system before the + driver is loaded, and it is released by the system after the system unloads + the function driver from memory. + + RegistryPath - represents the driver specific path in the Registry. + The function driver can use the path to store driver related data between + reboots. The path does not store hardware instance specific data. + +Return Value: + + STATUS_SUCCESS if successful, + STATUS_UNSUCCESSFUL otherwise. + +--*/ +{ + WDF_DRIVER_CONFIG config; + NTSTATUS status; + + WDF_DRIVER_CONFIG_INIT(&config, + EchoEvtDeviceAdd + ); + + status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &config, + WDF_NO_HANDLE); + if (!NT_SUCCESS(status)) { + KdPrint(("Error: WdfDriverCreate failed 0x%x\n", status)); + return status; + } + +#if DBG + EchoPrintDriverVersion(); +#endif + + return status; +} + +NTSTATUS +EchoEvtDeviceAdd( + IN WDFDRIVER Driver, + IN PWDFDEVICE_INIT DeviceInit + ) +/*++ +Routine Description: + + EvtDeviceAdd is called by the framework in response to AddDevice + call from the PnP manager. We create and initialize a device object to + represent a new instance of the device. + +Arguments: + + Driver - Handle to a framework driver object created in DriverEntry + + DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status; + + UNREFERENCED_PARAMETER(Driver); + + KdPrint(("Enter EchoEvtDeviceAdd\n")); + + status = EchoDeviceCreate(DeviceInit); + + return status; +} + +NTSTATUS +EchoPrintDriverVersion( + ) +/*++ +Routine Description: + + This routine shows how to retrieve framework version string and + also how to find out to which version of framework library the + client driver is bound to. + +Arguments: + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS status; + WDFSTRING string; + UNICODE_STRING us; + WDF_DRIVER_VERSION_AVAILABLE_PARAMS ver; + + // + // 1) Retreive version string and print that in the debugger. + // + status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &string); + if (!NT_SUCCESS(status)) { + KdPrint(("Error: WdfStringCreate failed 0x%x\n", status)); + return status; + } + + status = WdfDriverRetrieveVersionString(WdfGetDriver(), string); + if (!NT_SUCCESS(status)) { + // + // No need to worry about delete the string object because + // by default it's parented to the driver and it will be + // deleted when the driverobject is deleted when the DriverEntry + // returns a failure status. + // + KdPrint(("Error: WdfDriverRetrieveVersionString failed 0x%x\n", status)); + return status; + } + + WdfStringGetUnicodeString(string, &us); + KdPrint(("Echo Sample %wZ\n", &us)); + + WdfObjectDelete(string); + string = NULL; // To avoid referencing a deleted object. + + // + // 2) Find out to which version of framework this driver is bound to. + // + WDF_DRIVER_VERSION_AVAILABLE_PARAMS_INIT(&ver, 1, 0); + if (WdfDriverIsVersionAvailable(WdfGetDriver(), &ver) == TRUE) { + KdPrint(("Yes, framework version is 1.0\n")); + }else { + KdPrint(("No, framework verison is not 1.0\n")); + } + + return STATUS_SUCCESS; +} + diff --git a/tests/projects/windows/driver/umdf/echo/driver/driver.h b/tests/projects/windows/driver/umdf/echo/driver/driver.h new file mode 100644 index 000000000..6539d6cf5 --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/driver/driver.h @@ -0,0 +1,46 @@ +/*++ + +Copyright (c) 1990-2000 Microsoft Corporation + +Module Name: + + driver.h + +Abstract: + + This is a C version of a very simple sample driver that illustrates + how to use the driver framework and demonstrates best practices. + +--*/ + +#define INITGUID + +#include +#include +#include "device.h" +#include "queue.h" + +#ifndef ASSERT +#if DBG +#define ASSERT( exp ) \ + ((!(exp)) ? \ + (KdPrint(( "\n*** Assertion failed: " #exp "\n\n")), \ + DebugBreak(), \ + FALSE) : \ + TRUE) +#else +#define ASSERT( exp ) +#endif // DBG +#endif // ASSERT + +// +// WDFDRIVER Events +// + +DRIVER_INITIALIZE DriverEntry; +EVT_WDF_DRIVER_DEVICE_ADD EchoEvtDeviceAdd; + +NTSTATUS +EchoPrintDriverVersion( + ); + diff --git a/tests/projects/windows/driver/umdf/echo/driver/echoum.inx b/tests/projects/windows/driver/umdf/echo/driver/echoum.inx new file mode 100644 index 000000000..cae8b45fe Binary files /dev/null and b/tests/projects/windows/driver/umdf/echo/driver/echoum.inx differ diff --git a/tests/projects/windows/driver/umdf/echo/driver/queue.c b/tests/projects/windows/driver/umdf/echo/driver/queue.c new file mode 100644 index 000000000..e0f3d7b6b --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/driver/queue.c @@ -0,0 +1,538 @@ +/*++ + +Copyright (c) 1990-2000 Microsoft Corporation + +Module Name: + + queue.c + +Abstract: + + This is a C version of a very simple sample driver that illustrates + how to use the driver framework and demonstrates best practices. + +--*/ + +#include "driver.h" + +NTSTATUS +EchoQueueInitialize( + WDFDEVICE Device + ) +/*++ + +Routine Description: + + + The I/O dispatch callbacks for the frameworks device object + are configured in this function. + + A single default I/O Queue is configured for serial request + processing, and a driver context memory allocation is created + to hold our structure QUEUE_CONTEXT. + + This memory may be used by the driver automatically synchronized + by the Queue's presentation lock. + + The lifetime of this memory is tied to the lifetime of the I/O + Queue object, and we register an optional destructor callback + to release any private allocations, and/or resources. + + +Arguments: + + Device - Handle to a framework device object. + +Return Value: + + NTSTATUS + +--*/ +{ + WDFQUEUE queue; + NTSTATUS status; + PQUEUE_CONTEXT queueContext; + WDF_IO_QUEUE_CONFIG queueConfig; + WDF_OBJECT_ATTRIBUTES queueAttributes; + + // + // Configure a default queue so that requests that are not + // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto + // other queues get dispatched here. + // + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( + &queueConfig, + WdfIoQueueDispatchSequential + ); + + queueConfig.EvtIoRead = EchoEvtIoRead; + queueConfig.EvtIoWrite = EchoEvtIoWrite; + + // + // Fill in a callback for destroy, and our QUEUE_CONTEXT size + // + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_CONTEXT); + + // + // Set synchronization scope on queue and have the timer to use queue as + // the parent object so that queue and timer callbacks are synchronized + // with the same lock. + // + queueAttributes.SynchronizationScope = WdfSynchronizationScopeQueue; + + queueAttributes.EvtDestroyCallback = EchoEvtIoQueueContextDestroy; + + status = WdfIoQueueCreate( + Device, + &queueConfig, + &queueAttributes, + &queue + ); + + if( !NT_SUCCESS(status) ) { + KdPrint(("WdfIoQueueCreate failed 0x%x\n",status)); + return status; + } + + // Get our Driver Context memory from the returned Queue handle + queueContext = QueueGetContext(queue); + + queueContext->WriteMemory = NULL; + queueContext->Timer = NULL; + + queueContext->CurrentRequest = NULL; + queueContext->CurrentStatus = STATUS_INVALID_DEVICE_REQUEST; + + // + // Create the Queue timer + // + status = EchoTimerCreate(&queueContext->Timer, queue); + if (!NT_SUCCESS(status)) { + KdPrint(("Error creating timer 0x%x\n",status)); + return status; + } + + return status; +} + + +NTSTATUS +EchoTimerCreate( + IN WDFTIMER* Timer, + IN WDFQUEUE Queue + ) +/*++ + +Routine Description: + + Subroutine to create timer. By associating the timerobject with + the queue, we are basically telling the framework to serialize the queue + callbacks with the timer callback. By doing so, we don't have to worry + about protecting queue-context structure from multiple threads accessing + it simultaneously. + +Arguments: + + +Return Value: + + NTSTATUS + +--*/ +{ + NTSTATUS Status; + WDF_TIMER_CONFIG timerConfig; + WDF_OBJECT_ATTRIBUTES timerAttributes; + + // + // Create a non-periodic timer since WDF does not allow periodic timer + // at passive level, which is the level UMDF callbacks are invoked at. + // The workaround is to always restart the timer in the timer callback. + // + // WDF_TIMER_CONFIG_INIT sets AutomaticSerialization to TRUE by default. + // + WDF_TIMER_CONFIG_INIT(&timerConfig, EchoEvtTimerFunc); + + WDF_OBJECT_ATTRIBUTES_INIT(&timerAttributes); + timerAttributes.ParentObject = Queue; // Synchronize with the I/O Queue + timerAttributes.ExecutionLevel = WdfExecutionLevelPassive; + + Status = WdfTimerCreate(&timerConfig, + &timerAttributes, + Timer // Output handle + ); + + return Status; +} + + + +VOID +EchoEvtIoQueueContextDestroy( + WDFOBJECT Object +) +/*++ + +Routine Description: + + This is called when the Queue that our driver context memory + is associated with is destroyed. + +Arguments: + + Context - Context that's being freed. + +Return Value: + + VOID + +--*/ +{ + PQUEUE_CONTEXT queueContext = QueueGetContext(Object); + + // + // Release any resources pointed to in the queue context. + // + // The body of the queue context will be released after + // this callback handler returns + // + + // + // If Queue context has an I/O buffer, release it + // + if( queueContext->WriteMemory != NULL ) { + WdfObjectDelete(queueContext->WriteMemory); + queueContext->WriteMemory = NULL; + } + + return; +} + + +VOID +EchoEvtRequestCancel( + IN WDFREQUEST Request + ) +/*++ + +Routine Description: + + + Called when an I/O request is cancelled after the driver has marked + the request cancellable. This callback is automatically synchronized + with the I/O callbacks since we have chosen to use frameworks Device + level locking. + +Arguments: + + Request - Request being cancelled. + +Return Value: + + VOID + +--*/ +{ + PQUEUE_CONTEXT queueContext = QueueGetContext(WdfRequestGetIoQueue(Request)); + + KdPrint(("EchoEvtRequestCancel called on Request 0x%p\n", Request)); + + // + // The following is race free by the callside or DPC side + // synchronizing completion by calling + // WdfRequestMarkCancelable(Queue, Request, FALSE) before + // completion and not calling WdfRequestComplete if the + // return status == STATUS_CANCELLED. + // + WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); + + // + // This book keeping is synchronized by the common + // Queue presentation lock + // + ASSERT(queueContext->CurrentRequest == Request); + queueContext->CurrentRequest = NULL; + + return; +} + +VOID +EchoEvtIoRead( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t Length + ) +/*++ + +Routine Description: + + This event is called when the framework receives IRP_MJ_READ request. + It will copy the content from the queue-context buffer to the request buffer. + If the driver hasn't received any write request earlier, the read returns zero. + +Arguments: + + Queue - Handle to the framework queue object that is associated with the + I/O request. + + Request - Handle to a framework request object. + + Length - number of bytes to be read. + The default property of the queue is to not dispatch + zero lenght read & write requests to the driver and + complete is with status success. So we will never get + a zero length request. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS Status; + PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); + WDFMEMORY memory; + size_t writeMemoryLength; + + _Analysis_assume_(Length > 0); + + KdPrint(("EchoEvtIoRead Called! Queue 0x%p, Request 0x%p Length %d\n", + Queue,Request,Length)); + // + // No data to read + // + if( (queueContext->WriteMemory == NULL) ) { + WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)0L); + return; + } + + // + // Read what we have + // + WdfMemoryGetBuffer(queueContext->WriteMemory, &writeMemoryLength); + _Analysis_assume_(writeMemoryLength > 0); + + if( writeMemoryLength < Length ) { + Length = writeMemoryLength; + } + + // + // Get the request memory + // + Status = WdfRequestRetrieveOutputMemory(Request, &memory); + if( !NT_SUCCESS(Status) ) { + KdPrint(("EchoEvtIoRead Could not get request memory buffer 0x%x\n", Status)); + WdfVerifierDbgBreakPoint(); + WdfRequestCompleteWithInformation(Request, Status, 0L); + return; + } + + // Copy the memory out + Status = WdfMemoryCopyFromBuffer( memory, // destination + 0, // offset into the destination memory + WdfMemoryGetBuffer(queueContext->WriteMemory, NULL), + Length ); + if( !NT_SUCCESS(Status) ) { + KdPrint(("EchoEvtIoRead: WdfMemoryCopyFromBuffer failed 0x%x\n", Status)); + WdfRequestComplete(Request, Status); + return; + } + + // Set transfer information + WdfRequestSetInformation(Request, (ULONG_PTR)Length); + + // Mark the request is cancelable + WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); + + + // Defer the completion to another thread from the timer dpc + queueContext->CurrentRequest = Request; + queueContext->CurrentStatus = Status; + + return; +} + +VOID +EchoEvtIoWrite( + IN WDFQUEUE Queue, + IN WDFREQUEST Request, + IN size_t Length + ) +/*++ + +Routine Description: + + This event is invoked when the framework receives IRP_MJ_WRITE request. + This routine allocates memory buffer, copies the data from the request to it, + and stores the buffer pointer in the queue-context with the length variable + representing the buffers length. The actual completion of the request + is defered to the periodic timer dpc. + +Arguments: + + Queue - Handle to the framework queue object that is associated with the + I/O request. + + Request - Handle to a framework request object. + + Length - number of bytes to be read. + The default property of the queue is to not dispatch + zero lenght read & write requests to the driver and + complete is with status success. So we will never get + a zero length request. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS Status; + WDFMEMORY memory; + PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); + PVOID writeBuffer = NULL; + + _Analysis_assume_(Length > 0); + + KdPrint(("EchoEvtIoWrite Called! Queue 0x%p, Request 0x%p Length %d\n", + Queue,Request,Length)); + + if( Length > MAX_WRITE_LENGTH ) { + KdPrint(("EchoEvtIoWrite Buffer Length to big %d, Max is %d\n", + Length,MAX_WRITE_LENGTH)); + WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_OVERFLOW, 0L); + return; + } + + // Get the memory buffer + Status = WdfRequestRetrieveInputMemory(Request, &memory); + if( !NT_SUCCESS(Status) ) { + KdPrint(("EchoEvtIoWrite Could not get request memory buffer 0x%x\n", + Status)); + WdfVerifierDbgBreakPoint(); + WdfRequestComplete(Request, Status); + return; + } + + // Release previous buffer if set + if( queueContext->WriteMemory != NULL ) { + WdfObjectDelete(queueContext->WriteMemory); + queueContext->WriteMemory = NULL; + } + + Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, + NonPagedPoolNx, + 'sam1', + Length, + &queueContext->WriteMemory, + &writeBuffer + ); + + if(!NT_SUCCESS(Status)) { + KdPrint(("EchoEvtIoWrite: Could not allocate %d byte buffer\n", Length)); + WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); + return; + } + + + // Copy the memory in + Status = WdfMemoryCopyToBuffer( memory, + 0, // offset into the source memory + writeBuffer, + Length ); + if( !NT_SUCCESS(Status) ) { + KdPrint(("EchoEvtIoWrite WdfMemoryCopyToBuffer failed 0x%x\n", Status)); + WdfVerifierDbgBreakPoint(); + + WdfObjectDelete(queueContext->WriteMemory); + queueContext->WriteMemory = NULL; + + WdfRequestComplete(Request, Status); + return; + } + + // Set transfer information + WdfRequestSetInformation(Request, (ULONG_PTR)Length); + + // Specify the request is cancelable + WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); + + // Defer the completion to another thread from the timer dpc + queueContext->CurrentRequest = Request; + queueContext->CurrentStatus = Status; + + return; +} + + +VOID +EchoEvtTimerFunc( + IN WDFTIMER Timer + ) +/*++ + +Routine Description: + + This is the TimerDPC the driver sets up to complete requests. + This function is registered when the WDFTIMER object is created, and + will automatically synchronize with the I/O Queue callbacks + and cancel routine. + +Arguments: + + Timer - Handle to a framework Timer object. + +Return Value: + + VOID + +--*/ +{ + NTSTATUS Status; + WDFREQUEST Request; + WDFQUEUE queue; + PQUEUE_CONTEXT queueContext ; + + queue = WdfTimerGetParentObject(Timer); + queueContext = QueueGetContext(queue); + + // + // DPC is automatically synchronized to the Queue lock, + // so this is race free without explicit driver managed locking. + // + Request = queueContext->CurrentRequest; + if( Request != NULL ) { + + // + // Attempt to remove cancel status from the request. + // + // The request is not completed if it is already cancelled + // since the EchoEvtIoCancel function has run, or is about to run + // and we are racing with it. + // + Status = WdfRequestUnmarkCancelable(Request); + if( Status != STATUS_CANCELLED ) { + + queueContext->CurrentRequest = NULL; + Status = queueContext->CurrentStatus; + + KdPrint(("CustomTimerDPC Completing request 0x%p, Status 0x%x \n", Request,Status)); + + WdfRequestComplete(Request, Status); + } + else { + KdPrint(("CustomTimerDPC Request 0x%p is STATUS_CANCELLED, not completing\n", + Request)); + } + } + + // + // Restart the Timer since WDF does not allow periodic timer + // with autosynchronization at passive level + // + WdfTimerStart(Timer, WDF_REL_TIMEOUT_IN_MS(TIMER_PERIOD)); + + return; +} + + diff --git a/tests/projects/windows/driver/umdf/echo/driver/queue.h b/tests/projects/windows/driver/umdf/echo/driver/queue.h new file mode 100644 index 000000000..5c04dc8f7 --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/driver/queue.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 1990-2000 Microsoft Corporation + +Module Name: + + queue.h + +Abstract: + + This is a C version of a very simple sample driver that illustrates + how to use the driver framework and demonstrates best practices. + +--*/ + +// Set max write length for testing +#define MAX_WRITE_LENGTH 1024*40 + +// Set timer period in ms +#define TIMER_PERIOD 1000*2 + +// +// This is the context that can be placed per queue +// and would contain per queue information. +// +typedef struct _QUEUE_CONTEXT { + + // Here we allocate a buffer from a test write so it can be read back + WDFMEMORY WriteMemory; + + // Timer DPC for this queue + WDFTIMER Timer; + + // Virtual I/O + WDFREQUEST CurrentRequest; + NTSTATUS CurrentStatus; + +} QUEUE_CONTEXT, *PQUEUE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(QUEUE_CONTEXT, QueueGetContext) + +NTSTATUS +EchoQueueInitialize( + WDFDEVICE hDevice + ); + +EVT_WDF_IO_QUEUE_CONTEXT_DESTROY_CALLBACK EchoEvtIoQueueContextDestroy; + +// +// Events from the IoQueue object +// +EVT_WDF_REQUEST_CANCEL EchoEvtRequestCancel; +EVT_WDF_IO_QUEUE_IO_READ EchoEvtIoRead; +EVT_WDF_IO_QUEUE_IO_WRITE EchoEvtIoWrite; + +NTSTATUS +EchoTimerCreate( + IN WDFTIMER* pTimer, + IN WDFQUEUE Queue + ); + +EVT_WDF_TIMER EchoEvtTimerFunc; diff --git a/tests/projects/windows/driver/umdf/echo/exe/echoapp.cpp b/tests/projects/windows/driver/umdf/echo/exe/echoapp.cpp new file mode 100644 index 000000000..47c0ae0a1 --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/exe/echoapp.cpp @@ -0,0 +1,652 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + EchoApp.cpp + +Abstract: + + An application to exercise the WDF "echo" sample driver. + + +Environment: + + user mode only + +--*/ + + +#include +_Analysis_mode_(_Analysis_code_type_user_code_) + +#define INITGUID + +#include +#include +#include +#include +#include +#include "public.h" + +#define NUM_ASYNCH_IO 100 +#define BUFFER_SIZE (40*1024) + +#define READER_TYPE 1 +#define WRITER_TYPE 2 + +#define MAX_DEVPATH_LENGTH 256 + +BOOLEAN G_PerformAsyncIo; +BOOLEAN G_LimitedLoops; +ULONG G_AsyncIoLoopsNum; +WCHAR G_DevicePath[MAX_DEVPATH_LENGTH]; + + +ULONG +AsyncIo( + PVOID ThreadParameter + ); + +BOOLEAN +PerformWriteReadTest( + IN HANDLE hDevice, + IN ULONG TestLength + ); + +BOOL +GetDevicePath( + IN LPGUID InterfaceGuid, + _Out_writes_(BufLen) PWCHAR DevicePath, + _In_ size_t BufLen + ); + + +int __cdecl +main( + _In_ int argc, + _In_reads_(argc) char* argv[] + ) +{ + HANDLE hDevice = INVALID_HANDLE_VALUE; + HANDLE th1 = NULL; + BOOLEAN result = TRUE; + + + if (argc > 1) { + if(!_strnicmp (argv[1], "-Async", 6) ) { + G_PerformAsyncIo = TRUE; + if (argc > 2) { + G_AsyncIoLoopsNum = atoi(argv[2]); + G_LimitedLoops = TRUE; + } + else { + G_LimitedLoops = FALSE; + } + + } else { + printf("Usage:\n"); + printf(" Echoapp.exe --- Send single write and read request synchronously\n"); + printf(" Echoapp.exe -Async --- Send reads and writes asynchronously without terminating\n"); + printf(" Echoapp.exe -Async --- Send reads and writes asynchronously\n"); + printf("Exit the app anytime by pressing Ctrl-C\n"); + result = FALSE; + goto exit; + } + } + + if ( !GetDevicePath( + (LPGUID) &GUID_DEVINTERFACE_ECHO, + G_DevicePath, + sizeof(G_DevicePath)/sizeof(G_DevicePath[0])) ) + { + result = FALSE; + goto exit; + } + + printf("DevicePath: %ws\n", G_DevicePath); + + hDevice = CreateFile(G_DevicePath, + GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL ); + + if (hDevice == INVALID_HANDLE_VALUE) { + printf("Failed to open device. Error %d\n",GetLastError()); + result = FALSE; + goto exit; + } + + printf("Opened device successfully\n"); + + if(G_PerformAsyncIo) { + + printf("Starting AsyncIo\n"); + + // + // Create a reader thread + // + th1 = CreateThread( NULL, // Default Security Attrib. + 0, // Initial Stack Size, + (LPTHREAD_START_ROUTINE) AsyncIo, // Thread Func + (LPVOID)READER_TYPE, + 0, // Creation Flags + NULL ); // Don't need the Thread Id. + + if (th1 == NULL) { + printf("Couldn't create reader thread - error %d\n", GetLastError()); + result = FALSE; + goto exit; + } + + // + // Use this thread for peforming write. + // + result = (BOOLEAN)AsyncIo((PVOID)WRITER_TYPE); + + }else { + // + // Write pattern buffers and read them back, then verify them + // + result = PerformWriteReadTest(hDevice, 512); + if(!result) { + goto exit; + } + + result = PerformWriteReadTest(hDevice, 30*1024); + if(!result) { + goto exit; + } + + } + +exit: + + if (th1 != NULL) { + WaitForSingleObject(th1, INFINITE); + CloseHandle(th1); + } + + if (hDevice != INVALID_HANDLE_VALUE) { + CloseHandle(hDevice); + } + + return ((result == TRUE) ? 0 : 1); + +} + +PUCHAR +CreatePatternBuffer( + IN ULONG Length + ) +{ + unsigned int i; + PUCHAR p, pBuf; + + pBuf = (PUCHAR)malloc(Length); + if( pBuf == NULL ) { + printf("Could not allocate %d byte buffer\n",Length); + return NULL; + } + + p = pBuf; + + for(i=0; i < Length; i++ ) { + *p = (UCHAR)i; + p++; + } + + return pBuf; +} + +BOOLEAN +VerifyPatternBuffer( + _In_reads_bytes_(Length) PUCHAR pBuffer, + _In_ ULONG Length + ) +{ + unsigned int i; + PUCHAR p = pBuffer; + + for( i=0; i < Length; i++ ) { + + if( *p != (UCHAR)(i & 0xFF) ) { + printf("Pattern changed. SB 0x%x, Is 0x%x\n", + (UCHAR)(i & 0xFF), *p); + return FALSE; + } + + p++; + } + + return TRUE; +} + +BOOLEAN +PerformWriteReadTest( + IN HANDLE hDevice, + IN ULONG TestLength + ) +/* +*/ +{ + ULONG bytesReturned =0; + PUCHAR WriteBuffer = NULL, + ReadBuffer = NULL; + BOOLEAN result = TRUE; + + WriteBuffer = CreatePatternBuffer(TestLength); + if( WriteBuffer == NULL ) { + + result = FALSE; + goto Cleanup; + } + + ReadBuffer = (PUCHAR)malloc(TestLength); + if( ReadBuffer == NULL ) { + + printf("PerformWriteReadTest: Could not allocate %d " + "bytes ReadBuffer\n",TestLength); + + result = FALSE; + goto Cleanup; + + } + + // + // Write the pattern to the device + // + bytesReturned = 0; + + if (!WriteFile ( hDevice, + WriteBuffer, + TestLength, + &bytesReturned, + NULL)) { + + printf ("PerformWriteReadTest: WriteFile failed: " + "Error %d\n", GetLastError()); + + result = FALSE; + goto Cleanup; + + } else { + + if( bytesReturned != TestLength ) { + + printf("bytes written is not test length! Written %d, " + "SB %d\n",bytesReturned, TestLength); + + result = FALSE; + goto Cleanup; + } + + printf ("%d Pattern Bytes Written successfully\n", + bytesReturned); + } + + bytesReturned = 0; + + if ( !ReadFile (hDevice, + ReadBuffer, + TestLength, + &bytesReturned, + NULL)) { + + printf ("PerformWriteReadTest: ReadFile failed: " + "Error %d\n", GetLastError()); + + result = FALSE; + goto Cleanup; + + } else { + + if( bytesReturned != TestLength ) { + + printf("bytes Read is not test length! Read %d, " + "SB %d\n",bytesReturned, TestLength); + + // + // Note: Is this a Failure Case?? + // + result = FALSE; + goto Cleanup; + } + + printf ("%d Pattern Bytes Read successfully\n",bytesReturned); + } + + // + // Now compare + // + if( !VerifyPatternBuffer(ReadBuffer, TestLength) ) { + + printf("Verify failed\n"); + + result = FALSE; + goto Cleanup; + } + + printf("Pattern Verified successfully\n"); + +Cleanup: + + // + // Free WriteBuffer if non NULL. + // + if (WriteBuffer) { + free (WriteBuffer); + } + + // + // Free ReadBuffer if non NULL + // + if (ReadBuffer) { + free (ReadBuffer); + } + + return result; +} + +ULONG +AsyncIo( + PVOID ThreadParameter + ) +{ + HANDLE hDevice = INVALID_HANDLE_VALUE; + HANDLE hCompletionPort = NULL; + OVERLAPPED *pOvList = NULL; + PUCHAR buf = NULL; + ULONG numberOfBytesTransferred; + OVERLAPPED *completedOv; + ULONG_PTR i; + ULONG ioType = (ULONG)(ULONG_PTR)ThreadParameter; + ULONG_PTR key; + ULONG error; + BOOLEAN result = TRUE; + ULONG maxPendingRequests = NUM_ASYNCH_IO; + ULONG remainingRequestsToSend = 0; + ULONG remainingRequestsToReceive = 0; + + hDevice = CreateFile(G_DevicePath, + GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL ); + + + if (hDevice == INVALID_HANDLE_VALUE) { + printf("Cannot open %ws error %d\n", G_DevicePath, GetLastError()); + result = FALSE; + goto Error; + } + + hCompletionPort = CreateIoCompletionPort(hDevice, NULL, 1, 0); + if (hCompletionPort == NULL) { + printf("Cannot open completion port %d \n",GetLastError()); + result = FALSE; + goto Error; + } + + // + // We will only have NUM_ASYNCH_IO or G_AsyncIoLoopsNum pending at any + // time (whichever is less) + // + if (G_LimitedLoops == TRUE) { + remainingRequestsToReceive = G_AsyncIoLoopsNum; + if (G_AsyncIoLoopsNum > NUM_ASYNCH_IO) { + // + // After we send the initial NUM_ASYNCH_IO, we will have additional + // (G_AsyncIoLoopsNum - NUM_ASYNCH_IO) I/Os to send + // + maxPendingRequests = NUM_ASYNCH_IO; + remainingRequestsToSend = G_AsyncIoLoopsNum - NUM_ASYNCH_IO; + } + else { + maxPendingRequests = G_AsyncIoLoopsNum; + remainingRequestsToSend = 0; + + } + } + + pOvList = (OVERLAPPED *)malloc(maxPendingRequests * sizeof(OVERLAPPED)); + if (pOvList == NULL) { + printf("Cannot allocate overlapped array \n"); + result = FALSE; + goto Error; + } + + buf = (PUCHAR)malloc(maxPendingRequests * BUFFER_SIZE); + if (buf == NULL) { + printf("Cannot allocate buffer \n"); + result = FALSE; + goto Error; + } + + ZeroMemory(pOvList, maxPendingRequests * sizeof(OVERLAPPED)); + ZeroMemory(buf, maxPendingRequests * BUFFER_SIZE); + + // + // Issue asynch I/O + // + + for (i = 0; i < maxPendingRequests; i++) { + if (ioType == READER_TYPE) { + if ( ReadFile( hDevice, + buf + (i* BUFFER_SIZE), + BUFFER_SIZE, + NULL, + &pOvList[i]) == 0) { + + error = GetLastError(); + if (error != ERROR_IO_PENDING) { + printf(" %dth Read failed %d \n", (ULONG) i, GetLastError()); + result = FALSE; + goto Error; + } + } + + } else { + if ( WriteFile( hDevice, + buf + (i* BUFFER_SIZE), + BUFFER_SIZE, + NULL, + &pOvList[i]) == 0) { + error = GetLastError(); + if (error != ERROR_IO_PENDING) { + printf(" %dth Write failed %d \n", (ULONG) i, GetLastError()); + result = FALSE; + goto Error; + } + } + } + } + + // + // Wait for the I/Os to complete. If one completes then reissue the I/O + // + + WHILE (1) { + + if ( GetQueuedCompletionStatus(hCompletionPort, &numberOfBytesTransferred, &key, &completedOv, INFINITE) == 0) { + printf("GetQueuedCompletionStatus failed %d\n", GetLastError()); + result = FALSE; + goto Error; + } + + // + // Read successfully completed. If we're doing unlimited I/Os then Issue another one. + // + + if (ioType == READER_TYPE) { + + i = completedOv - pOvList; + printf("Number of bytes read by request number %Id is %d\n", i, numberOfBytesTransferred); + + // + // If we're done with the I/Os, then exit + // + if (G_LimitedLoops == TRUE) { + if ((--remainingRequestsToReceive) == 0) { + break; + } + + if (remainingRequestsToSend == 0) { + continue; + } + else { + remainingRequestsToSend--; + } + } + + + if ( ReadFile( hDevice, + buf + (i * BUFFER_SIZE), + BUFFER_SIZE, + NULL, + completedOv) == 0) { + error = GetLastError(); + if (error != ERROR_IO_PENDING) { + printf("%Idth Read failed %d \n", i, GetLastError()); + result = FALSE; + goto Error; + } + } + } else { + + i = completedOv - pOvList; + + printf("Number of bytes written by request number %Id is %d\n", i, numberOfBytesTransferred); + + // + // If we're done with the I/Os, then exit + // + if (G_LimitedLoops == TRUE) { + if ((--remainingRequestsToReceive) == 0) { + break; + } + + if (remainingRequestsToSend == 0) { + continue; + } + else { + remainingRequestsToSend--; + } + } + + + if ( WriteFile( hDevice, + buf + (i * BUFFER_SIZE), + BUFFER_SIZE, + NULL, + completedOv) == 0) { + error = GetLastError(); + if (error != ERROR_IO_PENDING) { + + printf("%Idth write failed %d \n", i, GetLastError()); + result = FALSE; + goto Error; + } + } + } + } + +Error: + if(hDevice != INVALID_HANDLE_VALUE) { + CloseHandle(hDevice); + } + + if(hCompletionPort) { + CloseHandle(hCompletionPort); + } + + if(buf) { + free(buf); + } + if(pOvList) { + free(pOvList); + } + + return (ULONG)result; + +} + +BOOL +GetDevicePath( + _In_ LPGUID InterfaceGuid, + _Out_writes_(BufLen) PWCHAR DevicePath, + _In_ size_t BufLen + ) +{ + CONFIGRET cr = CR_SUCCESS; + PWSTR deviceInterfaceList = NULL; + ULONG deviceInterfaceListLength = 0; + PWSTR nextInterface; + HRESULT hr = E_FAIL; + BOOL bRet = TRUE; + + cr = CM_Get_Device_Interface_List_Size( + &deviceInterfaceListLength, + InterfaceGuid, + NULL, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (cr != CR_SUCCESS) { + printf("Error 0x%x retrieving device interface list size.\n", cr); + goto clean0; + } + + if (deviceInterfaceListLength <= 1) { + bRet = FALSE; + printf("Error: No active device interfaces found.\n" + " Is the sample driver loaded?"); + goto clean0; + } + + deviceInterfaceList = (PWSTR)malloc(deviceInterfaceListLength * sizeof(WCHAR)); + if (deviceInterfaceList == NULL) { + printf("Error allocating memory for device interface list.\n"); + goto clean0; + } + ZeroMemory(deviceInterfaceList, deviceInterfaceListLength * sizeof(WCHAR)); + + cr = CM_Get_Device_Interface_List( + InterfaceGuid, + NULL, + deviceInterfaceList, + deviceInterfaceListLength, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (cr != CR_SUCCESS) { + printf("Error 0x%x retrieving device interface list.\n", cr); + goto clean0; + } + + nextInterface = deviceInterfaceList + wcslen(deviceInterfaceList) + 1; + if (*nextInterface != UNICODE_NULL) { + printf("Warning: More than one device interface instance found. \n" + "Selecting first matching device.\n\n"); + } + + hr = StringCchCopy(DevicePath, BufLen, deviceInterfaceList); + if (FAILED(hr)) { + bRet = FALSE; + printf("Error: StringCchCopy failed with HRESULT 0x%x", hr); + goto clean0; + } + +clean0: + if (deviceInterfaceList != NULL) { + free(deviceInterfaceList); + } + if (CR_SUCCESS != cr) { + bRet = FALSE; + } + + return bRet; +} + diff --git a/tests/projects/windows/driver/umdf/echo/exe/public.h b/tests/projects/windows/driver/umdf/echo/exe/public.h new file mode 100644 index 000000000..defcded56 --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/exe/public.h @@ -0,0 +1,30 @@ +/*++ +Copyright (c) 1990-2000 Microsoft Corporation All Rights Reserved + +Module Name: + + public.h + +Abstract: + + This module contains the common declarations shared by driver + and user applications. + + +Environment: + + user and kernel + +--*/ + +#define WHILE(a) \ +__pragma(warning(suppress:4127)) while(a) + +// +// Define an Interface Guid so that app can find the device and talk to it. +// + +DEFINE_GUID (GUID_DEVINTERFACE_ECHO, + 0xcdc35b6e, 0xbe4, 0x4936, 0xbf, 0x5f, 0x55, 0x37, 0x38, 0xa, 0x7c, 0x1a); +// {CDC35B6E-0BE4-4936-BF5F-5537380A7C1A} + diff --git a/tests/projects/windows/driver/umdf/echo/xmake.lua b/tests/projects/windows/driver/umdf/echo/xmake.lua new file mode 100644 index 000000000..0a5ec9517 --- /dev/null +++ b/tests/projects/windows/driver/umdf/echo/xmake.lua @@ -0,0 +1,22 @@ +add_rules("mode.debug", "mode.release") + +add_defines("_UNICODE", "UNICODE") + +target("echo") + add_rules("wdk.env.umdf", "wdk.driver") + + -- set test sign +-- set_values("wdk.sign.mode", "test") + + -- set release sign +-- set_values("wdk.sign.mode", "release") +-- set_values("wdk.sign.certfile", path.join(os.projectdir(), "xxx.cer")) + + add_files("driver/*.c") + add_files("driver/*.inx") + add_includedirs("exe") + +target("app") + add_rules("wdk.env.umdf", "wdk.binary") + add_files("exe/*.cpp") + diff --git a/tests/projects/windows/driver/umdf/skeleton/Skeleton.rc b/tests/projects/windows/driver/umdf/skeleton/Skeleton.rc new file mode 100644 index 000000000..0e202c4f5 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/Skeleton.rc @@ -0,0 +1,21 @@ +//--------------------------------------------------------------------------- +// Skeleton.rc +// +// Copyright (c) Microsoft Corporation, All Rights Reserved +//--------------------------------------------------------------------------- + + +#include +#include + +// +// TODO: Change the file description and file names to match your binary. +// + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT_UNKNOWN +#define VER_FILEDESCRIPTION_STR "WDF:UMDF Skeleton User-Mode Driver Sample" +#define VER_INTERNALNAME_STR "UMDFSkeleton" +#define VER_ORIGINALFILENAME_STR "UMDFSkeleton.dll" + +#include "common.ver" diff --git a/tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_OSR.inx b/tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_OSR.inx new file mode 100644 index 000000000..3da01ae62 Binary files /dev/null and b/tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_OSR.inx differ diff --git a/tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_Root.inx b/tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_Root.inx new file mode 100644 index 000000000..63d9f94c5 Binary files /dev/null and b/tests/projects/windows/driver/umdf/skeleton/UMDFSkeleton_Root.inx differ diff --git a/tests/projects/windows/driver/umdf/skeleton/comsup.cpp b/tests/projects/windows/driver/umdf/skeleton/comsup.cpp new file mode 100644 index 000000000..fb0b0807c --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/comsup.cpp @@ -0,0 +1,344 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved + +Module Name: + + ComSup.cpp + +Abstract: + + This module contains implementations for the functions and methods + used for providing COM support. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#include "internal.h" + +#include "comsup.tmh" + +// +// Implementation of CUnknown methods. +// + +CUnknown::CUnknown( + VOID + ) : m_ReferenceCount(1) +/*++ + + Routine Description: + + Constructor for an instance of the CUnknown class. This simply initializes + the reference count of the object to 1. The caller is expected to + call Release() if it wants to delete the object once it has been allocated. + + Arguments: + + None + + Return Value: + + None + +--*/ +{ + // do nothing. +} + +HRESULT +STDMETHODCALLTYPE +CUnknown::QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ) +/*++ + + Routine Description: + + This method provides the basic support for query interface on CUnknown. + If the interface requested is IUnknown it references the object and + returns an interface pointer. Otherwise it returns an error. + + Arguments: + + InterfaceId - the IID being requested + + Object - a location to store the interface pointer to return. + + Return Value: + + S_OK or E_NOINTERFACE + +--*/ +{ + if (IsEqualIID(InterfaceId, __uuidof(IUnknown))) + { + *Object = QueryIUnknown(); + return S_OK; + } + else + { + *Object = NULL; + return E_NOINTERFACE; + } +} + +IUnknown * +CUnknown::QueryIUnknown( + VOID + ) +/*++ + + Routine Description: + + This helper method references the object and returns a pointer to the + object's IUnknown interface. + + This allows other methods to convert a CUnknown pointer into an IUnknown + pointer without a typecast and without calling QueryInterface and dealing + with the return value. + + Arguments: + + None + + Return Value: + + A pointer to the object's IUnknown interface. + +--*/ +{ + AddRef(); + return static_cast(this); +} + +ULONG +STDMETHODCALLTYPE +CUnknown::AddRef( + VOID + ) +/*++ + + Routine Description: + + This method adds one to the object's reference count. + + Arguments: + + None + + Return Value: + + The new reference count. The caller should only use this for debugging + as the object's actual reference count can change while the caller + examines the return value. + +--*/ +{ + return InterlockedIncrement(&m_ReferenceCount); +} + +ULONG +STDMETHODCALLTYPE +CUnknown::Release( + VOID + ) +/*++ + + Routine Description: + + This method subtracts one to the object's reference count. If the count + goes to zero, this method deletes the object. + + Arguments: + + None + + Return Value: + + The new reference count. If the caller uses this value it should only be + to check for zero (i.e. this call caused or will cause deletion) or + non-zero (i.e. some other call may have caused deletion, but this one + didn't). + +--*/ +{ + ULONG count = InterlockedDecrement(&m_ReferenceCount); + + if (count == 0) + { + delete this; + } + return count; +} + +// +// Implementation of CClassFactory methods. +// + +// +// Define storage for the factory's static lock count variable. +// + +LONG CClassFactory::s_LockCount = 0; + +IClassFactory * +CClassFactory::QueryIClassFactory( + VOID + ) +/*++ + + Routine Description: + + This helper method references the object and returns a pointer to the + object's IClassFactory interface. + + This allows other methods to convert a CClassFactory pointer into an + IClassFactory pointer without a typecast and without dealing with the + return value QueryInterface. + + Arguments: + + None + + Return Value: + + A referenced pointer to the object's IClassFactory interface. + +--*/ +{ + AddRef(); + return static_cast(this); +} + +HRESULT +CClassFactory::QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ) +/*++ + + Routine Description: + + This method attempts to retrieve the requested interface from the object. + + If the interface is found then the reference count on that interface (and + thus the object itself) is incremented. + + Arguments: + + InterfaceId - the interface the caller is requesting. + + Object - a location to store the interface pointer. + + Return Value: + + S_OK or E_NOINTERFACE + +--*/ +{ + // + // This class only supports IClassFactory so check for that. + // + + if (IsEqualIID(InterfaceId, __uuidof(IClassFactory))) + { + *Object = QueryIClassFactory(); + return S_OK; + } + else + { + // + // See if the base class supports the interface. + // + + return CUnknown::QueryInterface(InterfaceId, Object); + } +} + +HRESULT +STDMETHODCALLTYPE +CClassFactory::CreateInstance( + _In_opt_ IUnknown * /* OuterObject */, + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ) +/*++ + + Routine Description: + + This COM method is the factory routine - it creates instances of the driver + callback class and returns the specified interface on them. + + Arguments: + + OuterObject - only used for aggregation, which our driver callback class + does not support. + + InterfaceId - the interface ID the caller would like to get from our + new object. + + Object - a location to store the referenced interface pointer to the new + object. + + Return Value: + + Status. + +--*/ +{ + HRESULT hr; + + PCMyDriver driver; + + *Object = NULL; + + hr = CMyDriver::CreateInstance(&driver); + + if (SUCCEEDED(hr)) + { + hr = driver->QueryInterface(InterfaceId, Object); + driver->Release(); + } + + return hr; +} + +HRESULT +STDMETHODCALLTYPE +CClassFactory::LockServer( + _In_ BOOL Lock + ) +/*++ + + Routine Description: + + This COM method can be used to keep the DLL in memory. However since the + driver's DllCanUnloadNow function always returns false, this has little + effect. Still it tracks the number of lock and unlock operations. + + Arguments: + + Lock - Whether the caller wants to lock or unlock the "server" + + Return Value: + + S_OK + +--*/ +{ + if (Lock) + { + InterlockedIncrement(&s_LockCount); + } + else + { + InterlockedDecrement(&s_LockCount); + } + return S_OK; +} + diff --git a/tests/projects/windows/driver/umdf/skeleton/comsup.h b/tests/projects/windows/driver/umdf/skeleton/comsup.h new file mode 100644 index 000000000..ba4cd89c3 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/comsup.h @@ -0,0 +1,215 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved + +Module Name: + + ComSup.h + +Abstract: + + This module contains classes and functions use for providing COM support + code. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#pragma once + +// +// Forward type declarations. They are here rather than in internal.h as +// you only need them if you choose to use these support classes. +// + +typedef class CUnknown *PCUnknown; +typedef class CClassFactory *PCClassFactory; + +// +// Base class to implement IUnknown. You can choose to derive your COM +// classes from this class, or simply implement IUnknown in each of your +// classes. +// + +class CUnknown : public IUnknown +{ + +// +// Private data members and methods. These are only accessible by the methods +// of this class. +// +private: + + // + // The reference count for this object. Initialized to 1 in the + // constructor. + // + + LONG m_ReferenceCount; + +// +// Protected data members and methods. These are accessible by the subclasses +// but not by other classes. +// +protected: + + // + // The constructor and destructor are protected to ensure that only the + // subclasses of CUnknown can create and destroy instances. + // + + CUnknown( + VOID + ); + + // + // The destructor MUST be virtual. Since any instance of a CUnknown + // derived class should only be deleted from within CUnknown::Release, + // the destructor MUST be virtual or only CUnknown::~CUnknown will get + // invoked on deletion. + // + // If you see that your CMyDevice specific destructor is never being + // called, make sure you haven't deleted the virtual destructor here. + // + + virtual + ~CUnknown( + VOID + ) + { + // Do nothing + } + +// +// Public Methods. These are accessible by any class. +// +public: + + IUnknown * + QueryIUnknown( + VOID + ); + +// +// COM Methods. +// +public: + + // + // IUnknown methods + // + + virtual + ULONG + STDMETHODCALLTYPE + AddRef( + VOID + ); + + virtual + ULONG + STDMETHODCALLTYPE + Release( + VOID + ); + + virtual + HRESULT + STDMETHODCALLTYPE + QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ); +}; + +// +// Class factory support class. Create an instance of this from your +// DllGetClassObject method and modify the implementation to create +// an instance of your driver event handler class. +// + +class CClassFactory : public CUnknown, public IClassFactory +{ +// +// Private data members and methods. These are only accessible by the methods +// of this class. +// +private: + + // + // The lock count. This is shared across all instances of IClassFactory + // and can be queried through the public IsLocked method. + // + + static LONG s_LockCount; + +// +// Public Methods. These are accessible by any class. +// +public: + + IClassFactory * + QueryIClassFactory( + VOID + ); + +// +// COM Methods. +// +public: + + // + // IUnknown methods + // + + virtual + ULONG + STDMETHODCALLTYPE + AddRef( + VOID + ) + { + return __super::AddRef(); + } + + _At_(this, __drv_freesMem(object)) + virtual + ULONG + STDMETHODCALLTYPE + Release( + VOID + ) + { + return __super::Release(); + } + + virtual + HRESULT + STDMETHODCALLTYPE + QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ); + + // + // IClassFactory methods. + // + + virtual + HRESULT + STDMETHODCALLTYPE + CreateInstance( + _In_opt_ IUnknown *OuterObject, + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ); + + virtual + HRESULT + STDMETHODCALLTYPE + LockServer( + _In_ BOOL Lock + ); +}; diff --git a/tests/projects/windows/driver/umdf/skeleton/device.cpp b/tests/projects/windows/driver/umdf/skeleton/device.cpp new file mode 100644 index 000000000..2efcd36f0 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/device.cpp @@ -0,0 +1,238 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved. + +Module Name: + + Device.cpp + +Abstract: + + This module contains the implementation of the UMDF Skeleton sample driver's + device callback object. + + The skeleton sample device does very little. It does not implement either + of the PNP interfaces so once the device is setup, it won't ever get any + callbacks until the device is removed. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#include "internal.h" +#include "device.tmh" + +HRESULT +CMyDevice::CreateInstance( + _In_ IWDFDriver *FxDriver, + _In_ IWDFDeviceInitialize * FxDeviceInit, + _Out_ PCMyDevice *Device + ) +/*++ + + Routine Description: + + This method creates and initializs an instance of the skeleton driver's + device callback object. + + Arguments: + + FxDeviceInit - the settings for the device. + + Device - a location to store the referenced pointer to the device object. + + Return Value: + + Status + +--*/ +{ + PCMyDevice device; + HRESULT hr; + + // + // Allocate a new instance of the device class. + // + + device = new CMyDevice(); + + if (NULL == device) + { + return E_OUTOFMEMORY; + } + + // + // Initialize the instance. + // + + hr = device->Initialize(FxDriver, FxDeviceInit); + + if (SUCCEEDED(hr)) + { + *Device = device; + } + else + { + device->Release(); + } + + return hr; +} + +HRESULT +CMyDevice::Initialize( + _In_ IWDFDriver * FxDriver, + _In_ IWDFDeviceInitialize * FxDeviceInit + ) +/*++ + + Routine Description: + + This method initializes the device callback object and creates the + partner device object. + + The method should perform any device-specific configuration that: + * could fail (these can't be done in the constructor) + * must be done before the partner object is created -or- + * can be done after the partner object is created and which aren't + influenced by any device-level parameters the parent (the driver + in this case) might set. + + Arguments: + + FxDeviceInit - the settings for this device. + + Return Value: + + status. + +--*/ +{ + IWDFDevice *fxDevice; + HRESULT hr; + + // + // Configure things like the locking model before we go to create our + // partner device. + // + + // + // Set no locking unless you need an automatic callbacks synchronization + // + + FxDeviceInit->SetLockingConstraint(None); + + // + // TODO: If you're writing a filter driver then indicate that here. + // + // FxDeviceInit->SetFilter(); + // + + // + // TODO: Any per-device initialization which must be done before + // creating the partner object. + // + + // + // Create a new FX device object and assign the new callback object to + // handle any device level events that occur. + // + + // + // QueryIUnknown references the IUnknown interface that it returns + // (which is the same as referencing the device). We pass that to + // CreateDevice, which takes its own reference if everything works. + // + + { + IUnknown *unknown = this->QueryIUnknown(); + + hr = FxDriver->CreateDevice(FxDeviceInit, unknown, &fxDevice); + + unknown->Release(); + } + + // + // If that succeeded then set our FxDevice member variable. + // + + if (SUCCEEDED(hr)) + { + m_FxDevice = fxDevice; + + // + // Drop the reference we got from CreateDevice. Since this object + // is partnered with the framework object they have the same + // lifespan - there is no need for an additional reference. + // + + fxDevice->Release(); + } + + return hr; +} + +HRESULT +CMyDevice::Configure( + VOID + ) +/*++ + + Routine Description: + + This method is called after the device callback object has been initialized + and returned to the driver. It would setup the device's queues and their + corresponding callback objects. + + Arguments: + + FxDevice - the framework device object for which we're handling events. + + Return Value: + + status + +--*/ +{ + // + // TODO: Setup your device queues and I/O forwarding. + // + + return S_OK; +} + +HRESULT +CMyDevice::QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ) +/*++ + + Routine Description: + + This method is called to get a pointer to one of the object's callback + interfaces. + + Since the skeleton driver doesn't support any of the device events, this + method simply calls the base class's BaseQueryInterface. + + If the skeleton is extended to include device event interfaces then this + method must be changed to check the IID and return pointers to them as + appropriate. + + Arguments: + + InterfaceId - the interface being requested + + Object - a location to store the interface pointer if successful + + Return Value: + + S_OK or E_NOINTERFACE + +--*/ +{ + return CUnknown::QueryInterface(InterfaceId, Object); +} diff --git a/tests/projects/windows/driver/umdf/skeleton/device.h b/tests/projects/windows/driver/umdf/skeleton/device.h new file mode 100644 index 000000000..26dd0e329 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/device.h @@ -0,0 +1,115 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved + +Module Name: + + Device.h + +Abstract: + + This module contains the type definitions for the UMDF Skeleton sample + driver's device callback class. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#pragma once + +// +// Class for the iotrace driver. +// + +class CMyDevice : public CUnknown +{ + +// +// Private data members. +// +private: + + IWDFDevice *m_FxDevice; + +// +// Private methods. +// + +private: + + CMyDevice( + VOID + ) + { + m_FxDevice = NULL; + } + + HRESULT + Initialize( + _In_ IWDFDriver *FxDriver, + _In_ IWDFDeviceInitialize *FxDeviceInit + ); + +// +// Public methods +// +public: + + // + // The factory method used to create an instance of this driver. + // + + static + HRESULT + CreateInstance( + _In_ IWDFDriver *FxDriver, + _In_ IWDFDeviceInitialize *FxDeviceInit, + _Out_ PCMyDevice *Device + ); + + HRESULT + Configure( + VOID + ); + +// +// COM methods +// +public: + + // + // IUnknown methods. + // + + virtual + ULONG + STDMETHODCALLTYPE + AddRef( + VOID + ) + { + return __super::AddRef(); + } + + _At_(this, __drv_freesMem(object)) + virtual + ULONG + STDMETHODCALLTYPE + Release( + VOID + ) + { + return __super::Release(); + } + + virtual + HRESULT + STDMETHODCALLTYPE + QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ); + +}; diff --git a/tests/projects/windows/driver/umdf/skeleton/dllsup.cpp b/tests/projects/windows/driver/umdf/skeleton/dllsup.cpp new file mode 100644 index 000000000..e540452d9 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/dllsup.cpp @@ -0,0 +1,177 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved. + +Module Name: + + dllsup.cpp + +Abstract: + + This module contains the implementation of the UMDF Skeleton Sample + Driver's entry point and its exported functions for providing COM support. + + This module can be copied without modification to a new UMDF driver. It + depends on some of the code in comsup.cpp & comsup.h to handle DLL + registration and creating the first class factory. + + This module is dependent on the following defines: + + MYDRIVER_TRACING_ID - A wide string passed to WPP when initializing + tracing. For example the skeleton uses + L"Microsoft\\UMDF\\Skeleton" + + MYDRIVER_CLASS_ID - A GUID encoded in struct format used to + initialize the driver's ClassID. + + These are defined in internal.h for the sample. If you choose + to use a different primary include file, you should ensure they are + defined there as well. + +Environment: + + WDF User-Mode Driver Framework (WDF:UMDF) + +--*/ + +#include "internal.h" +#include "dllsup.tmh" + +const GUID CLSID_MyDriverCoClass = MYDRIVER_CLASS_ID; + +BOOL +WINAPI +DllMain( + HINSTANCE ModuleHandle, + DWORD Reason, + PVOID /* Reserved */ + ) +/*++ + + Routine Description: + + This is the entry point and exit point for the I/O trace driver. This + does very little as the I/O trace driver has minimal global data. + + This method initializes tracing. + + Arguments: + + ModuleHandle - the DLL handle for this module. + + Reason - the reason this entry point was called. + + Reserved - unused + + Return Value: + + TRUE + +--*/ +{ + + UNREFERENCED_PARAMETER( ModuleHandle ); + + if (DLL_PROCESS_ATTACH == Reason) + { + // + // Initialize tracing. + // + + WPP_INIT_TRACING(MYDRIVER_TRACING_ID); + + } + else if (DLL_PROCESS_DETACH == Reason) + { + // + // Cleanup tracing. + // + + WPP_CLEANUP(); + } + + return TRUE; +} + +HRESULT +STDAPICALLTYPE +DllGetClassObject( + _In_ REFCLSID ClassId, + _In_ REFIID InterfaceId, + _Outptr_ LPVOID *Interface + ) +/*++ + + Routine Description: + + This routine is called by COM in order to instantiate the + driver callback object and do an initial query interface on it. + + This method only creates an instance of the driver's class factory, as this + is the minimum required to support UMDF. + + Arguments: + + ClassId - the CLSID of the object being "gotten" + + InterfaceId - the interface the caller wants from that object. + + Interface - a location to store the referenced interface pointer + + Return Value: + + S_OK if the function succeeds or error indicating the cause of the + failure. + +--*/ +{ + PCClassFactory factory; + + HRESULT hr = S_OK; + + *Interface = NULL; + + // + // If the CLSID doesn't match that of our "coclass" (defined in the IDL + // file) then we can't create the object the caller wants. This may + // indicate that the COM registration is incorrect, and another CLSID + // is referencing this drvier. + // + + if (IsEqualCLSID(ClassId, CLSID_MyDriverCoClass) == false) + { + Trace( + TRACE_LEVEL_ERROR, + L"ERROR: Called to create instance of unrecognized class (%!GUID!)", + &ClassId + ); + + return CLASS_E_CLASSNOTAVAILABLE; + } + + // + // Create an instance of the class factory for the caller. + // + + factory = new CClassFactory(); + + if (NULL == factory) + { + hr = E_OUTOFMEMORY; + } + + // + // Query the object we created for the interface the caller wants. After + // that we release the object. This will drive the reference count to + // 1 (if the QI succeeded an referenced the object) or 0 (if the QI failed). + // In the later case the object is automatically deleted. + // + + if (SUCCEEDED(hr)) + { + hr = factory->QueryInterface(InterfaceId, Interface); + factory->Release(); + } + + return hr; +} diff --git a/tests/projects/windows/driver/umdf/skeleton/driver.cpp b/tests/projects/windows/driver/umdf/skeleton/driver.cpp new file mode 100644 index 000000000..d91b4b0b5 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/driver.cpp @@ -0,0 +1,220 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved. + +Module Name: + + Driver.cpp + +Abstract: + + This module contains the implementation of the UMDF Skeleton Sample's + core driver callback object. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#include "internal.h" +#include "driver.tmh" + +HRESULT +CMyDriver::CreateInstance( + _Out_ PCMyDriver *Driver + ) +/*++ + + Routine Description: + + This static method is invoked in order to create and initialize a new + instance of the driver class. The caller should arrange for the object + to be released when it is no longer in use. + + Arguments: + + Driver - a location to store a referenced pointer to the new instance + + Return Value: + + S_OK if successful, or error otherwise. + +--*/ +{ + PCMyDriver driver; + HRESULT hr; + + // + // Allocate the callback object. + // + + driver = new CMyDriver(); + + if (NULL == driver) + { + return E_OUTOFMEMORY; + } + + // + // Initialize the callback object. + // + + hr = driver->Initialize(); + + if (SUCCEEDED(hr)) + { + // + // Store a pointer to the new, initialized object in the output + // parameter. + // + + *Driver = driver; + } + else + { + + // + // Release the reference on the driver object to get it to delete + // itself. + // + + driver->Release(); + } + + return hr; +} + +HRESULT +CMyDriver::Initialize( + VOID + ) +/*++ + + Routine Description: + + This method is called to initialize a newly created driver callback object + before it is returned to the creator. Unlike the constructor, the + Initialize method contains operations which could potentially fail. + + Arguments: + + None + + Return Value: + + None + +--*/ +{ + return S_OK; +} + +HRESULT +CMyDriver::QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Interface + ) +/*++ + + Routine Description: + + This method returns a pointer to the requested interface on the callback + object.. + + Arguments: + + InterfaceId - the IID of the interface to query/reference + + Interface - a location to store the interface pointer. + + Return Value: + + S_OK if the interface is supported. + E_NOINTERFACE if it is not supported. + +--*/ +{ + if (IsEqualIID(InterfaceId, __uuidof(IDriverEntry))) + { + *Interface = QueryIDriverEntry(); + return S_OK; + } + else + { + return CUnknown::QueryInterface(InterfaceId, Interface); + } +} + +HRESULT +CMyDriver::OnDeviceAdd( + _In_ IWDFDriver *FxWdfDriver, + _In_ IWDFDeviceInitialize *FxDeviceInit + ) +/*++ + + Routine Description: + + The FX invokes this method when it wants to install our driver on a device + stack. This method creates a device callback object, then calls the Fx + to create an Fx device object and associate the new callback object with + it. + + Arguments: + + FxWdfDriver - the Fx driver object. + + FxDeviceInit - the initialization information for the device. + + Return Value: + + status + +--*/ +{ + HRESULT hr; + + PCMyDevice device = NULL; + + // + // TODO: Do any per-device initialization (reading settings from the + // registry for example) that's necessary before creating your + // device callback object here. Otherwise you can leave such + // initialization to the initialization of the device event + // handler. + // + + // + // Create a new instance of our device callback object + // + + hr = CMyDevice::CreateInstance(FxWdfDriver, FxDeviceInit, &device); + + // + // TODO: Change any per-device settings that the object exposes before + // calling Configure to let it complete its initialization. + // + + // + // If that succeeded then call the device's construct method. This + // allows the device to create any queues or other structures that it + // needs now that the corresponding fx device object has been created. + // + + if (SUCCEEDED(hr)) + { + hr = device->Configure(); + } + + // + // Release the reference on the device callback object now that it's been + // associated with an fx device object. + // + + if (NULL != device) + { + device->Release(); + } + + return hr; +} diff --git a/tests/projects/windows/driver/umdf/skeleton/driver.h b/tests/projects/windows/driver/umdf/skeleton/driver.h new file mode 100644 index 000000000..e764f517d --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/driver.h @@ -0,0 +1,149 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved + +Module Name: + + Driver.h + +Abstract: + + This module contains the type definitions for the UMDF Skeleton sample's + driver callback class. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#pragma once + +// +// This class handles driver events for the skeleton sample. In particular +// it supports the OnDeviceAdd event, which occurs when the driver is called +// to setup per-device handlers for a new device stack. +// + +class CMyDriver : public CUnknown, public IDriverEntry +{ +// +// Private data members. +// +private: + +// +// Private methods. +// +private: + + // + // Returns a refernced pointer to the IDriverEntry interface. + // + + IDriverEntry * + QueryIDriverEntry( + VOID + ) + { + AddRef(); + return static_cast(this); + } + + HRESULT + Initialize( + VOID + ); + +// +// Public methods +// +public: + + // + // The factory method used to create an instance of this driver. + // + + static + HRESULT + CreateInstance( + _Out_ PCMyDriver *Driver + ); + +// +// COM methods +// +public: + + // + // IDriverEntry methods + // + + virtual + HRESULT + STDMETHODCALLTYPE + OnInitialize( + _In_ IWDFDriver *FxWdfDriver + ) + { + UNREFERENCED_PARAMETER( FxWdfDriver ); + + return S_OK; + } + + virtual + HRESULT + STDMETHODCALLTYPE + OnDeviceAdd( + _In_ IWDFDriver *FxWdfDriver, + _In_ IWDFDeviceInitialize *FxDeviceInit + ); + + virtual + VOID + STDMETHODCALLTYPE + OnDeinitialize( + _In_ IWDFDriver *FxWdfDriver + ) + { + UNREFERENCED_PARAMETER( FxWdfDriver ); + + return; + } + + // + // IUnknown methods. + // + // We have to implement basic ones here that redirect to the + // base class becuase of the multiple inheritance. + // + + virtual + ULONG + STDMETHODCALLTYPE + AddRef( + VOID + ) + { + return __super::AddRef(); + } + + _At_(this, __drv_freesMem(object)) + virtual + ULONG + STDMETHODCALLTYPE + Release( + VOID + ) + { + return __super::Release(); + } + + virtual + HRESULT + STDMETHODCALLTYPE + QueryInterface( + _In_ REFIID InterfaceId, + _Out_ PVOID *Object + ); +}; diff --git a/tests/projects/windows/driver/umdf/skeleton/exports.def b/tests/projects/windows/driver/umdf/skeleton/exports.def new file mode 100644 index 000000000..7d46558b7 --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/exports.def @@ -0,0 +1,10 @@ +; Skeleton.def : Declares the module parameters. + +; +; TODO: Change the library name here to match your binary name. +; + +LIBRARY "UMDFSkeleton.DLL" + +EXPORTS + DllGetClassObject PRIVATE diff --git a/tests/projects/windows/driver/umdf/skeleton/internal.h b/tests/projects/windows/driver/umdf/skeleton/internal.h new file mode 100644 index 000000000..f338a9b6c --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/internal.h @@ -0,0 +1,90 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved + +Module Name: + + Internal.h + +Abstract: + + This module contains the local type definitions for the UMDF Skeleton + driver sample. + +Environment: + + Windows User-Mode Driver Framework (WUDF) + +--*/ + +#pragma once + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + +// +// Include the WUDF DDI +// + +#include "wudfddi.h" + +// +// Use specstrings for in/out annotation of function parameters. +// + +#include "specstrings.h" + +// +// Forward definitions of classes in the other header files. +// + +typedef class CMyDriver *PCMyDriver; +typedef class CMyDevice *PCMyDevice; + +// +// Define the tracing flags. +// +// TODO: Choose a different trace control GUID +// + +#define WPP_CONTROL_GUIDS \ + WPP_DEFINE_CONTROL_GUID( \ + MyDriverTraceControl, (e7541cdd,30e8,4b50,aeb0,51927330ae64), \ + \ + WPP_DEFINE_BIT(MYDRIVER_ALL_INFO) \ + ) + +#define WPP_FLAG_LEVEL_LOGGER(flag, level) \ + WPP_LEVEL_LOGGER(flag) + +#define WPP_FLAG_LEVEL_ENABLED(flag, level) \ + (WPP_LEVEL_ENABLED(flag) && \ + WPP_CONTROL(WPP_BIT_ ## flag).Level >= level) + +// +// This comment block is scanned by the trace preprocessor to define our +// Trace function. +// +// begin_wpp config +// FUNC Trace{FLAG=MYDRIVER_ALL_INFO}(LEVEL, MSG, ...); +// end_wpp +// + +// +// Driver specific #defines +// +// TODO: Change these values to be appropriate for your driver. +// + +#define MYDRIVER_TRACING_ID L"Microsoft\\UMDF\\Skeleton" +#define MYDRIVER_CLASS_ID { 0xd4112073, 0xd09b, 0x458f, { 0xa5, 0xaa, 0x35, 0xef, 0x21, 0xee, 0xf5, 0xde } } + + +// +// Include the type specific headers. +// + +#include "comsup.h" +#include "driver.h" +#include "device.h" diff --git a/tests/projects/windows/driver/umdf/skeleton/xmake.lua b/tests/projects/windows/driver/umdf/skeleton/xmake.lua new file mode 100644 index 000000000..8a48274ca --- /dev/null +++ b/tests/projects/windows/driver/umdf/skeleton/xmake.lua @@ -0,0 +1,13 @@ +add_rules("mode.debug", "mode.release") + +add_defines("_UNICODE", "UNICODE") + +target("UMDFSkeleton") + add_rules("wdk.env.umdf", "wdk.driver") + add_values("wdk.tracewpp.flags", "-scan:internal.h") + add_files("*.cpp", {rule = "wdk.tracewpp"}) + add_files("*.rc", "*.inx") + set_values("wdk.umdf.sdkver", "1.9") + add_shflags("/DEF:exports.def", {force = true}) + add_shflags("/ENTRY:_DllMainCRTStartup" .. (is_arch("x86") and "@12" or ""), {force = true}) + diff --git a/tests/projects/windows/driver/wdm/msdsm/SampleDSM.inf b/tests/projects/windows/driver/wdm/msdsm/SampleDSM.inf new file mode 100644 index 000000000..f632f6e50 Binary files /dev/null and b/tests/projects/windows/driver/wdm/msdsm/SampleDSM.inf differ diff --git a/tests/projects/windows/driver/wdm/msdsm/dsmmain.c b/tests/projects/windows/driver/wdm/msdsm/dsmmain.c new file mode 100644 index 000000000..bdf875184 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/dsmmain.c @@ -0,0 +1,9752 @@ +/*++ + +Copyright (C) 2004-2010 Microsoft Corporation + +Module Name: + + dsmmain.c + +Abstract: + + This driver is the Microsoft Device Specific Module (DSM). + It exports behaviours that mpio.sys will use to determine how to + multipath SPC-3 conforming devices. + + This file contains routines that are internal to MSDSM. + +Environment: + + kernel mode only + +Notes: + +--*/ + +#include "precomp.h" + +#ifdef DEBUG_USE_WPP +#include "dsmmain.tmh" +#endif + +#pragma warning (disable:4305) + +extern BOOLEAN DoAssert; + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(PAGE, DsmpRegisterPersistentReservationKeys) +#endif + +VOID +DsmpFreeDSMResources( + _In_ IN PDSM_CONTEXT DsmContext + ) +/*++ + +Routine Description: + + This routine will free the resources allocated by the DSM. This routine + should be called when the DSM is being unloaded. + +Arguements: + + DsmContext - DSM context given to MPIO during initialization + +Return Value: + + None +--*/ +{ + PDSM_WMILIB_CONTEXT wmiInfo; + PVOID tempAddress = (PVOID)DsmContext; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmpFreeDSMResources (DsmCtxt %p): Entering function.\n", + DsmContext)); + + // + // First free the buffer allocated for storing the registry path. + // + wmiInfo = &gDsmInitData.DsmWmiInfo; + + if (wmiInfo->RegistryPath.Buffer) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_INIT, + "DsmpFreeDSMResources (DsmCtxt %p): Freeing wmiInfo's registry buffer.\n", + DsmContext)); + + DsmpFreePool(wmiInfo->RegistryPath.Buffer); + } + + if (DsmContext) { + PLIST_ENTRY entry; + PDSM_DEVICE_INFO deviceInfo; + PDSM_GROUP_ENTRY groupEntry; + PDSM_FAILOVER_GROUP failGroup; + PDSM_CONTROLLER_LIST_ENTRY controllerEntry; + + ExDeleteNPagedLookasideList(&(DsmContext->CompletionContextList)); + + // + // Free up the devices (DeviceInfo) list. + // + while (!IsListEmpty(&DsmContext->DeviceList)) { + + entry = DsmContext->DeviceList.Flink; + + NT_ASSERT(entry); + + deviceInfo = CONTAINING_RECORD(entry, DSM_DEVICE_INFO, ListEntry); + + if (deviceInfo) { + + DsmpRemoveDeviceFailGroup(DsmContext, deviceInfo->FailGroup, deviceInfo, TRUE); + DsmpRemoveDeviceEntry(DsmContext, deviceInfo->Group, deviceInfo); + } + } + + NT_ASSERT(!DsmContext->NumberDevices && + !DsmContext->NumberFOGroups && + !DsmContext->NumberGroups); + + // + // By now, there should be no group entries left but play it safe and + // free up the GROUP list. + // + while (!IsListEmpty(&DsmContext->GroupList)) { + + entry = DsmContext->GroupList.Flink; + + NT_ASSERT(entry); + + groupEntry = CONTAINING_RECORD(entry, DSM_GROUP_ENTRY, ListEntry); + + if (groupEntry) { + + DsmpRemoveGroupEntry(DsmContext, groupEntry, TRUE); + + DsmpFreePool(groupEntry); + } + } + + // + // By now there should be no FOG entries left but we play it safe and + // free up the FOG list. + // + while (!IsListEmpty(&DsmContext->FailGroupList)) { + + entry = RemoveHeadList(&DsmContext->FailGroupList); + + if (entry) { + + failGroup = CONTAINING_RECORD(entry, DSM_FAILOVER_GROUP, ListEntry); + + if (failGroup) { + + PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry = NULL; + PLIST_ENTRY deviceEntry = NULL; + + while (!IsListEmpty(&failGroup->FOG_DeviceList)) { + + deviceEntry = RemoveHeadList(&failGroup->FOG_DeviceList); + + if (deviceEntry) { + + fogDeviceListEntry = CONTAINING_RECORD(deviceEntry, DSM_FOG_DEVICELIST_ENTRY, ListEntry); + + if (!fogDeviceListEntry) { + continue; + } + + (fogDeviceListEntry->DeviceInfo)->FailGroup = NULL; + + DsmpFreePool(fogDeviceListEntry); + InterlockedDecrement((LONG volatile*)&failGroup->Count); + } + } + + DsmpFreeZombieGroupList(failGroup); + DsmpFreePool(failGroup); + InterlockedDecrement((LONG volatile*)&DsmContext->NumberFOGroups); + } + } + } + + // + // Free up the controller list. + // + while (!IsListEmpty(&DsmContext->ControllerList)) { + + entry = RemoveHeadList(&DsmContext->ControllerList); + + if (entry) { + + controllerEntry = CONTAINING_RECORD(entry, DSM_CONTROLLER_LIST_ENTRY, ListEntry); + + if (controllerEntry) { + + DsmpFreeControllerEntry(DsmContext, controllerEntry); + + InterlockedDecrement((LONG volatile*)&DsmContext->NumberControllers); + } + } + } + + NT_ASSERT(!DsmContext->NumberControllers); + + // + // Free up the stale FOG list. + // + while (!IsListEmpty(&DsmContext->StaleFailGroupList)) { + + entry = RemoveHeadList(&DsmContext->StaleFailGroupList); + + if (entry) { + + failGroup = CONTAINING_RECORD(entry, DSM_FAILOVER_GROUP, ListEntry); + + if (failGroup) { + + InterlockedDecrement((LONG volatile*)&DsmContext->NumberStaleFOGroups); + NT_ASSERT(IsListEmpty(&failGroup->FOG_DeviceList)); + DsmpFreeZombieGroupList(failGroup); + DsmpFreePool(failGroup); + } + } + } + + // + // Free up the supported devices list buffer. + // + DsmpFreePool(DsmContext->SupportedDevices.Buffer); + + // + // It's the responsibility of the mpio bus driver to have already + // destroyed all devices and paths. As those functions free allocations + // for the objects, the only thing needed here is to free the DsmContext. + // + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_INIT, + "DsmpFreeDSMResources (DsmCtxt %p): Freeing the DsmContext.\n", + DsmContext)); + + DsmpFreePool(DsmContext); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmpFreeDSMResources (DsmCtxt %p): Exiting function.\n", + tempAddress)); + + return; +} + + +PDSM_GROUP_ENTRY +DsmpFindDevice( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN BOOLEAN AcquireDSMLockExclusive + ) +/*++ + +Routine Description: + + This routine searches for a serial number match between DeviceInfo and + the rest of the devices currently being driven by this DSM. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DeviceInfo - The deviceInfo containing serial number for which to search. + AcquireDSMLockExclusive - If TRUE this routine should acquire DsmContextLock Exclusively + +Return Value: + + The multi-path group entry in which the device resides. + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo; + PLIST_ENTRY entry; + PDSM_GROUP_ENTRY groupEntry = NULL; + ULONG i; + KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFindDevice (DevInfo %p): Entering function.\n", + DeviceInfo)); + + if (AcquireDSMLockExclusive) { + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + } + + // + // Run through the DeviceInfo List + // + entry = DsmContext->DeviceList.Flink; + for (i = 0; i < DsmContext->NumberDevices; i++, entry = entry->Flink) { + + // + // Extract the deviceInfo structure. + // + deviceInfo = CONTAINING_RECORD(entry, DSM_DEVICE_INFO, ListEntry); + DSM_ASSERT(deviceInfo); + + if (deviceInfo) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpFindDevice (DevInfo %p): Comparing with %p.\n", + DeviceInfo, + deviceInfo)); + + // + // Call the Serial Number compare routine. + // + if (DsmCompareDevices(DsmContext, + DeviceInfo, + deviceInfo)) { + + groupEntry = deviceInfo->Group; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpFindDevice (DevInfo %p): Found matching multi-path group %p.\n", + DeviceInfo, + groupEntry)); + + break; + } + } + } + + if (AcquireDSMLockExclusive) { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFindDevice (DevInfo %p): Exiting function with groupEntry %p.\n", + DeviceInfo, + groupEntry)); + + return groupEntry; +} + + +PDSM_GROUP_ENTRY +DsmpBuildGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + This will allocate and partially initialise a multi-path group entry. + + N.B: This routine must be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DeviceInfo - The first device to be added to the group. + +Return Value: + + The new group entry. + +--*/ +{ + PDSM_GROUP_ENTRY group; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildGroupEntry (DevInfo %p): Entering function.\n", + DeviceInfo)); + + // + // Allocate the memory for the multi-path group. + // + group = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_GROUP_ENTRY), + DSM_TAG_GROUP_ENTRY); + + if (group) { + + InitializeListHead(&group->FailingDevInfoList); + group->GroupNumber = InterlockedIncrement((LONG volatile*)&DsmContext->NumberGroups); + group->GroupSig = DSM_GROUP_SIG; + group->State = DSM_GP_NORMAL; + + // + // Add it to the list of multi-path groups. + // + InsertTailList(&DsmContext->GroupList, &group->ListEntry); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildGroupEntry (DevInfo %p): Failed to allocate memory for the group.\n", + DeviceInfo)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildGroupEntry (DevInfo %p): Exiting function with group %p.\n", + DeviceInfo, + group)); + + return group; +} + + +NTSTATUS +DsmpParseTargetPortGroupsInformation( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, + _In_ IN ULONG TargetPortGroupsInfoLength + ) +/*++ + +Routine Description: + + This will parse the information returned back from a previously + made call to ReportTargetPortGroups and build new TPG entries or + update old ones. + + N.B: This routine must be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DsmContext + Group - group entry + TargetPortGroupsInfo - Pointer to the ReportTPG returned buffer. + TargetPortGroupsInfoLength - length of the buffer. + +Return Value: + + STATUS_SUCCESS or appropriate error code. + +--*/ +{ + PUCHAR targetPortGroupsInfoIndex; + ULONG bytes = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroupEntry = NULL; + ULONG descriptorSize = 0; + NTSTATUS status = STATUS_SUCCESS; + ULONG index; + DSM_DEVICE_STATE tpgState = DSM_DEV_NOT_USED_STATE; + ULONG bytesLeft; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpParseTargetPortGroupsInformation (Group %p): Entering function.\n", + Group)); + + targetPortGroupsInfoIndex = TargetPortGroupsInfo + bytes; + bytesLeft = TargetPortGroupsInfoLength - bytes; + + while (bytes < TargetPortGroupsInfoLength && NT_SUCCESS(status)) { + + targetPortGroupEntry = DsmpFindTargetPortGroupEntry(DsmContext, + Group, + targetPortGroupsInfoIndex, + bytesLeft); + + if (targetPortGroupEntry) { + + targetPortGroupEntry = DsmpUpdateTargetPortGroupEntry(DsmContext, + targetPortGroupEntry, + targetPortGroupsInfoIndex, + bytesLeft, + &descriptorSize); + } else { + + targetPortGroupEntry = DsmpBuildTargetPortGroupEntry(DsmContext, + Group, + targetPortGroupsInfoIndex, + bytesLeft, + &descriptorSize); + + if (targetPortGroupEntry) { + + // + // Insert this TPG entry into array + // + for (index = 0; index < DSM_MAX_PATHS; index++) { + + if (!Group->TargetPortGroupList[index]) { + + Group->TargetPortGroupList[index] = targetPortGroupEntry; + InterlockedIncrement((LONG volatile*)&Group->NumberTargetPortGroups); + targetPortGroupEntry->Group = Group; + break; + } + } + + if (index == DSM_MAX_PATHS) { + + NT_ASSERT(index < DSM_MAX_PATHS); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpParseTargetPortGroupsInformation (Group %p): Number of paths exceeded max supported.\n", + Group)); + + status = STATUS_UNSUCCESSFUL; + goto __Exit_DsmpParseTargetPortGroupsInformation; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpParseTargetPortGroupsInformation (Group %p): Insufficient resources to build TPG.\n", + Group)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (NT_SUCCESS(status)) { + + // + // If this is the first TPG being parsed, save off its AA state. + // + if (tpgState == DSM_DEV_NOT_USED_STATE) { + + tpgState = targetPortGroupEntry->AsymmetricAccessState; + + } else { + + // + // Check if this TPG's AA state differs from the previous one's. + // Symmetric LU access means that TPG access states must be the + // same for TPGs. If this one is different, we know that the + // device supports Asymmetric LU access. + // + if (tpgState != targetPortGroupEntry->AsymmetricAccessState) { + + Group->Symmetric = FALSE; + } + } + } + + if (targetPortGroupEntry) { + + // + // Set the flag to indicate that we've encountered this TPG in the RTPG information. + // + targetPortGroupEntry->Traversed = TRUE; + } + + bytes += descriptorSize; + targetPortGroupsInfoIndex += descriptorSize; + bytesLeft -= descriptorSize; + } + + // + // Since we've gone through the entire information reported by back RTPG, it + // is now time to delete the stale entries. + // + for (index = 0; index < DSM_MAX_PATHS; index++) { + + targetPortGroupEntry = Group->TargetPortGroupList[index]; + + if (targetPortGroupEntry) { + + if (targetPortGroupEntry->Traversed) { + + // + // Entry needs to continue to exist. Reset the flag and continue. + // + targetPortGroupEntry->Traversed = FALSE; + continue; + + } else { + + PLIST_ENTRY entry; + PLIST_ENTRY tempEntry; + PDSM_TARGET_PORT_LIST_ENTRY targetPort; + + // + // For this target port group, clean up all its target ports if + // the port doesn't expose any instance of this device. + // + for (entry = targetPortGroupEntry->TargetPortList.Flink; + entry != NULL && entry != &targetPortGroupEntry->TargetPortList; + entry = entry->Flink) { + + targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); + + if (targetPort) { + + // + // If the TP doesn't expose this device, it is safe + // to delete it. + // + if (IsListEmpty(&targetPort->TP_DeviceList)) { + + tempEntry = entry; + entry = entry->Blink; + + RemoveEntryList(tempEntry); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpParseTargetPortGroupsInformation (Group %p): Deleting empty target port %p from TPG %p list.\n", + Group, + targetPort, + targetPortGroupEntry)); + + DsmpFreePool(targetPort); + + InterlockedDecrement((LONG volatile*)&targetPortGroupEntry->NumberTargetPorts); + } + } + } + + // + // If the TPG doesn't have any TPs, it is safe to delete it. + // + if (!targetPortGroupEntry->NumberTargetPorts) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpParseTargetPortGroupsInformation (Group %p): Deleting target port group %p.\n", + Group, + targetPortGroupEntry)); + + DsmpFreePool(targetPortGroupEntry); + + InterlockedDecrement((LONG volatile*)&Group->NumberTargetPortGroups); + + Group->TargetPortGroupList[index] = NULL; + } + } + } + } + +__Exit_DsmpParseTargetPortGroupsInformation: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpParseTargetPortGroupsInformation (Group %p): Exiting function with status %x\n", + Group, + status)); + + return status; +} + + +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpFindTargetPortGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, + _In_ IN ULONG TPGs_BufferLength + ) +/*++ + +Routine Description: + + This will search the group's TPG array to look for an identifier match. + + N.B: This routine must be called with DsmContextLock held in either Shared + or Exclusive mode. + +Arguments: + + DsmContext - DsmContext + Group - group entry + TargetPortGroupsDescriptor - Pointer to the TPG descriptor. + TPGs_BufferLength - Length of the passed in TargetPortGroupsDescriptor buffer. + +Return Value: + + Pointer to the array element that matches, else NULL. + +--*/ +{ + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = NULL; + PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR descriptor = (PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR)TargetPortGroupsDescriptor; + ULONG index; + BOOLEAN found = FALSE; + USHORT identifier = ((descriptor->TPG_Identifier & 0x00FF) << 8) | ((descriptor->TPG_Identifier & 0xFF00) >> 8); + + UNREFERENCED_PARAMETER(TPGs_BufferLength); + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPortGroupEntry (Group %p): Entering function.\n", + Group)); + + for (index = 0; index < DSM_MAX_PATHS && !found; index++) { + + targetPortGroup = Group->TargetPortGroupList[index]; + + if (targetPortGroup) { + + if (targetPortGroup->Identifier == identifier) { + + found = TRUE; + } + } + } + + if (!found) { + targetPortGroup = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPortGroupEntry (Group %p): Exiting function with targetPortGroup %p.\n", + Group, + targetPortGroup)); + + return targetPortGroup; +} + +_Success_(return!=0) +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpUpdateTargetPortGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, + _In_ IN ULONG TPGs_BufferLength, + _Out_ OUT PULONG DescriptorSize + ) +/*++ + +Routine Description: + + This routine will update the target port group with information contained + in the passed in descriptor. + + N.B: This routine must be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DsmContext + TargetPortGroup - Pointer to the TPG entry to update. + TargetPortGroupsDescriptor - Pointer to the TPG descriptor. + TPGs_BufferLength - Length of the passed in TargetPortGroupsDescriptor buffer. + DescriptorSize - return value of the size of the descriptor. + +Return Value: + + The updated target port group entry on success, NULL in case of failure. + +--*/ +{ + PLIST_ENTRY entry; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = TargetPortGroup; + PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR descriptor = (PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR)TargetPortGroupsDescriptor; + ULONG numberTargetPorts = 0; + PULONG descriptorIndex; + ULONG index; + PDSM_TARGET_PORT_LIST_ENTRY listEntry; + NTSTATUS status = STATUS_SUCCESS; + ULONG identifier; + PLIST_ENTRY tempEntry = NULL; + ULONG delCount; + PUCHAR endOfBuffer = TargetPortGroupsDescriptor + TPGs_BufferLength - 1; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Entering function.\n", + TargetPortGroup)); + + if (DescriptorSize == NULL) { + status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Status %x due to null passed in DescriptorSize pointer\n", + TargetPortGroup, + status)); + + goto __Exit_DsmpUpdateTargetPortGroupEntry; + } + + *DescriptorSize = sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + (targetPortGroup->NumberTargetPorts * sizeof(ULONG)); + + if (((PUCHAR)descriptor + sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) - 1) > endOfBuffer) { + + status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Status %x due to incorrect passed in TPG buffer size (%u).\n", + TargetPortGroup, + status, + TPGs_BufferLength)); + + goto __Exit_DsmpUpdateTargetPortGroupEntry; + } + + identifier = ((descriptor->TPG_Identifier & 0x00FF) << 8) | ((descriptor->TPG_Identifier & 0xFF00) >> 8); + NT_ASSERT(targetPortGroup->Identifier == (USHORT)identifier); + NT_ASSERT(targetPortGroup->ActiveOptimizedSupported == (descriptor->ActiveOptimizedSupported) ? TRUE : FALSE); + NT_ASSERT(targetPortGroup->ActiveUnoptimizedSupported == (descriptor->ActiveUnoptimizedSupported) ? TRUE : FALSE); + NT_ASSERT(targetPortGroup->StandBySupported == (descriptor->StandbySupported) ? TRUE : FALSE); + NT_ASSERT(targetPortGroup->UnavailableSupported == (descriptor->UnavailableSupported) ? TRUE : FALSE); + NT_ASSERT(targetPortGroup->TransitioningSupported == (descriptor->TransitioningSupported) ? TRUE : FALSE); + DSM_ASSERT(targetPortGroup->VendorUnique == descriptor->VendorUnique); + + // + // It is possible that the asymmetric access state, status code and number of port + // may have changed + // + if ((targetPortGroup->AsymmetricAccessState) != (descriptor->AsymmetricAccessState & 0xF)) + { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Asymmetric access state has changed.\n", + TargetPortGroup)); + + + targetPortGroup->AsymmetricAccessState = descriptor->AsymmetricAccessState & 0xF; + } + + targetPortGroup->Preferred = (descriptor->Preferred) ? TRUE : FALSE; + + targetPortGroup->StatusCode = descriptor->StatusCode; + + numberTargetPorts = descriptor->NumberTargetPorts; + + NT_ASSERT(numberTargetPorts > 0); + + // + // Point to first target port identifier + // + descriptorIndex = descriptor->TargetPortIds; + + for (index = 0; index < numberTargetPorts && NT_SUCCESS(status); index++) { + + if (((PUCHAR)descriptorIndex + ((index + 1) * sizeof(ULONG)) - 1) > endOfBuffer) { + + status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Status %x due to incorrect TPG buffer size (%u) passed in.\n", + TargetPortGroup, + status, + TPGs_BufferLength)); + + goto __Exit_DsmpUpdateTargetPortGroupEntry; + } + + GetUlongFrom4ByteArray((PUCHAR)(&descriptorIndex[index]), identifier); + + listEntry = DsmpFindTargetPortListEntry(DsmContext, + targetPortGroup, + identifier); + + if (listEntry) { + + RemoveEntryList(&listEntry->ListEntry); + InsertHeadList(&targetPortGroup->TargetPortList, &listEntry->ListEntry); + + } else { + + listEntry = DsmpBuildTargetPortListEntry(DsmContext, + targetPortGroup, + identifier); + + if (listEntry) { + + InsertHeadList(&targetPortGroup->TargetPortList, &listEntry->ListEntry); + InterlockedIncrement((LONG volatile*)&targetPortGroup->NumberTargetPorts); + + } else { + + status = STATUS_INSUFFICIENT_RESOURCES; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Failed to allocate TargetPort (identifier %x).\n", + TargetPortGroup, + identifier)); + } + } + } + + // + // Ignore the status & carry on. Even if we weren't able to build TP entries + // for the new target ports, we are no worse off than before. + // + DSM_ASSERT(NT_SUCCESS(status)); + + *DescriptorSize = sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + (numberTargetPorts * sizeof(ULONG)); + + for (index = 0, entry = targetPortGroup->TargetPortList.Flink; + index < numberTargetPorts; + index++, entry = entry->Flink); + + delCount = targetPortGroup->NumberTargetPorts - numberTargetPorts; + + for (index = 0; index < delCount; index++) { + + tempEntry = entry; + entry = entry->Flink; + + RemoveEntryList(tempEntry); + InterlockedDecrement((LONG volatile*)&targetPortGroup->NumberTargetPorts); + + listEntry = CONTAINING_RECORD(tempEntry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); + NT_ASSERT(listEntry); + + if (listEntry) { + + PLIST_ENTRY deviceEntry; + PDSM_TARGET_PORT_DEVICELIST_ENTRY tp_device; + + while (!IsListEmpty(&listEntry->TP_DeviceList)) { + + deviceEntry = RemoveHeadList(&listEntry->TP_DeviceList); + InterlockedDecrement((LONG volatile*)&listEntry->Count); + + if (deviceEntry) { + + tp_device = CONTAINING_RECORD(deviceEntry, DSM_TARGET_PORT_DEVICELIST_ENTRY, ListEntry); + + if (tp_device) { + + if (tp_device->DeviceInfo) { + + tp_device->DeviceInfo->TargetPort = NULL; + } + + DsmpFreePool(tp_device); + } + } + } + + DsmpFreePool(listEntry); + } + } + +__Exit_DsmpUpdateTargetPortGroupEntry: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupEntry (TPG %p): Exiting function.\n", + targetPortGroup)); + + return targetPortGroup; +} + + +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpBuildTargetPortGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, + _In_ IN ULONG TPGs_BufferLength, + _Out_ OUT PULONG DescriptorSize + ) +/*++ + +Routine Description: + + This will allocate and partially initialise a target port group entry. + + N.B: This routine must be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DsmContext + Group - The group that this newly going to be built TPG belongs to. + TargetPortGroupsDescriptor - Pointer to the TPG descriptor. + TPGs_BufferLength - Length of the passed in TargetPortGroupsDescriptor buffer. + DescriptorSize - return value of the size of the descriptor. + +Return Value: + + The new target port group entry. + +--*/ +{ + PDSM_TARGET_PORT_GROUP_ENTRY entry = NULL; + PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR descriptor = (PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR)TargetPortGroupsDescriptor; + ULONG numberTargetPorts = 0; + PULONG descriptorIndex; + ULONG index = 0; + PDSM_TARGET_PORT_LIST_ENTRY listEntry; + NTSTATUS status = STATUS_SUCCESS; + ULONG identifier; + PUCHAR endOfBuffer = TargetPortGroupsDescriptor + TPGs_BufferLength - 1; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Entering function.\n", + Group)); + + if (DescriptorSize == NULL) { + + status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Status %x due to null passed in DescriptorSize pointer\n", + Group, + status)); + + goto __Exit_DsmpBuildTargetPortGroupEntry; + } + + *DescriptorSize = 0; + + if (((PUCHAR)descriptor + sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) - 1) > endOfBuffer) { + + status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Status %x due to incorrect passed in TPG buffer size (%u).\n", + Group, + status, + TPGs_BufferLength)); + + goto __Exit_DsmpBuildTargetPortGroupEntry; + } + + // + // Allocate the memory for the multi-path group. + // + entry = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_TARGET_PORT_GROUP_ENTRY), + DSM_TAG_TARGET_PORT_GROUP_ENTRY); + + if (entry) { + + entry->TargetPortGroupSig = DSM_TARGET_PORT_GROUP_SIG; + + // + // Target Port Group's access state + // + entry->AsymmetricAccessState = descriptor->AsymmetricAccessState & 0xF; + + // + // Target Port Group's supported states + // + entry->ActiveOptimizedSupported = (descriptor->ActiveOptimizedSupported) ? TRUE : FALSE; + entry->ActiveUnoptimizedSupported = (descriptor->ActiveUnoptimizedSupported) ? TRUE : FALSE; + entry->StandBySupported = (descriptor->StandbySupported) ? TRUE : FALSE; + entry->UnavailableSupported = (descriptor->UnavailableSupported) ? TRUE : FALSE; + + // + // Target Port Group's Preference and support for reporting transitioning + // + entry->Preferred = (descriptor->Preferred) ? TRUE : FALSE; + entry->TransitioningSupported = (descriptor->TransitioningSupported) ? TRUE : FALSE; + + // + // Target Port Group's identifier + // + entry->Identifier = ((descriptor->TPG_Identifier & 0x00FF) << 8) | ((descriptor->TPG_Identifier & 0xFF00) >> 8); + + // + // Target Port Group's status code + // + entry->StatusCode = descriptor->StatusCode; + + // + // Vendor unique + // + entry->VendorUnique = descriptor->VendorUnique; + + // + // Number of target ports + // + numberTargetPorts = descriptor->NumberTargetPorts; + + NT_ASSERT(numberTargetPorts > 0); + + // + // Point to first target port identifier + // + descriptorIndex = descriptor->TargetPortIds; + + InitializeListHead(&entry->TargetPortList); + + for (index = 0; index < numberTargetPorts && NT_SUCCESS(status); index++) { + + if (((PUCHAR)descriptorIndex + ((index + 1) * sizeof(ULONG)) - 1) > endOfBuffer) { + + status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Status %x due to incorrect TPG buffer size (%u) passed in.\n", + Group, + status, + TPGs_BufferLength)); + + break; + } + + GetUlongFrom4ByteArray((PUCHAR)(&descriptorIndex[index]), identifier); + + listEntry = DsmpBuildTargetPortListEntry(DsmContext, + entry, + identifier); + + if (listEntry) { + + InsertTailList(&entry->TargetPortList, &listEntry->ListEntry); + InterlockedIncrement((LONG volatile*)&entry->NumberTargetPorts); + + } else { + + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Failed to allocate memory for TP (identifier %x) of TPG %p.\n", + Group, + identifier, + entry)); + } + } + + if (NT_SUCCESS(status)) { + *DescriptorSize = sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + (numberTargetPorts * sizeof(ULONG)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Failed to allocate memory for the TPG.\n", + Group)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + + if (!NT_SUCCESS(status)) { + + // + // Delete the target port list and the target port group entry + // + numberTargetPorts = index - 1; + + if (entry) { + + PLIST_ENTRY delEntry; + + for (index = 0; index < numberTargetPorts; index++) { + + delEntry = RemoveHeadList(&entry->TargetPortList); + listEntry = CONTAINING_RECORD(delEntry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Cleaning up TPG %p's TP %x.\n", + Group, + entry, + listEntry->Identifier)); + + DsmpFreePool(listEntry); + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Cleaning up TPG %p.\n", + Group, + entry)); + + DsmpFreePool(entry); + entry = NULL; + } + } + +__Exit_DsmpBuildTargetPortGroupEntry: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortGroupEntry (Group %p): Exiting function with entry %p.\n", + Group, + entry)); + + return entry; +} + + +PDSM_TARGET_PORT_LIST_ENTRY +DsmpFindTargetPortListEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN ULONG RelativeTargetPortId + ) +/*++ + +Routine Description: + + This will search the passed in TPG's target port list for an identifier match. + + N.B: This routine must be called with DsmContextLock held in either Shared or + Exclusive mode. + +Arguments: + + DsmContext - DsmContext + TargetPortGroup - The Target Port Group whose target ports need to be searched. + RelativeTargetPortId - Identifier of the target port entry being matched. + +Return Value: + + The target port list entry if match found, else NULL. + +--*/ +{ + PLIST_ENTRY entry = NULL; + PDSM_TARGET_PORT_LIST_ENTRY targetPort = NULL; + BOOLEAN found = FALSE; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPortListEntry (TPG %p): Entering function.\n", + TargetPortGroup)); + + for (entry = TargetPortGroup->TargetPortList.Flink; + entry != &TargetPortGroup->TargetPortList && !found; + entry = entry->Flink) { + + targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); + NT_ASSERT(targetPort); + + if (targetPort) { + + if (targetPort->Identifier == RelativeTargetPortId) { + + NT_ASSERT(targetPort->TargetPortGroup == TargetPortGroup); + + found = TRUE; + } + } + } + + if (!found) { + targetPort = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPortListEntry (TPG %p): Exiting function with target port %p.\n", + TargetPortGroup, + targetPort)); + + return targetPort; +} + + +PDSM_TARGET_PORT_LIST_ENTRY +DsmpBuildTargetPortListEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN ULONG RelativeTargetPortId + ) +/*++ + +Routine Description: + + This will allocate and partially initialize a target port list entry. + + N.B: This routine must be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DsmContext + TargetPortGroup - The Target Port Group that this target port belongs to. + RelativeTargetPortId - Identifier of the target port entry being added. + +Return Value: + + The new target port list entry. + +--*/ +{ + PDSM_TARGET_PORT_LIST_ENTRY entry; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortListEntry (TPG %p): Entering function.\n", + TargetPortGroup)); + + entry = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_TARGET_PORT_LIST_ENTRY), + DSM_TAG_TARGET_PORT_LIST_ENTRY); + + if (entry) { + + InitializeListHead(&entry->TP_DeviceList); + + entry->Identifier = RelativeTargetPortId; + entry->TargetPortGroup = TargetPortGroup; + entry->TargetPortSig = DSM_TARGET_PORT_SIG; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortListEntry (TPG %p): Failed to allocate memory for target port (identifier %x).\n", + TargetPortGroup, + RelativeTargetPortId)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpBuildTargetPortListEntry (TPG %p): Exiting function with entry %p.\n", + TargetPortGroup, + entry)); + + return entry; +} + + +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpFindTargetPortGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PUSHORT TargetPortGroupId + ) +/*++ + +Routine Description: + + This routine searches the list of TargetPortGroups of a Group to + find a match for the passed in TargetPortGroupId. + + N.B: This routine must be called with DsmContextLock held in either Shared or + Exclusive mode. + +Arguments: + + DsmContext - DSM context. + Group - The group whose target port groups to search for a match. + TargetPortGroupId - Identifier of the target port group entry being searched. + +Return Value: + + The target port group entry which matches the passed in identifier. + +--*/ +{ + ULONG index; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroupEntry = NULL; + BOOLEAN found = FALSE; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPortGroup (Group %p): Entering function.\n", + Group)); + + // + // Run through the target port group array + // + for (index = 0; index < DSM_MAX_PATHS && !found; index++) { + + targetPortGroupEntry = Group->TargetPortGroupList[index]; + + if (targetPortGroupEntry) { + + if (targetPortGroupEntry->Identifier == *TargetPortGroupId) { + + found = TRUE; + } + } + } + + if (!found) { + + targetPortGroupEntry = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPortGroup (Group %p): Exiting function with targetPortGroupEntry %p.\n", + Group, + targetPortGroupEntry)); + + return targetPortGroupEntry; +} + + +PDSM_TARGET_PORT_LIST_ENTRY +DsmpFindTargetPort( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN PULONG TargetPortGroupId + ) +/*++ + +Routine Description: + + This routine searches the list of TargetPorts to + find a match for the passed in TargetPortGroup and RelativeTargetPortId. + + N.B. Spin lock must be held by caller. + +Arguments: + + DsmContext - DSM context. + TargetPortGroup - the Target Port Group of which this target port is a member. + RelativeTargetPortId - Identifier of the target port entry being searched. + +Return Value: + + The target port entry which matches the passed in identifier. + +--*/ +{ + PLIST_ENTRY entry; + PDSM_TARGET_PORT_LIST_ENTRY targetPortListEntry = NULL; + BOOLEAN found = FALSE; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPort (TPG %p): Entering function.\n", + TargetPortGroup)); + + // + // Run through the Target Port List + // + for (entry = TargetPortGroup->TargetPortList.Flink; + entry != &TargetPortGroup->TargetPortList && !found; + entry = entry->Flink) { + + // + // Extract the target port group structure. + // + targetPortListEntry = CONTAINING_RECORD(entry, + DSM_TARGET_PORT_LIST_ENTRY, + ListEntry); + NT_ASSERT(targetPortListEntry); + + if (targetPortListEntry) { + + NT_ASSERT(TargetPortGroup == targetPortListEntry->TargetPortGroup); + + // + // Compare with passed in identifier. + // + if (targetPortListEntry->Identifier == *TargetPortGroupId) { + + found = TRUE; + } + } + } + + if (!found) { + + targetPortListEntry = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindTargetPort (TPG %p): Exiting function with targetPortListEntry %p.\n", + TargetPortGroup, + targetPortListEntry)); + + return targetPortListEntry; +} + + +NTSTATUS +DsmpAddDeviceEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + This routine adds DeviceInfo to an existing multi-path group. + + N.B: This routine MUST be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + Group - The multi-path group to which DeviceInfo should be added. + DeviceInfo - The new device. + DeviceState - The initial device state (active, passive,...) + +Return Value: + + UNSUCCESSFUL - If there are too many paths already. + SUCCESS + +--*/ +{ + ULONG numberDevices; + NTSTATUS status = STATUS_SUCCESS; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpAddDeviceEntry (DevInfo %p): Entering function.\n", + DeviceInfo)); + + // + // Ensure that this is a valid config - namely, it hasn't + // exceeded the number of paths supported. + // + numberDevices = * (volatile ULONG *) &Group->NumberDevices; + if (numberDevices < DSM_MAX_PATHS) { + +#if DBG + ULONG i; + + // + // Ensure that this isn't a second copy of the same pdo. + // + for (i = 0; i < numberDevices; i++) { + if (Group->DeviceList[i]->PortPdo == DeviceInfo->PortPdo) { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpAddDeviceEntry (DevInfo %p): Received same PDO %p twice.\n", + DeviceInfo, + DeviceInfo->PortPdo)); + } + } +#endif + + // + // Indicate one more device is present in this group. + // + Group->DeviceList[numberDevices] = DeviceInfo; + + // + // Indicate one more in the list. + // + InterlockedIncrement((LONG volatile*)&Group->NumberDevices); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpAddDeviceEntry (DevInfo %p): Adding Device to Group %p\n", + DeviceInfo, + Group)); + + // + // Set-up this device's group id. + // + DeviceInfo->Group = Group; + + // + // One more deviceInfo entry. + // + InterlockedIncrement((LONG volatile*)&DsmContext->NumberDevices); + + // + // Finally, add it to the global list of devices. + // + InsertTailList(&DsmContext->DeviceList, + &DeviceInfo->ListEntry); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpAddDeviceEntry (DevInfo %p): Max Paths already added for Group %p.\n", + DeviceInfo, + Group)); + + status = STATUS_UNSUCCESSFUL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpAddDeviceEntry (DevInfo %p): Exiting function with status %x.\n", + DeviceInfo, + status)); + + return status; +} + + +PDSM_CONTROLLER_LIST_ENTRY +DsmpFindControllerEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDEVICE_OBJECT PortObject, + _In_ IN PSCSI_ADDRESS ScsiAddress, + _In_reads_(ControllerSerialNumberLength) IN PSTR ControllerSerialNumber, + _In_ IN SIZE_T ControllerSerialNumberLength, + _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, + _In_ IN BOOLEAN AcquireLock + ) +/*++ + +Routine Description: + + This routine compares the passed in serial number and SCSI address with the + entries in the list of controller objects. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization. + PortObject - Port FDO exposing the controller. + ScsiAddress - The scsi address to match. + ControllerSerialNumber - The serial number for which to find a match. + ControllerSerialNumberLength - Length of the passed in serial number, in bytes. + CodeSet - Code set used when building the passed in serial number. + AcquireLock - FALSE indicates that the caller has already acquired the spin lock. + +Return Value: + + Controller list entry if a match is found, else NULL + +--*/ +{ + KIRQL oldIrql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error + PLIST_ENTRY entry; + PDSM_CONTROLLER_LIST_ENTRY controllerEntry = NULL; + BOOLEAN found = FALSE; + PDSM_CONTROLLER_LIST_ENTRY candidate = NULL; + + UNREFERENCED_PARAMETER(CodeSet); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFindControllerEntry (SN %s): Entering function.\n", + ControllerSerialNumber)); + + if (AcquireLock) { + + oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + } + + for (entry = DsmContext->ControllerList.Flink; + entry != &DsmContext->ControllerList && !found; + entry = entry->Flink) { + + controllerEntry = CONTAINING_RECORD(entry, DSM_CONTROLLER_LIST_ENTRY, ListEntry); + NT_ASSERT(controllerEntry); + + if (!controllerEntry) { + + continue; + } + + // + // Serial numbers and Portal, Bus, and Target of the SCSI address must match. + // + if (!strncmp((const char*)controllerEntry->Identifier, + ControllerSerialNumber, + ControllerSerialNumberLength) && + (controllerEntry->ScsiAddress->PortNumber == ScsiAddress->PortNumber && + controllerEntry->ScsiAddress->PathId == ScsiAddress->PathId && + controllerEntry->ScsiAddress->TargetId == ScsiAddress->TargetId)) { + + if (controllerEntry->IdLength == ControllerSerialNumberLength) { + + found = TRUE; + + } else { + + if ((!candidate) || + (controllerEntry->IdLength > ControllerSerialNumberLength && ControllerSerialNumberLength == 32)) { + + candidate = controllerEntry; + } + } + } + } + + if (!found) { + + if (candidate) { + + controllerEntry = candidate; + + } else { + + controllerEntry = NULL; + } + } + + // + // If we found a matching controller entry, we need to make sure the Port + // Object (FDO) is updated. We also don't care about the LUN part of the + // SCSI address so we just set it to zero. + // + if (controllerEntry) { + controllerEntry->PortObject = PortObject; + controllerEntry->ScsiAddress->Lun = 0; + } + + if (AcquireLock) { + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFindControllerEntry (SN %s): Exiting function with controllerEntry %p\n", + ControllerSerialNumber, + controllerEntry)); + + return controllerEntry; +} + + +_Ret_maybenull_ +_Must_inspect_result_ +_When_(return != NULL, __drv_allocatesMem(Mem)) +PDSM_CONTROLLER_LIST_ENTRY +DsmpBuildControllerEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_opt_ IN PDEVICE_OBJECT DeviceObject, + _In_ IN PDEVICE_OBJECT PortObject, + _In_ IN PSCSI_ADDRESS ScsiAddress, + _In_ IN PSTR ControllerSerialNumber, + _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, + _In_ IN BOOLEAN AcquireLock + ) +/*++ + +Routine Description: + + This routine builds a new controller list entry with the passed in serial number info. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization. + DeviceObject - Controller's PDO. + PortObject - Port FDO exposing the controller. + ScsiAddress - scsi address of the controller. + ControllerSerialNumber - The serial number to associate with new entry. + CodeSet - Code set of the identifier that was used to build the serial number. + AcquireLock - TRUE indicates that the function must grab the spinlock. FALSE indicates + that caller has the spin lock held. + +Return Value: + + New controller list entry if we successfully built one, else NULL + +--*/ +{ + KIRQL oldIrql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error + PDSM_CONTROLLER_LIST_ENTRY controllerEntry = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildControllerEntry (SN %s): Entering function - Controller %p seen through PortFDO %p.\n", + ControllerSerialNumber, + DeviceObject, + PortObject)); + + if (AcquireLock) { + + oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + } + + controllerEntry = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_CONTROLLER_LIST_ENTRY), + DSM_TAG_CONTROLLER_LIST_ENTRY); + + if (controllerEntry) { + + // + // Note: + // ControllerSerialNumber's length fits in a 32-bit value. + // See implementation in DsmpParseDeviceID() + // + ULONG length = (ULONG)strlen(ControllerSerialNumber); + + controllerEntry->Identifier = DsmpAllocatePool(NonPagedPoolNx, + length + 1, + DSM_TAG_SERIAL_NUM); + + if (controllerEntry->Identifier) { + + controllerEntry->ScsiAddress = DsmpAllocatePool(NonPagedPoolNx, + sizeof(SCSI_ADDRESS), + DSM_TAG_SCSI_ADDRESS); + if (controllerEntry->ScsiAddress) { + + RtlCopyMemory(controllerEntry->ScsiAddress, ScsiAddress, sizeof(SCSI_ADDRESS)); + + controllerEntry->DeviceObject = DeviceObject; + controllerEntry->PortObject = PortObject; + controllerEntry->ControllerSig = DSM_CONTROLLER_SIG; + controllerEntry->IdLength = length; + controllerEntry->IdCodeSet = CodeSet; + + RtlCopyMemory(controllerEntry->Identifier, + ControllerSerialNumber, + length); + + controllerEntry->RefCount = 0; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildControllerEntry (SN %s): Failed to allocate resources for scsiaddress (controllerEntry %p).\n", + ControllerSerialNumber, + controllerEntry)); + + DsmpFreePool(controllerEntry->Identifier); + controllerEntry->Identifier = NULL; + DsmpFreePool(controllerEntry); + controllerEntry = NULL; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildControllerEntry (SN %s): Failed to allocate resources for identifier (controllerEntry %p).\n", + ControllerSerialNumber, + controllerEntry)); + + DsmpFreePool(controllerEntry); + controllerEntry = NULL; + } + + } else { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildControllerEntry (SN %s): Failed to allocate memory for ControllerEntry.\n", + ControllerSerialNumber)); + } + + if (AcquireLock) { + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildControllerEntry (SN %s): Exiting function with controllerEntry %p\n", + ControllerSerialNumber, + controllerEntry)); + + return controllerEntry; +} + + +VOID +DsmpFreeControllerEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ __drv_freesMem(Mem) IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry + ) +/*++ + +Routine Description: + + This routine frees the allocations of the passed in controller list entry. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization. + ControllerEntry - Controller list entry. + +Return Value: + + Nothing + +--*/ +{ + PVOID tempAddress = (PVOID)ControllerEntry; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFreeControllerEntry (Entry %p): Entering function.\n", + ControllerEntry)); + + if (ControllerEntry->Identifier) { + DsmpFreePool(ControllerEntry->Identifier); + } + + if (ControllerEntry->ScsiAddress) { + DsmpFreePool(ControllerEntry->ScsiAddress); + } + + DsmpFreePool(ControllerEntry); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFreeControllerEntry (Entry %p): Exiting function.\n", + tempAddress)); + + return; +} + + +BOOLEAN +DsmpIsDeviceBelongsToController( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry + ) +/*++ + +Routine Description: + + This routine determines if the device passed in was exposed via the passed + in controller. + The match is to be based on VID and SCSI Address (using the Port, Bus + and Target comparison). + +Arguments: + + DsmContext - DSM context given to MPIO during initialization. + DeviceInfo - The device instance to match. + ControllerEntry - The controller object which we need to determine whether + DeviceInfo is exposed from. + +Return Value: + + TRUE - if the controller's VID and scsi address match + FALSE - not matched + +--*/ +{ + BOOLEAN saMatch = FALSE; + BOOLEAN vMatch = FALSE; + BOOLEAN match = FALSE; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpIsDeviceBelongsToController (DevInfo %p): Entering function - ControllerEntry is %p.\n", + DeviceInfo, + ControllerEntry)); + + if (DeviceInfo->ScsiAddress && ControllerEntry->ScsiAddress) { + + saMatch = (DeviceInfo->ScsiAddress->PathId == ControllerEntry->ScsiAddress->PathId && + DeviceInfo->ScsiAddress->PortNumber == ControllerEntry->ScsiAddress->PortNumber && + DeviceInfo->ScsiAddress->TargetId == ControllerEntry->ScsiAddress->TargetId); + } + + if (saMatch) { + + INQUIRYDATA inquiryData = {0}; + UCHAR controllerVID[9] = {0}; + UCHAR deviceVID[9] = {0}; + + if (NT_SUCCESS(DsmpGetStandardInquiryData(ControllerEntry->DeviceObject, &inquiryData))) { + + RtlStringCchCopyA((PSTR)controllerVID, + ARRAYSIZE(controllerVID), + (PCSTR)(&inquiryData.VendorId)); + + RtlStringCchCopyA((PSTR)deviceVID, + ARRAYSIZE(deviceVID), + (PCSTR)(&DeviceInfo->Descriptor) + DeviceInfo->Descriptor.VendorIdOffset); + + + if (!strcmp((const char*)controllerVID, (const char*)deviceVID)) { + + vMatch = TRUE; + } + } + } + + match = saMatch & vMatch; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpIsDeviceBelongsToController (DevInfo %p): ControllerEntry %p. Exiting function with match = %x.\n", + DeviceInfo, + ControllerEntry, + match)); + + return match; +} + + +PDSM_DEVICE_INFO +DsmpFindDevInfoFromGroupAndFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_FAILOVER_GROUP FOGroup + ) +/*++ + +Routine Description: + + This routine will find the deviceInfo that is part of both the passed in Group + as well as passed in Fail-Over group. + + N.B: This routine MUST be called with DsmContextLock held in either Shared or + Exclusive mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + Group - The group that represents the device. + FOGroup - The FOG that the device is part of. + +Return Value: + + The deviceInfo that is part of both. + NULL - if not found. + +--*/ +{ + ULONG i; + PDSM_DEVICE_INFO deviceInfo = NULL; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpFindDevInfoFromGroupAndFOGroup (Group %p FOG %p): Entering function.\n", + Group, + FOGroup)); + + if (Group && FOGroup) { + + // + // Run through the list of devInfos in passed in Group + // + for (i = 0; i < DSM_MAX_PATHS; i++) { + + deviceInfo = Group->DeviceList[i]; + + if (deviceInfo) { + + if (deviceInfo->FailGroup == FOGroup) { + + break; + + } else { + + deviceInfo = NULL; + } + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpFindFOGroup (Group %p FOG %p): Exiting function with deviceInfo %p.\n", + Group, + FOGroup, + deviceInfo)); + + return deviceInfo; +} + + +PDSM_FAILOVER_GROUP +DsmpFindFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PVOID PathId + ) +/*++ + +Routine Description: + + This routine will find the Fail-Over group that corresponds to PathId. + + N.B: This routine MUST be called with DsmContextLock held in either Shared or + Exclusive mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + PathId - The Path Identifier that corresponds to + an adapter/adapter-controller + +Return Value: + + The fail-over group. + NULL - if not found. + +--*/ +{ + PDSM_FAILOVER_GROUP failOverGroup = NULL; + PDSM_FAILOVER_GROUP retFOGroup = NULL; + PLIST_ENTRY entry; + ULONG i; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindFOGroup (PathId %p): Entering function.\n", + PathId)); + + // + // Run through the list of Fail-Over Groups + // + entry = DsmContext->FailGroupList.Flink; + for (i = 0; i < DsmContext->NumberFOGroups; i++, entry = entry->Flink) { + + // + // Extract the fail-over group structure. + // + failOverGroup = CONTAINING_RECORD(entry, DSM_FAILOVER_GROUP, ListEntry); + NT_ASSERT(failOverGroup); + + if (!failOverGroup) { + continue; + } + + // + // Check for a match of the PathId. + // + if (failOverGroup->PathId == PathId) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpFindFOGroup (PathId %p): Found a FO group %p.\n", + PathId, + failOverGroup)); + + retFOGroup = failOverGroup; + + break; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindFOGroup (PathId %p): Exiting function with retFOGroup %p.\n", + PathId, + retFOGroup)); + + return retFOGroup; +} + + +PDSM_FAILOVER_GROUP +DsmpBuildFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PVOID *PathId + ) +/*++ + +Routine Description: + + This routine will build and partially initialise a fail-over group entry. + The FOG corresponds to the device list which will fail as a group. + + N.B: This routine MUST be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DeviceInfo - The first device to add to the group. + PathId - An identifier that is returned to mpio that id's the path. + +Return Value: + + The fail-over group entry. + NULL - on failed allocation. + +--*/ +{ + PDSM_FAILOVER_GROUP failOverGroup; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildFOGroup (PathId %p): Entering function.\n", PathId)); + + // + // Allocate a new Fail Over Group + // + failOverGroup = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_FAILOVER_GROUP), + DSM_TAG_FO_GROUP); + if (failOverGroup) { + + InitializeListHead(&failOverGroup->FOG_DeviceList); + InitializeListHead(&failOverGroup->ZombieGroupList); + + // + // Get the current number of groups, and add the one that's being created. + // + InterlockedIncrement((LONG volatile*)&DsmContext->NumberFOGroups); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpBuildFOGroup (PathId %p): Path that will be used for %p is %p.\n", + PathId, + DeviceInfo, + *PathId)); + + failOverGroup->PathId = *PathId; + + // + // Set the initial state to NORMAL. + // + failOverGroup->State = DSM_FG_NORMAL; + + failOverGroup->FailOverSig = DSM_FOG_SIG; + + // + // Add it to the global list. + // + InsertTailList(&DsmContext->FailGroupList, + &failOverGroup->ListEntry); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpBuildFOGroup (PathId %p): Added new FOGroup %p with path %p. Count of FO Group %d.\n", + PathId, + failOverGroup, + *PathId, + DsmContext->NumberFOGroups)); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildFOGroup (PathId %p): Failed to allocate memory for FailOverGroup.\n", + PathId)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildFOGroup (PathId %p): Exiting function with failOverGroup %p.\n", + PathId, + failOverGroup)); + + return failOverGroup; +} + + +NTSTATUS +DsmpUpdateFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_FAILOVER_GROUP FailGroup, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + This routine will add DeviceInfo to an existing FOG. + + N.B: This routine MUST be called with DsmContextLock held in Exclusive mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + FailGroup - The fail-over group entry. + DeviceInfo - The new device. + +Return Value: + + STATUS_SUCCESS or appropriate error code. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpUpdateFOGroup (FOG %p): Entering function. DeviceInfo %p.\n", + FailGroup, + DeviceInfo)); + + if (DeviceInfo && FailGroup) { + + fogDeviceListEntry = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_FOG_DEVICELIST_ENTRY), + DSM_TAG_FOG_DEV_ENTRY); + + if (fogDeviceListEntry) { + + // + // Add the device to the list of devices that are on this path. + // + fogDeviceListEntry->DeviceInfo = DeviceInfo; + InterlockedIncrement((LONG volatile*)&FailGroup->Count); + InsertTailList(&FailGroup->FOG_DeviceList, &fogDeviceListEntry->ListEntry); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpUpdateFOGroup (FOG %p): DevInfo %p added (current count: %d)\n", + FailGroup, + DeviceInfo, + FailGroup->Count)); + + // + // Set the device's F.O. Group. + // + DeviceInfo->FailGroup = FailGroup; + + } else { + + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpUpdateFOGroup (FOG %p): Failed to allocate memory for FOG devlist entry.\n", + FailGroup)); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpUpdateFOGroup (FOG %p): Exiting function with status %x.\n", + FailGroup, + status)); + + return status; +} + + +VOID +DsmpRemoveDeviceFailGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_FAILOVER_GROUP FailGroup, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN BOOLEAN AcquireDSMLockExclusive + ) +/*++ + +Routine Description: + + This routine will remove DeviceInfo from the FOG. + This routine is called in response to a removal of the device. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + FailGroup - The FOG from which DeviceInfo should be removed. + DeviceInfo - The now missing device. + AcquireDSMLockExclusive - If TRUE this routine should acquire DsmContextLock Exclusively + +Return Value: + + NOTHING + +--*/ +{ + KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 warnings + PLIST_ENTRY entry; + PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry; + PLIST_ENTRY zombieEntry; + PDSM_ZOMBIEGROUP_ENTRY zombieGroup; + PDSM_ZOMBIEGROUP_ENTRY newZombieGroup; + BOOLEAN groupInZombieList = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceFailGroup (FOG %p): Entering function. DeviceInfo %p.\n", + FailGroup, + DeviceInfo)); + + if (FailGroup && DeviceInfo) { + + if (AcquireDSMLockExclusive) { + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + } + + for (entry = FailGroup->FOG_DeviceList.Flink; + entry != &FailGroup->FOG_DeviceList; + entry = entry->Flink) { + + fogDeviceListEntry = CONTAINING_RECORD(entry, + DSM_FOG_DEVICELIST_ENTRY, + ListEntry); + DSM_ASSERT(fogDeviceListEntry); + + if (!fogDeviceListEntry) { + continue; + } + + if (fogDeviceListEntry->DeviceInfo == DeviceInfo) { + + DeviceInfo->FailGroup = NULL; + RemoveEntryList(entry); + DsmpFreePool(fogDeviceListEntry); + + InterlockedDecrement((LONG volatile*)&FailGroup->Count); + + // + // If a DeviceInfo is removed, we need to keep its group in a + // "zombie" list so that we can still access a fail-over group's + // associated groups even when all its devices are gone. + // + for (zombieEntry = FailGroup->ZombieGroupList.Flink; + zombieEntry != &(FailGroup->ZombieGroupList); + zombieEntry = zombieEntry->Flink) { + + zombieGroup = CONTAINING_RECORD(zombieEntry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); + if (zombieGroup != NULL && + zombieGroup->Group != NULL && + zombieGroup->Group == DeviceInfo->Group) { + + groupInZombieList = TRUE; + break; + } + } + + // + // Create a new entry if the group does not exist in the zombie group list. + // + if (groupInZombieList == FALSE) { + newZombieGroup = (PDSM_ZOMBIEGROUP_ENTRY)DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_ZOMBIEGROUP_ENTRY), + DSM_TAG_ZOMBIEGROUP_ENTRY); + if (newZombieGroup != NULL) { + newZombieGroup->Group = DeviceInfo->Group; + InsertTailList(&FailGroup->ZombieGroupList, &newZombieGroup->ListEntry); + } else { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceFailGroup (DevInfo %p): Failed to allocate memory for the zombie group.\n", + DeviceInfo)); + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceFailGroup (FOG %p): DevInfo %p removed from FOG (current count: %d)\n", + FailGroup, + DeviceInfo, + FailGroup->Count)); + + break; + } + } + + if (AcquireDSMLockExclusive) { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceFailGroup (FOG %p): Exiting function.\n", + FailGroup)); + + return; +} + + +ULONG +DsmpRemoveDeviceEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + This routine will remove DeviceInfo from Group. If it is the last DeviceInfo + in the Group, it has the added side-effect of cleaning up the Group entry + also. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + Group - The multi-path group from which DeviceInfo should be removed. + DeviceInfo - The device to remove. + +Return Value: + + Number of devices left in group. + +--*/ +{ + KIRQL irql; + ULONG i; + ULONG j; + ULONG numberDevices; + BOOLEAN freeGroup = FALSE; + PVOID tempAddress = (PVOID)Group; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceEntry (Group %p): Entering function. DeviceInfo %p.\n", + Group, + DeviceInfo)); + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Find it's offset in the array of devices. + // + for (i = 0; i < Group->NumberDevices; i++) { + + if (Group->DeviceList[i] == DeviceInfo) { + + // + // Zero out it's entry. + // + Group->DeviceList[i] = NULL; + + // + // Reduce the number in the group. + // + InterlockedDecrement((LONG volatile*)&Group->NumberDevices); + + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceEntry (Group %p): Removing Device %p (desiredState %u) from Group\n", + Group, + DeviceInfo, + DeviceInfo->DesiredState)); + + // + // Collapse the array. + // Holding the spinlock, so that the state is consistent in other + // routines. + // + for (j = i; j < Group->NumberDevices; j++) { + + // + // Shuffle all entries down to fill the hole. + // + Group->DeviceList[j] = Group->DeviceList[j + 1]; + } + + // + // Zero out the last one. + // + Group->DeviceList[j] = NULL; + break; + } + } + + // + // Remove this devInfo from the TargetPort deviceList + // + DsmpRemoveDeviceFromTargetPortList(DeviceInfo); + + numberDevices = Group->NumberDevices; + + // + // See if anything is left in the Group. + // + if (Group->NumberDevices == 0) { + + Group->State = DSM_GP_FAILED; + + // + // Yank it from the Group list. + // + DsmpRemoveGroupEntry(DsmContext, Group, FALSE); + + freeGroup = TRUE; + } + + // + // Yank the device out of the Global list. + // + RemoveEntryList(&DeviceInfo->ListEntry); + InterlockedDecrement((LONG volatile*)&DsmContext->NumberDevices); + + // + // If the serial number buffer was allocated, need to free it. + // + if (DeviceInfo->SerialNumberAllocated) { + DsmpFreePool(DeviceInfo->SerialNumber); + } + + if (DeviceInfo->ScsiAddress) { + DsmpFreePool(DeviceInfo->ScsiAddress); + } + + // + // Fix up the Reservation List, if needed. + // + if (!freeGroup && Group->ReservationList) { + ULONG oldList; + + // + // Capture the list for debugging. + // + oldList = Group->ReservationList; + Group->ReservationList = 0; + + // + // Go through all devices in this group and find the one(s) registered. + // + for (i = 0; i < Group->NumberDevices; i++) { + + if (Group->DeviceList[i]->RegisterServiced) { + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmRemoveDeviceEntry (Group %p): Device %p at %d registered.\n", + Group, + Group->DeviceList[i], + i)); + + // + // Indicate its place. + // + Group->ReservationList |= (1 << i); + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmRemoveDeviceEntry (Group %p): Reservations Old (%x) New (%x).\n", + Group, + oldList, + Group->ReservationList)); + } + + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + // + // Free the allocation. + // + DsmpFreePool(DeviceInfo); + + if (freeGroup) { + + // + // Free the allocations. + // + if (Group->RegistryKeyName) { + DsmpFreePool(Group->RegistryKeyName); + } + + if (Group->HardwareId) { + DsmpFreePool(Group->HardwareId); + } + + DsmpFreePool(Group); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceEntry (Group %p): Exiting function - numberDevices = %x.\n", + tempAddress, + numberDevices)); + + return numberDevices; +} + + +VOID +DsmpRemoveDeviceFromTargetPortList( + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + This will remove a DeviceInfo from its target port device list. + + The caller should ensure that the DsmContext->SpinLock is held before + calling this function. + +Arguments: + + DeviceInfo - The DeviceInfo to be removed. + +Return Value: + + None + +--*/ +{ + if (DeviceInfo->TargetPort) { + + PLIST_ENTRY entry; + PDSM_TARGET_PORT_DEVICELIST_ENTRY listEntry; + + for (entry = DeviceInfo->TargetPort->TP_DeviceList.Flink; + entry != NULL && entry != &DeviceInfo->TargetPort->TP_DeviceList; + entry = entry->Flink) { + + listEntry = CONTAINING_RECORD(entry, DSM_TARGET_PORT_DEVICELIST_ENTRY, ListEntry); + + if (listEntry) { + + if (listEntry->DeviceInfo == DeviceInfo) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRemoveDeviceFromTargetPortList: Removing device %p from target port entry %p.\n", + DeviceInfo, + listEntry)); + + RemoveEntryList(entry); + InterlockedDecrement((LONG volatile*)&DeviceInfo->TargetPort->Count); + DsmpFreePool(listEntry); + + DeviceInfo->TargetPort = NULL; + DeviceInfo->TargetPortGroup = NULL; + + break; + } + } + } + } +} + + +VOID +DsmpRemoveZombieGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY ZombieGroup + ) +/* ++ + +Routine Description: + + This will scan through all the Failover Groups and remove the given Group + from each Failover Group's zombie group list. + + The DSM lock should be aquired by the caller. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + ZombieGroup - Group entry that should be removed from FOGs' ZombieGroupList + +Return Value: + + None + +-- */ +{ + // + // Run through the list of Fail-Over Groups + // + ULONG i; + PDSM_FAILOVER_GROUP failOverGroup = NULL; + PLIST_ENTRY fogEntry; + PLIST_ENTRY groupEntry; + PDSM_ZOMBIEGROUP_ENTRY zombieGroupEntry; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveZombieGroupEntry (Group %p): Entering function.\n", + ZombieGroup)); + + fogEntry = DsmContext->FailGroupList.Flink; + for (i = 0; fogEntry != NULL && i < DsmContext->NumberFOGroups; i++, fogEntry = fogEntry->Flink) { + + failOverGroup = CONTAINING_RECORD(fogEntry, DSM_FAILOVER_GROUP, ListEntry); + if (failOverGroup != NULL) { + + for (groupEntry = failOverGroup->ZombieGroupList.Flink; + groupEntry != &(failOverGroup->ZombieGroupList); + groupEntry = groupEntry->Flink) { + + zombieGroupEntry = CONTAINING_RECORD(groupEntry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); + if (zombieGroupEntry != NULL && + zombieGroupEntry->Group != NULL && + zombieGroupEntry->Group == ZombieGroup) { + + RemoveEntryList(groupEntry); + DsmpFreePool(zombieGroupEntry); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveZombieGroupEntry (Group %p): Found and removed a zombie group in (FOG %p)\n", + ZombieGroup, + failOverGroup)); + + // + // We removed the zombie group entry from this fail-over + // group, so we can move on to the next fail-over group. + // + break; + } + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveZombieGroupEntry (Group %p): Exiting function.\n", + ZombieGroup)); +} + + +VOID +DsmpRemoveGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY GroupEntry, + _In_ IN BOOLEAN AcquireDSMLockExclusive + ) +/*++ + +Routine Description: + + This will remove a group entry from the DSM's list. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + GroupEntry - Group entry that should be removed from DSM's list + AcquireDSMLockExclusive - If TRUE this routine should acquire DsmContextLock Exclusively + +Return Value: + + None + +--*/ +{ + KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 warnings + ULONG index; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup; + PLIST_ENTRY entry; + PDSM_TARGET_PORT_LIST_ENTRY targetPort; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveGroupEntry (Group %p): Entering function.\n", + GroupEntry)); + + if (AcquireDSMLockExclusive) { + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + } + + NT_ASSERT(GroupEntry && GroupEntry->ListEntry.Flink && GroupEntry->ListEntry.Blink); + + // + // Since this group is being removed, we need to make sure it is also + // removed from all fail-over groups' zombie group lists. + // + DsmpRemoveZombieGroupEntry(DsmContext, GroupEntry); + + // + // Add it to the list of multi-path groups. + // + RemoveEntryList(&GroupEntry->ListEntry); + + GroupEntry->ListEntry.Flink = GroupEntry->ListEntry.Blink = NULL; + + InterlockedDecrement((LONG volatile*)&DsmContext->NumberGroups); + + for (index = 0; index < DSM_MAX_PATHS; index++) { + + // + // Clean up all its Target Port Groups + // + targetPortGroup = GroupEntry->TargetPortGroupList[index]; + + if (targetPortGroup) { + + GroupEntry->TargetPortGroupList[index] = NULL; + + // + // For each target port group, clean up all its target ports + // + while (!IsListEmpty(&targetPortGroup->TargetPortList)) { + + entry = RemoveHeadList(&targetPortGroup->TargetPortList); + + if (entry) { + + targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); + + if (targetPort) { + + PLIST_ENTRY deviceEntry; + PDSM_TARGET_PORT_DEVICELIST_ENTRY listEntry; + + while (!IsListEmpty(&targetPort->TP_DeviceList)) { + + deviceEntry = RemoveHeadList(&targetPort->TP_DeviceList); + + if (deviceEntry) { + + listEntry = CONTAINING_RECORD(deviceEntry, + DSM_TARGET_PORT_DEVICELIST_ENTRY, + ListEntry); + + if (listEntry) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRemoveGroupEntry (Group %p): Deleting device %p from TP %p list (TPG %p).\n", + GroupEntry, + listEntry->DeviceInfo, + targetPort, + targetPortGroup)); + + DsmpFreePool(listEntry); + + InterlockedDecrement((LONG volatile*)&targetPort->Count); + } + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRemoveGroupEntry (Group %p): Deleting target port %p from TPG %p list.\n", + GroupEntry, + targetPort, + targetPortGroup)); + + DsmpFreePool(targetPort); + + InterlockedDecrement((LONG volatile*)&targetPortGroup->NumberTargetPorts); + } + } + } + + NT_ASSERT(targetPortGroup->NumberTargetPorts == 0); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRemoveGroupEntry (Group %p): Deleting target port group %p.\n", + GroupEntry, + targetPortGroup)); + + DsmpFreePool(targetPortGroup); + + InterlockedDecrement((LONG volatile*)&GroupEntry->NumberTargetPortGroups); + } + } + + NT_ASSERT(GroupEntry->NumberTargetPortGroups == 0); + + if (AcquireDSMLockExclusive) { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRemoveGroupEntry (Group %p): Exiting function.\n", + GroupEntry)); + + return; +} + + +PDSM_FAILOVER_GROUP +DsmpSetNewPath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDevice + ) +/*++ + +Routine Description: + + This routine will assign a new path to the multi-path group in + which FailingDevice resides. + + Caller must NOT hold spin lock. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + + FailingDevice - The device-path that is being moved + (due to failure, or admin. request) + +Return Value: + + The FOG containing the new path. + +--*/ +{ + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpSetNewPath (DevInfo %p): Entering function.\n", + FailingDevice)); + + if (DsmpIsSymmetricAccess(FailingDevice)) { + + DsmpSetLBForPathRemoval(DsmContext, FailingDevice, NULL, SpecialHandlingFlag); + + } else { + + DsmpSetLBForPathRemovalALUA(DsmContext, FailingDevice, NULL, SpecialHandlingFlag); + } + + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpSetNewPath (DevInfo %p): Exiting function with path (failGroup) %p.\n", + FailingDevice, + FailingDevice->Group->PathToBeUsed)); + + return FailingDevice->Group->PathToBeUsed; +} + + +PDSM_FAILOVER_GROUP +DsmpSetNewPathUsingGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group + ) +/*++ + +Routine Description: + + This routine will try to assign a new path using the given multi-path group. + This function should only be called during failover in the event that there + is no DeviceInfo with which to call DsmpSetNewPath(). + + Typically this will be called with one of a fail-over group's zombie groups. + + Caller must NOT hold spin lock. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization. + + Group - The multi-path group which to assign a new path. + +Return Value: + + The FOG containing the new path or NULL if no path was found. + +--*/ + +{ + ULONG i; + PDSM_DEVICE_INFO pDevInfo = NULL; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetNewPathUsingGroup (Group %p): Entering function.\n", + Group)); + + // + // Get the first available DeviceInfo. + // + for (i = 0; i < DSM_MAX_PATHS; i ++) { + if (Group->DeviceList[i] != NULL) { + pDevInfo = Group->DeviceList[i]; + break; + } + } + + if (pDevInfo == NULL) { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetNewPathForZombieGroup (ZombieGroup %p): No failover group can be found.\n", + Group)); + return NULL; + } + + + if (DsmpIsSymmetricAccess(pDevInfo)) { + + DsmpSetLBForPathRemoval(DsmContext, pDevInfo, Group, SpecialHandlingFlag); + + } else { + + DsmpSetLBForPathRemovalALUA(DsmContext, pDevInfo, Group, SpecialHandlingFlag); + } + + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetNewPathForZombieGroup (ZombieGroup %p): Exiting function with path (failGroup) %p.\n", + Group, + Group->PathToBeUsed)); + + return Group->PathToBeUsed; + +} + + +NTSTATUS +DsmpUpdateTargetPortGroupDevicesStates( + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN DSM_DEVICE_STATE NewState + ) +/*++ + +Routine Description: + + This routine will update the target port group and all its appropriate + devInfos (ones not in remove pending, removed, or invalidated) with the + new state. The ALUAState will only be updated, NOT the real State. + Caller needs to update the real State based on the current LB policy. + + Note: This should be called with DsmContext Lock held and should only be + called after a SetTargetPortGroups request was sent down. + +Arguments: + + TargetPortGroup - TargetPortGroup whose state and deviceInfos need to be + updated + + NewState - The new state + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PLIST_ENTRY entry = NULL; + PDSM_TARGET_PORT_LIST_ENTRY targetPort = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Entering function.\n", + TargetPortGroup)); + + if (!TargetPortGroup) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Invalid TPG passed in.\n", + TargetPortGroup)); + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpUpdateTargetPortGroupDevicesStates; + } + + // + // First update TPG's asymmetric access state. + // + TargetPortGroup->AsymmetricAccessState = NewState; + + // + // Now update state of each of the devices belonging to this TPG. + // + for (entry = TargetPortGroup->TargetPortList.Flink; + entry != &TargetPortGroup->TargetPortList; + entry = entry->Flink) { + + targetPort = CONTAINING_RECORD(entry, DSM_TARGET_PORT_LIST_ENTRY, ListEntry); + NT_ASSERT(targetPort); + + if (targetPort) { + + PLIST_ENTRY deviceEntry; + PDSM_TARGET_PORT_DEVICELIST_ENTRY tp_device; + + for (deviceEntry = targetPort->TP_DeviceList.Flink; + deviceEntry != &targetPort->TP_DeviceList; + deviceEntry = deviceEntry->Flink) { + + tp_device = CONTAINING_RECORD(deviceEntry, + DSM_TARGET_PORT_DEVICELIST_ENTRY, + ListEntry); + + if (tp_device) { + + tp_device->DeviceInfo->ALUAState = NewState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Updated device %p alua state to %x.\n", + TargetPortGroup, + tp_device->DeviceInfo, + tp_device->DeviceInfo->ALUAState)); + } + } + } + } + +__Exit_DsmpUpdateTargetPortGroupDevicesStates: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpUpdateTargetPortGroupDevicesStates (TPG %p): Exiting function with status %x.\n", + TargetPortGroup, + status)); + + return status; +} + + +VOID +DsmpIncrementCounters( + _In_ PDSM_FAILOVER_GROUP FailGroup, + _In_ PSCSI_REQUEST_BLOCK Srb + ) +{ + ULONG bytes = 0; + PCDB cdb = NULL; + ULONG cdbLength = 0; + BOOLEAN isReadWrite = FALSE; + ULONGLONG lastLba = 0; + ULONG numBlocks = 0; + ULONGLONG startLba = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpIncrementCounters (FOG %p): Entering function.\n", + FailGroup)); + + if (Srb) { + + cdb = SrbGetCdb(Srb); + + if (cdb && DsmIsReadWrite(cdb->AsByte[0])) { + + isReadWrite = TRUE; + } + } + + InterlockedIncrement(&FailGroup->NumberOfRequestsInFlight); + + // + // Update counters that apply to read/write requests + // + if (isReadWrite) { + + bytes = SrbGetDataTransferLength(Srb); + + InterlockedExchangeAdd64((LONGLONG volatile*)&FailGroup->OutstandingBytesOfIO, bytes); + + cdbLength = SrbGetCdbLength(Srb); + + if (cdbLength == 16) { + + REVERSE_BYTES_QUAD(&startLba, &cdb->CDB16.LogicalBlock); + REVERSE_BYTES(&numBlocks, &cdb->CDB16.TransferLength); + + } else { + + REVERSE_BYTES(&startLba, &cdb->CDB10.LogicalBlockByte0); + REVERSE_BYTES_SHORT(&numBlocks, &cdb->CDB10.TransferBlocksMsb); + } + + lastLba = startLba + numBlocks - 1; + + InterlockedExchange64((LONGLONG volatile*)&FailGroup->LastLba, lastLba); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpIncrementCounters (FOG %p): Exiting function.\n", + FailGroup)); + + return; +} + + +BOOLEAN +DsmpDecrementCounters( + _In_ PDSM_FAILOVER_GROUP FailGroup, + _In_ PSCSI_REQUEST_BLOCK Srb + ) +{ + ULONG bytes = 0; + PCDB cdb = NULL; + BOOLEAN isReadWrite = FALSE; + BOOLEAN isDeletionEligible = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpDecrementCounters (FOG %p): Entering function.\n", + FailGroup)); + + if (Srb) { + + cdb = SrbGetCdb(Srb); + + if (cdb && DsmIsReadWrite(cdb->AsByte[0])) { + + isReadWrite = TRUE; + } + } + + // + // Update counters that apply to read/write requests + // + if (isReadWrite) { + + bytes = SrbGetDataTransferLength(Srb); + + InterlockedExchangeAdd64((LONGLONG volatile*)&FailGroup->OutstandingBytesOfIO, -(LONGLONG)bytes); + } + + NT_ASSERT(FailGroup->NumberOfRequestsInFlight > 0); + if (InterlockedCompareExchange(&FailGroup->NumberOfRequestsInFlight, 0, 0) > 0) { + + if(InterlockedDecrement(&FailGroup->NumberOfRequestsInFlight) == 0){ + + // + // If the inflight requests on the path is zero, if needed path can be removed. + // + isDeletionEligible = TRUE; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpDecrementCounters (FOG %p): Exiting function.\n", + FailGroup)); + + return isDeletionEligible; +} + + +PDSM_FAILOVER_GROUP +DsmpGetPath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmList, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine will pick a path, for processing a request, based + on the current LoadBalance policy that is set. + + N.B: This routine must be called with DSM Context Lock held in Shared mode. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DsmList - List of DSM Ids sent by MPIO + Srb - The read/write/verify request + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + FailOver Group that should be used for processing the request +--*/ +{ + // + // Algorithm: + // ========== + // Failover-only: + // -------------- + // If symmetric LUA (ie. ALUA not supported, or symmetric LUA using ALUA semantics (viz. storage reports + // implicit-only transitions and all TPGs in A/O): + // One path AO, <- this will be the only path used for I/O + // M paths in SB, <- one of these will be made active on failure of the above active path + // Rest of the paths Failed (Invalidated/PendingRemove/Removed) + // + // If ALUA: + // One path AO, <- this will be the only path used for I/O + // M paths in AU, SB or UA <- one of these made active on failover. Pref: AU > SB > UA. Also, controller affinity. + // Rest of the paths Failed + // + // Automatic failback will happen only if Preferred path has been set. + // This is the only policy that will support failback. + // + // Round-Robin: + // ------------ + // If symmetric LUA: + // N paths AO, <- round robin among these + // Rest of the paths Failed + // + // If ALUA: + // Round Robin policy not supported since all paths can't be in A/O state. + // + // Round-Robin With Subset: + // ------------------------ + // If symmetric LUA: + // N paths AO, <- round robin among these + // M paths SB, <- if no active paths left, make one of these active + // Rest of the paths Failed + // + // If ALUA: + // N paths AO, <- round robin among these (NOTE: paths in AU not considered) + // M paths AU, SB or UA <- if no active paths, make subset of these active (based on TPG states after transition) + // Rest of the paths Failed + // + // Least-Queue Depth: + // ------------------ + // If symmetric LUA: + // N paths AO, <- one with least outstanding I/O is chosen + // Rest of the paths Failed + // + // If ALUA: + // N paths AO, <- one with least outstanding I/O is chosen + // M paths AU, SB or UA <- if no AO paths available, subset of these become active (based on TPG + // states after transition) - one with least outstanding I/O is chosen. + // Rest of the paths Failed + // + // Least-Weighted: + // --------------- + // If symmetric LUA: + // N paths AO, <- every path has an associated weight, path with least weight is used. + // Rest of the paths Failed + // + // If ALUA: + // N paths AO, + // M paths AU, SB or UA <- if no AO paths available, subset of these become active (based on TPG + // states after transition) - path with least weight used. + // Rest of the paths Failed + // + // Least-Blocks: + // ------------- + // If symmetric LUA: + // N paths AO, <- one with least cumulative outstanding IO is chosen + // Rest of the paths Failed + // + // If ALUA: + // N paths AO, <- one with least cumulative outstanding IO is chosen + // M paths AU, SB or UA <- if no AO paths available, subset of these become active (based on TPG + // states after transition) - one with least cumulative outstanding is chosen. + // + // Actual implementation of algorithm happens in the following routines: DsmpGetAnyActivePath, + // DsmpGetActivePathToBeUsed, flavors of DsmpSetLBForPathXXX. + // + + PDSM_FAILOVER_GROUP failGroup = NULL; + PDSM_DEVICE_INFO deviceInfo = DsmList->IdList[0]; + PDSM_GROUP_ENTRY groupEntry; + ULONG inx = 0; + + UNREFERENCED_PARAMETER(DsmContext); + UNREFERENCED_PARAMETER(SpecialHandlingFlag); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Entering function.\n", + DsmList)); + + if (!(DsmList->Count && deviceInfo)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Called with no available paths.\n", + DsmList)); + + goto __Exit_DsmpGetPath; + } + + groupEntry = deviceInfo->Group; + DSM_ASSERT(groupEntry->GroupSig == DSM_GROUP_SIG); + + switch (groupEntry->LoadBalanceType) { + + case DSM_LB_FAILOVER: + case DSM_LB_WEIGHTED_PATHS: { + + // + // For FailOverOnly there is only one active path so we can + // just grab it from the cached location and go with it. + // For LeastWeightPath we always choose the lowest weighted + // one so we grab that and go + // + failGroup = groupEntry->PathToBeUsed; + + break; + } + + case DSM_LB_ROUND_ROBIN: + case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { + + PDSM_DEVICE_INFO candidateDevice = NULL; + PDSM_GROUP_ENTRY newGroup = NULL; + ULONG newPath; + BOOLEAN foundPath = FALSE; + ULONG jnx = 0; + ULONG counter = 0; + BOOLEAN reset = FALSE; + + for (inx = 0; inx < DsmList->Count; inx++) { + + deviceInfo = DsmList->IdList[inx]; + + if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { + + continue; + } + + + if (deviceInfo->FailGroup == groupEntry->PathToBeUsed) { + + // + // We've reached the devInfo that corresponds to the path + // that we should be using. If this devInfo is not in the + // right state to be used, we need to find the first candidate + // starting from this one to satisfy the request. + // To play it safe, we may have already considered a previous + // devInfo to be a candidate, that now needs to be reset to + // the one that we now find. + // + reset = TRUE; + } + +#if DBG + if (deviceInfo->TargetPortGroup && !DsmpIsDeviceFailedState(deviceInfo->State)) { + + if (deviceInfo->State != deviceInfo->ALUAState) { + + DSM_ASSERT(groupEntry->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET && + deviceInfo->State == DSM_DEV_ACTIVE_UNOPTIMIZED && + deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED); + } + } +#endif + + if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { + + if (!candidateDevice || reset) { + + candidateDevice = deviceInfo; + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Candidate device %p.\n", + DsmList, + candidateDevice)); + + jnx = inx; + } + + if (!groupEntry->PathToBeUsed || deviceInfo->FailGroup == groupEntry->PathToBeUsed) { + + // + // The devInfo that corresponds to the path that we were + // supposed to use, is in a state that makes it usable. + // So we've found our devInfo. + // + InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)deviceInfo->FailGroup); + foundPath = TRUE; + candidateDevice = NULL; + + break; + } + } + } + + if (!foundPath) { + + if (candidateDevice) { + + InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)candidateDevice->FailGroup); + inx = jnx; + candidateDevice = NULL; + + } else { + + inx = 0; + } + } + + failGroup = groupEntry->PathToBeUsed; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Path to be used is %p.\n", + DsmList, + groupEntry->PathToBeUsed)); + + // + // The current chosen path is given by failGroup. Find the next path + // that should be chosen in the RoundRobin policy. Start with the + // device at index inx + 1, and look for the one with Active state. + // + for (counter = 0, jnx = inx + 1; + counter < DsmList->Count && !newGroup; + counter++, jnx++) { + + newPath = jnx % DsmList->Count; + + deviceInfo = DsmList->IdList[newPath]; + + if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { + + continue; + } + + + if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { + + newGroup = deviceInfo->Group; + DSM_ASSERT(newGroup == groupEntry); + + InterlockedExchangePointer(&(newGroup->PathToBeUsed), (PVOID)deviceInfo->FailGroup); + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): New Path is %p.\n", + DsmList, + newGroup->PathToBeUsed)); + + break; + } + } + + break; + } + + case DSM_LB_DYN_LEAST_QUEUE_DEPTH: { + + LONG leastQueueDepth = 0x7FFFFFFF; + + for (inx = 0; inx < DsmList->Count; inx++) { + + deviceInfo = DsmList->IdList[inx]; + + if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { + + continue; + } + + + if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED && + deviceInfo->FailGroup->NumberOfRequestsInFlight < leastQueueDepth) { + + leastQueueDepth = deviceInfo->FailGroup->NumberOfRequestsInFlight; + failGroup = deviceInfo->FailGroup; + } + } + + if (failGroup) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Path to be used for LQD is %p.\n", + DsmList, + failGroup)); + + } else { + + // + // For ALUA storage there are two cases where we are left with no + // TPG in the A/O state: + // 1) On storage that supports implicit transitions, a transition + // was initiated that left no TPG in the A/O state. + // 2) On storage that has explicit only transitions enabled, we tried + // making at least one path as A/O and failed. This can happen, + // for example, when STPG fails because this initiator is not + // registered or does not hold exclusive reservation over the + // target. + // + // For such storages, we should return some path instead of just + // failing the I/O. The path will likely be an A/U path until the + // storage does a transition to make a TPG A/O. + // + if (!DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmList->IdList[0])) { + + // + // Use the same path as the one used for the previous request. + // + failGroup = groupEntry->PathToBeUsed; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpGetPath (DsmIds %p): Using same path (FOG %p) as previous request for LQD.\n", + DsmList, + failGroup)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Failed to find a path for LQD.\n", + DsmList)); + } + } + + break; + } + + case DSM_LB_LEAST_BLOCKS: { + + ULONG bytes = 0; + PCDB cdb = NULL; + ULONG cdbLength = 0; + BOOLEAN isRead = FALSE; + BOOLEAN isWrite = FALSE; + PDSM_FAILOVER_GROUP lastPathUsed = groupEntry->PathToBeUsed; + ULONGLONG leastOutstandingIO = MAXULONGLONG; + ULONGLONG startLba = 0; + + // + // Use the last path under the following conditions: + // + // 1. This is not a read/write request or + // 2. This is a read/write request and + // a. The request is sequential and + // b. The cache is not exhausted + // + + if (Srb) { + + cdb = SrbGetCdb(Srb); + + if (cdb && DsmIsReadRequest(cdb->AsByte[0])) { + + isRead = TRUE; + } + + if (cdb && DsmIsWriteRequest(cdb->AsByte[0])) { + + isWrite = TRUE; + } + } + + if (isRead || isWrite) { + + if (groupEntry->UseCacheForLeastBlocks) { + + bytes = SrbGetDataTransferLength(Srb); + + cdbLength = SrbGetCdbLength(Srb); + + if (cdbLength == 16) { + + REVERSE_BYTES_QUAD(&startLba, &cdb->CDB16.LogicalBlock); + + } else { + + REVERSE_BYTES(&startLba, &cdb->CDB10.LogicalBlockByte0); + } + + // + // Check if: + // 1. The IO is sequential, AND + // 2. It is either: + // a. read request, OR + // b. write request and outstanding bytes will be within the cache limit + // + if ((lastPathUsed != NULL) && + (startLba >= lastPathUsed->LastLba) && + ((isRead) || + (isWrite && lastPathUsed->OutstandingBytesOfIO + bytes <= groupEntry->CacheSizeForLeastBlocks))) { + + failGroup = groupEntry->PathToBeUsed; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Sequential IO, so using same path %p for LeastBlocks.\n", + DsmList, + failGroup)); + } + } + + } else { + // + // The request is neither a read nor a write so use the same path. + // + failGroup = groupEntry->PathToBeUsed; + } + + if (!failGroup) { + + // + // Choose whichever Active/Optimized path has the least outstanding bytes. + // + for (inx = 0; inx < DsmList->Count; inx++) { + + deviceInfo = DsmList->IdList[inx]; + + if (!(deviceInfo && DsmpIsDeviceInitialized(deviceInfo) && DsmpIsDeviceUsable(deviceInfo) && DsmpIsDeviceUsablePR(deviceInfo))) { + + continue; + } + + + if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED && + deviceInfo->FailGroup->OutstandingBytesOfIO < leastOutstandingIO) { + + leastOutstandingIO = deviceInfo->FailGroup->OutstandingBytesOfIO; + failGroup = deviceInfo->FailGroup; + } + } + } + + if (failGroup) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Path to be used for LeastBlocks is %p.\n", + DsmList, + failGroup)); + + } else { + + // + // For ALUA storage there are two cases where we are left with no + // TPG in the A/O state: + // 1) On storage that supports implicit transitions, a transition + // was initiated that left no TPG in the A/O state. + // 2) On storage that has explicit only transitions enabled, we tried + // making at least one path as A/O and failed. This can happen, + // for example, when STPG fails because this initiator is not + // registered or does not hold exclusive reservation over the + // target. + // + // For such storages, we should return some path instead of just + // failing the I/O. The path will likely be an A/U path until the + // storage does a transition to make a TPG A/O. + // + if (!DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmList->IdList[0])) { + + // + // Use the same path as the one used for the previous request. + // + failGroup = groupEntry->PathToBeUsed; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpGetPath (DsmIds %p): Using same path (FOG %p) as previous request for LeastBlocks.\n", + DsmList, + failGroup)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Failed to find a path for LeastBlocks.\n", + DsmList)); + } + } + + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Invalid LB Type %d set for group %p.\n", + DsmList, + groupEntry->LoadBalanceType, + groupEntry)); + + DSM_ASSERT(FALSE); + + break; + } + } + +__Exit_DsmpGetPath: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpGetPath (DsmIds %p): Exiting function with failGroup %p.\n", + DsmList, + failGroup)); + + return failGroup; +} + + +PVOID +DsmpGetPathIdFromPassThroughPath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmList, + _In_ PIRP Irp, + _Inout_ IN OUT NTSTATUS *Status + ) +/*++ + +Routine Description: + + This routine will pick the path that corresponds to the PathId + in the mpio pass through structure. + + NOTE: Caller must ensure that the IRP is either MPTP or MPTPD. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DsmList - List of DSM Ids sent by MPIO + Irp - The MPTP or MPTPD request + Status - Returned status + +Return Value: + + The PathId to which the request should be sent +--*/ +{ + PDSM_FAILOVER_GROUP failGroup = NULL; + PDSM_GROUP_ENTRY groupEntry; + PDSM_DEVICE_INFO deviceInfo; + ULONG inx = 0; + NTSTATUS status = STATUS_INVALID_PARAMETER; + KIRQL irql; + PVOID newPath = NULL; + BOOLEAN found = FALSE; + BOOLEAN useScsiAddress = FALSE; + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + ULONG controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; + UCHAR pathId = 0; + UCHAR targetId = 0; + UCHAR portNumber = 0; + ULONGLONG mpioPathId = 0; + +#if DBG + BOOLEAN useMpioPathId = FALSE; +#endif + + // + // Extract the parameters from the passthrough based on the bitness of the + // process (32 or 64) and the type of passthrough (legacy or extended). + // +#if defined (_WIN64) + if (IoIs32bitProcess(Irp)) { + + if (DsmpIsMPIOPassThroughEx(controlCode)) { + PMPIO_PASS_THROUGH_PATH32_EX mpioPassThroughPath32 = (PMPIO_PASS_THROUGH_PATH32_EX)(Irp->AssociatedIrp.SystemBuffer); + PSCSI_PASS_THROUGH32_EX passThrough32 = (PSCSI_PASS_THROUGH32_EX)((PUCHAR)mpioPassThroughPath32 + mpioPassThroughPath32->PassThroughOffset); + + useScsiAddress = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; + #if DBG + useMpioPathId = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_PATHID; + #endif + + if (useScsiAddress) { + PSTOR_ADDRESS address; + if (passThrough32->StorAddressOffset < sizeof(SCSI_PASS_THROUGH_EX) || + passThrough32->StorAddressLength < sizeof(STOR_ADDRESS)) { + *Status = STATUS_INVALID_PARAMETER; + return NULL; + } + address = (PSTOR_ADDRESS)((PUCHAR)passThrough32 + passThrough32->StorAddressOffset); + if (address->Type != STOR_ADDRESS_TYPE_BTL8 || + address->AddressLength < STOR_ADDR_BTL8_ADDRESS_LENGTH) { + *Status = STATUS_INVALID_PARAMETER; + return NULL; + } + pathId = ((PSTOR_ADDR_BTL8)address)->Path; + targetId = ((PSTOR_ADDR_BTL8)address)->Target; + portNumber = mpioPassThroughPath32->PortNumber; + } else { + mpioPathId = mpioPassThroughPath32->MpioPathId; + } + + } else { + PMPIO_PASS_THROUGH_PATH32 mpioPassThroughPath32 = (PMPIO_PASS_THROUGH_PATH32)(Irp->AssociatedIrp.SystemBuffer); + + useScsiAddress = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; + #if DBG + useMpioPathId = mpioPassThroughPath32->Flags & MPIO_IOCTL_FLAG_USE_PATHID; + #endif + + if (useScsiAddress) { + pathId = mpioPassThroughPath32->PassThrough.PathId; + targetId = mpioPassThroughPath32->PassThrough.TargetId; + portNumber = mpioPassThroughPath32->PortNumber; + } else { + mpioPathId = mpioPassThroughPath32->MpioPathId; + } + } + } else +#endif + if (DsmpIsMPIOPassThroughEx(controlCode)) { + PMPIO_PASS_THROUGH_PATH_EX mpioPassThroughPath = (PMPIO_PASS_THROUGH_PATH_EX)(Irp->AssociatedIrp.SystemBuffer); + PSCSI_PASS_THROUGH_EX passThrough = (PSCSI_PASS_THROUGH_EX)((PUCHAR)mpioPassThroughPath + mpioPassThroughPath->PassThroughOffset); + + useScsiAddress = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; + #if DBG + useMpioPathId = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_PATHID; + #endif + + if (useScsiAddress) { + PSTOR_ADDRESS address; + if (passThrough->StorAddressOffset < sizeof(SCSI_PASS_THROUGH_EX) || + passThrough->StorAddressLength < sizeof(STOR_ADDRESS)) { + *Status = STATUS_INVALID_PARAMETER; + return NULL; + } + address = (PSTOR_ADDRESS)((PUCHAR)passThrough + passThrough->StorAddressOffset); + if (address->Type != STOR_ADDRESS_TYPE_BTL8 || + address->AddressLength < STOR_ADDR_BTL8_ADDRESS_LENGTH) { + *Status = STATUS_INVALID_PARAMETER; + return NULL; + } + pathId = ((PSTOR_ADDR_BTL8)address)->Path; + targetId = ((PSTOR_ADDR_BTL8)address)->Target; + portNumber = mpioPassThroughPath->PortNumber; + } else { + mpioPathId = mpioPassThroughPath->MpioPathId; + } + } else { + PMPIO_PASS_THROUGH_PATH mpioPassThroughPath = (PMPIO_PASS_THROUGH_PATH)(Irp->AssociatedIrp.SystemBuffer); + + useScsiAddress = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_SCSIADDRESS; + #if DBG + useMpioPathId = mpioPassThroughPath->Flags & MPIO_IOCTL_FLAG_USE_PATHID; + #endif + + if (useScsiAddress) { + pathId = mpioPassThroughPath->PassThrough.PathId; + targetId = mpioPassThroughPath->PassThrough.TargetId; + portNumber = mpioPassThroughPath->PortNumber; + } else { + mpioPathId = mpioPassThroughPath->MpioPathId; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpGetPathIdFromPassThroughPath (DsmIds %p): Entering function.\n", + DsmList)); + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + deviceInfo = DsmList->IdList[0]; + groupEntry = deviceInfo->Group; + DSM_ASSERT(groupEntry->GroupSig == DSM_GROUP_SIG); + // + // useMpioPathId is BOOLEAN (0 or 1) since MPIO_IOCTL_FLAG_USE_PATHID = 1 + // But since MPIO_IOCTL_FLAG_USE_SCSIADDRESS = 0x2, + // useScsiAddress could have a value of 2 if set. Use logical NOT to make boolean before comparing below + // + DSM_ASSERT(useMpioPathId == !useScsiAddress); + + for (inx = 0; inx < DSM_MAX_PATHS; inx++) { + + deviceInfo = groupEntry->DeviceList[inx]; + + if (deviceInfo) { + + failGroup = deviceInfo->FailGroup; + + if (failGroup) { + + if (useScsiAddress) { + + if (portNumber == deviceInfo->ScsiAddress->PortNumber && + pathId == deviceInfo->ScsiAddress->PathId && + targetId == deviceInfo->ScsiAddress->TargetId) { + + found = TRUE; + break; + } + } else { + + NT_ASSERT(useMpioPathId); + + if ((ULONGLONG)((ULONG_PTR)(failGroup->PathId)) == mpioPathId) { + + found = TRUE; + break; + } + } + } + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + if (found) { + + newPath = failGroup->PathId; + status = STATUS_SUCCESS; + + // + // This should not affect the next path chosen based on the + // current LB policy, so do NOT update groupEntry->PathToBeUsed + // + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpGetPathIdFromPassThroughPath (DsmIds %p): Failed to get corresponding path.\n", + DsmList)); + } + + if (Status) { + + *Status = status; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpGetPathIdFromPassThroughPath (DsmIds %p): Exiting function with path %p and status %x.\n", + DsmList, + newPath, + status)); + + return newPath; +} + + +BOOLEAN +DsmpShouldRetryTPGRequest( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ) +/*++ + +Routine Description: + + This routine determines if a Report/Set TargetPortGroup request (sent either + as a passThrough or as an IRP_MJ_SCSI) needs to be retried. + +Arguments: + + SenseData - Pointer to Sense Data information buffer. + SenseDataSize - Size of the passed in sense data buffer. + +Return Value: + + TRUE if sense information indicates a retry-able error, else FALSE. + +--*/ +{ + BOOLEAN retry = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryTPGRequest (SenseData %p): Entering function.\n", + SenseData)); + + // + // Two types of conditions need to be retried: + // 1. Asymmetric Access State Changed + // 2. Asymmetric Access State Transition + // + + // + // Check if asymmetric access state changed + // + retry = DsmpShouldRetryPassThroughRequest(SenseData, SenseDataSize); + if (!retry) { + + BOOLEAN validSense = FALSE; + UCHAR senseKey = 0; + UCHAR addSenseCode = 0; + UCHAR addSenseCodeQualifier = 0; + + validSense = ScsiGetSenseKeyAndCodes(SenseData, + SenseDataSize, + SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, + &senseKey, + &addSenseCode, + &addSenseCodeQualifier); + if (validSense) { + + if (senseKey == SCSI_SENSE_NOT_READY) { + + switch (addSenseCode) { + case SCSI_ADSENSE_LUN_NOT_READY: { + + // + // Check if asymmetric access state transitioning + // + if (addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION) { + + retry = TRUE; + } + break; + } + + case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: { + + if (addSenseCodeQualifier == SCSI_SENSEQ_REPORTED_LUNS_DATA_CHANGED) { + + retry = TRUE; + } + break; + } + + default: { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryTPGRequest (SenseData %p): AddSenseCode %x. Not retrying.\n", + SenseData, + addSenseCode)); + + retry = FALSE; + break; + } + } + } + } else { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryTPGRequest (SenseData %p): Sense data size %d not big enough.\n", + SenseData, + SenseDataSize)); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryTPGRequest (SenseData %p): Exiting function with retry %x.\n", + SenseData, + retry)); + + return retry; +} + + +BOOLEAN +DsmpIsDeviceRemoved( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ) +/*++ + +Routine Description: + + This routine evaluate Sense Data and determine if LUN is available or not. + +Arguments: + + SenseData - Pointer to Sense Data information buffer. + SenseDataSize - Size of the passed in sense data buffer. + +Return Value: + + TRUE if device is no longer available, else FALSE. + +--*/ +{ + BOOLEAN validSense = FALSE; + UCHAR senseKey = 0; + UCHAR addSenseCode = 0; + UCHAR addSenseCodeQualifier = 0; + BOOLEAN bRemoved = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpIsDeviceRemoved (SenseData %p): Entering function.\n", + SenseData)); + + validSense = ScsiGetSenseKeyAndCodes(SenseData, + SenseDataSize, + SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, + &senseKey, + &addSenseCode, + &addSenseCodeQualifier); + + if (validSense) { + // + // SPC 3 6.25 suggests response should follow Test Unit Ready responses + // For now, we accept Ileegal Request as an indication of device not in available + // state. + // + if (senseKey == SCSI_SENSE_ILLEGAL_REQUEST) { + + ASSERT(addSenseCodeQualifier == 0); //LOGICAL UNIT NOT SUPPORTED + + bRemoved = TRUE; + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpIsDeviceRemoved (SenseData %p): SenseKey %x AddSenseCode %x. Remove %x\n", + SenseData, + senseKey, + addSenseCode, + bRemoved)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpIsDeviceRemoved (SenseData %p): Exiting function. Removed %x.\n", + SenseData, + bRemoved)); + + return bRemoved; +} + + +BOOLEAN +DsmpReservationCommand( + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb + ) +/*++ + +Routine Description: + + This routine examines the DeviceIoControlCode and Srb OpCode to determine + if this is PR request. + +Arguments: + + Irp - The Irp containing Srb. + Srb - The current non-read/write Srb. + +Return Value: + + TRUE - If it's a special-case command (some reservation-handling request). + +--*/ +{ + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + UCHAR opCode = 0; + BOOLEAN isReservationCommand = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpReservationCommand (Irp %p): Entering function.\n", + Irp)); + + // + // Ensure it's a scsi request before checking the opcode. + // + if (irpStack->MajorFunction == IRP_MJ_SCSI) { + + PCDB cdb = SrbGetCdb(Srb); + if (cdb != NULL) { + opCode = cdb->AsByte[0]; + + if (opCode == SCSIOP_PERSISTENT_RESERVE_IN || opCode == SCSIOP_PERSISTENT_RESERVE_OUT) { + + // + // Set or release a reservation. + // + isReservationCommand = TRUE; + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpReservationCommand (Irp %p): Exiting function - IsReservationCmd %x.\n", + Irp, + isReservationCommand)); + + return isReservationCommand; +} + + +BOOLEAN +DsmpMpioPassThroughPathCommand( + _In_ IN PIRP Irp + ) +/*++ + +Routine Description: + + This routine examines the DeviceIoControlCode to determine whether this is + either a mpio pass through or a mpio pass through direct. If so, it needs + to be handled via a specific path indicated by the caller. + +Arguments: + + Irp - The Irp. + +Return Value: + + TRUE - If it is either MPTP or MPTPD. + FALSE - Otherwise. + +--*/ +{ + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + ULONG ioctlCode; + BOOLEAN isMPTPCommand = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpMpioPassThroughPathCommand (Irp %p): Entering function.\n", + Irp)); + + if (irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) { + + // + // Check whether this is a MPTP, MPTPD, or an extended flavor. + // + ioctlCode = irpStack->Parameters.DeviceIoControl.IoControlCode; + + if (ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH || + ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH_DIRECT || + ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH_EX || + ioctlCode == IOCTL_MPIO_PASS_THROUGH_PATH_DIRECT_EX) { + + isMPTPCommand = TRUE; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpMpioPassThroughPathCommand (Irp %p): Exiting function - IsMpioPassThruPathCmd %!bool!.\n", + Irp, + isMPTPCommand)); + + return isMPTPCommand; +} + + +VOID +DsmpRequestComplete( + _In_ IN PVOID DsmId, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PVOID DsmContext + ) +/*++ + +Routine Description: + + This routine is called from mpio's completion routine when the Irp + has been completed by the port driver. Currently, it updates some counters + and free's the context back to the look-aside list. + +Arguments: + + DsmIds - The collection of DSM IDs that pertain to the MPDISK. + Irp - Irp containing SRB. + Srb - Scsi request block + DsmContext - DSM context given to MPIO during initialization + +Return Value: + + NONE + +--*/ + +{ + PDSM_DEVICE_INFO deviceInfo = DsmId; + PDSM_CONTEXT dsmContext = (PDSM_CONTEXT)DsmContext; + UCHAR opCode = 0xFF; + ULONG dataTransferLength = 0; + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PDSM_FAILOVER_GROUP failGroup = irpStack->Parameters.Others.Argument3; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpRequestComplete (DevInfo %p): Entering function.\n", + DsmId)); + + DSM_ASSERT(DsmContext); + + if (Srb) { + PCDB cdb = SrbGetCdb(Srb); + if (cdb) { + opCode = cdb->AsByte[0]; + } + dataTransferLength = SrbGetDataTransferLength(Srb); + } + + // + // Extract the interesting bits from the context struct. + // + + if (failGroup) { + + if (DsmpDecrementCounters(failGroup, Srb)) { + + // + // If there are no requests on a path that is supposed to be removed, remove it now. + // + if (failGroup->State == DSM_FG_PENDING_REMOVE) { + + KIRQL oldIrql; + + NT_ASSERT(failGroup->Count == 0); + + oldIrql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + RemoveEntryList(&failGroup->ListEntry); + InterlockedDecrement((LONG volatile*)&dsmContext->NumberStaleFOGroups); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpRequestComplete (DevInfo %p): Removing FOGroup %p with path %p.\n", + DsmId, + failGroup, + failGroup->PathId)); + + DsmpFreePool(failGroup); + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), oldIrql); + } + } + } + + // + // Note: We use the deviceInfo passed in since the one saved off in the + // context may be stale in the case of a retried I/O + // + if (deviceInfo) { + + // + // If statistics gathering is enabled update the inflight request count + // for this device-path pairing. + // + if (!dsmContext->DisableStatsGathering) { + + // + // Indicate one less request on this device. + // Update the path that on which the increment was done. + // + if (InterlockedCompareExchange((LONG volatile*)&deviceInfo->NumberOfRequestsInProgress, 0, 0) > 0) { + InterlockedDecrement(&(deviceInfo->NumberOfRequestsInProgress)); + } + } + + // + // If statistics gathering is enabled, we are interested in read/write requests + // + if (!dsmContext->DisableStatsGathering) { + + // + // If it's a read or a write, update the stats. + // Use the path that was cached during dispatch. + // + if (DsmIsReadRequest(opCode)) { + + if (deviceInfo->DeviceStats.NumberReads <= MAXULONG) { + + InterlockedIncrement((LONG volatile*)&deviceInfo->DeviceStats.NumberReads); + } + + if ((MAXULONGLONG - dataTransferLength) > deviceInfo->DeviceStats.BytesRead) { + + deviceInfo->DeviceStats.BytesRead += dataTransferLength; + + } else { + + deviceInfo->DeviceStats.BytesRead = MAXULONGLONG; + } + + } else if (DsmIsWriteRequest(opCode)) { + + if (deviceInfo->DeviceStats.NumberWrites <= MAXULONG) { + + InterlockedIncrement((LONG volatile*)&deviceInfo->DeviceStats.NumberWrites); + } + + if ((MAXULONGLONG - dataTransferLength) > deviceInfo->DeviceStats.BytesWritten) { + + deviceInfo->DeviceStats.BytesWritten += dataTransferLength; + + } else { + + deviceInfo->DeviceStats.BytesWritten = MAXULONGLONG; + } + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpRequestComplete (DevInfo %p): Exiting function.\n", + DsmId)); + + return; +} + + +NTSTATUS +DsmpRegisterPersistentReservationKeys( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN BOOLEAN Register + ) +/*++ + +Routine Description: + + This routine is used to build and send down the request to register + or unregister the persistent reservation keys to the device down + the path given by DeviceInfo. + +Arguments: + + DeviceInfo - Device-path pair to use for sending down the request + Register - Flag to indicate whether to register or unregister the keys. + +Return Value: + + STATUS_SUCCESS on success, else appropriate failure code. + +--*/ +{ + PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; + PCDB cdb; + PPRO_PARAMETER_LIST parameters; + IO_STATUS_BLOCK ioStatus; + NTSTATUS status = STATUS_SUCCESS; + ULONG length; + PDSM_DEVICE_INFO deviceInfo = DeviceInfo; + PDSM_GROUP_ENTRY group; + ULONGLONG saKey; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Entering function - Register = %x.\n", + deviceInfo, + Register)); + + group = DeviceInfo->Group; + + NT_ASSERT(group && group->PRKeyValid); + + if (DeviceInfo->State >= DSM_DEV_FAILED) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Unusable - state %d.\n", + deviceInfo, + deviceInfo->State)); + + status = STATUS_UNSUCCESSFUL; + goto __Exit_DsmpRegisterPersistentReservationKeys; + } + + // + // Build a pass through command to process Persistent Reserve Out + // for registering the device. + // + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + passThrough = DsmpAllocatePool(NonPagedPoolNx, + length, + DSM_TAG_PASS_THRU); + if (!passThrough) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Failed to allocate memory for persistent reserve.\n", + deviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegisterPersistentReservationKeys; + } + + REVERSE_BYTES_QUAD(&saKey, &group->PersistentReservationRegisteredKey); + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Attempting PR-Out SA %u, Type %u, Scope %u, PR-Key %I64x.\n", + deviceInfo, + group->PRServiceAction, + group->PRType, + group->PRScope, + saKey)); + +__RetryRequest: + + // + // Build the cdb to reserve the device (Logical Unit). The type of reservation + // scope and service action is whatever cluster service provided at the time of + // sending down registration to this device before this particular path was available. + // + cdb = (PCDB) passThrough->ScsiPassThrough.Cdb; + cdb->PERSISTENT_RESERVE_OUT.OperationCode = SCSIOP_PERSISTENT_RESERVE_OUT; + cdb->PERSISTENT_RESERVE_OUT.ServiceAction = group->PRServiceAction; + cdb->PERSISTENT_RESERVE_OUT.Scope = group->PRScope; + cdb->PERSISTENT_RESERVE_OUT.Type = group->PRType; + cdb->PERSISTENT_RESERVE_OUT.ParameterListLength[1] = sizeof(PRO_PARAMETER_LIST); + + passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); + passThrough->ScsiPassThrough.CdbLength = 10; + passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; + passThrough->ScsiPassThrough.DataIn = 0; + passThrough->ScsiPassThrough.DataTransferLength = sizeof(PRO_PARAMETER_LIST); + passThrough->ScsiPassThrough.TimeOutValue = 20; + passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); + passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); + + parameters = (PPRO_PARAMETER_LIST)(passThrough->DataBuffer); + + // + // Copy the persistent reservation key given by cluster service to + // Service Action Reservation Key. This key will be registered + // with the device. + // + // Set ServiceActionReservationKey to the well-known key if we are registering. + // Note that to unregister ServiceActionReservationKey needs to be set to 0. + // + if (Register) { + + RtlCopyMemory(parameters->ServiceActionReservationKey, group->PersistentReservationRegisteredKey, 8); + + } else { + + RtlCopyMemory(parameters->ReservationKey, group->PersistentReservationRegisteredKey, 8); + RtlZeroMemory(parameters->ServiceActionReservationKey, 8); + } + + DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, + DeviceInfo->TargetObject, + passThrough, + passThrough, + length, + length, + FALSE, + &ioStatus); + + status = ioStatus.Status; + + if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(ioStatus.Status))) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Persistent Reserve (Register Key) succeeded using %p.\n", + deviceInfo, + DeviceInfo)); + + } else { + + PUCHAR senseData; + UCHAR senseInfoLength; + + senseData = (PUCHAR)(passThrough->SenseInfoBuffer); + senseInfoLength = passThrough->ScsiPassThrough.SenseInfoLength; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): DevInfo %p, Register keys (%d): NTStatus %x, ScsiStatus %x.\n", + deviceInfo, + DeviceInfo, + Register, + ioStatus.Status, + passThrough->ScsiPassThrough.ScsiStatus)); + + if (DsmpShouldRetryPassThroughRequest((PVOID)senseData, senseInfoLength)) { + + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + RtlZeroMemory(passThrough, length); + + goto __RetryRequest; + + } else if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Will change success to error status for register\n", + deviceInfo)); + + status = STATUS_INVALID_DEVICE_REQUEST; + } + } + + // + // Free the passthrough + data buffer. + // + DsmpFreePool(passThrough); + +__Exit_DsmpRegisterPersistentReservationKeys: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpRegisterPersistentReservationKeys (DevInfo %p): Exiting function with status %x.\n", + DeviceInfo, + status)); + + return status; +} + + + +BOOLEAN +DsmpShouldRetryPassThroughRequest( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ) +/*++ + +Routine Description: + + This routine determines if a passthrough request needs to be retried based on the + information in the passed in sense data. + +Arguments: + + SenseData - Pointer to Sense Data information buffer. + SenseDataSize - Size of the passed in sense data buffer. + +Return Value: + + TRUE if sense information indicates a retry-able error, else FALSE. + +--*/ +{ + BOOLEAN validSense = FALSE; + UCHAR senseKey = 0; + UCHAR addSenseCode = 0; + BOOLEAN retry = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPassThroughRequest (SenseData %p): Entering function.\n", + SenseData)); + +#if DBG + if (SenseDataSize > 0) { + + ULONG inx; + PUCHAR senseInfo; + + + senseInfo = (PUCHAR) SenseData; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPassThroughRequest (SenseData %p): Sense info length %d. Sense Info : ", + SenseData, + SenseDataSize)); + + for (inx = 0; inx < SenseDataSize; inx++) { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "%x ", + senseInfo[inx])); + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "\n")); + } +#endif + + validSense = ScsiGetSenseKeyAndCodes(SenseData, + SenseDataSize, + SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, + &senseKey, + &addSenseCode, + NULL); + if (validSense) { + if (senseKey == SCSI_SENSE_UNIT_ATTENTION) { + + switch (addSenseCode) { + case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: + case SCSI_ADSENSE_BUS_RESET: + case SCSI_ADSENSE_PARAMETERS_CHANGED: { + retry = TRUE; + break; + } + + default: { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPassThroughRequest (SenseData %p): AddSenseCode %x. Not retrying.\n", + SenseData, + addSenseCode)); + + retry = FALSE; + break; + } + } + } + } else { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPassThroughRequest (SenseData %p): Sense data size %d not big enough.\n", + SenseData, + SenseDataSize)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPassThroughRequest (SenseData %p): Exiting function with retry %x.\n", + SenseData, + retry)); + + return retry; +} + + +BOOLEAN +DsmpShouldRetryPersistentReserveCommand( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ) +/*++ + +Routine Description: + + This routine determines if a a PR request needs to be retried based on the + information in the passed in sense data. + +Arguments: + + SenseData - Pointer to Sense Data information buffer. + SenseDataSize - Size of the passed in sense data buffer. + +Return Value: + + TRUE if sense information indicates a retry-able error, else FALSE. + +--*/ +{ + BOOLEAN retry = FALSE; + BOOLEAN validSense = FALSE; + UCHAR senseKey = 0; + UCHAR addSenseCode = 0; + UCHAR addSenseCodeQualifier = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPersistentReserveCommand (SenseData %p): Entering function.\n", + SenseData)); + + retry = DsmpShouldRetryPassThroughRequest(SenseData, SenseDataSize); + + if (!retry) { + validSense = ScsiGetSenseKeyAndCodes(SenseData, + SenseDataSize, + SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, + &senseKey, + &addSenseCode, + &addSenseCodeQualifier); + if (validSense) { + + // + // If the TPG is in transitioning state, retry the request + // + if ((senseKey == SCSI_SENSE_UNIT_ATTENTION || senseKey == SCSI_SENSE_NOT_READY) && + (addSenseCode == SCSI_ADSENSE_LUN_NOT_READY && + addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION)) { + + retry = TRUE; + } + } else { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPersistentReserveCommand (SenseData %p): Sense data size %d not big enough.\n", + SenseData, + SenseDataSize)); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpShouldRetryPersistentReserveCommand (SenseData %p): Exiting function with retry %x.\n", + SenseData, + retry)); + + return retry; +} + + +VOID +DsmpAllowStandbyPathsToRest( + _In_ PDSM_GROUP_ENTRY Group + ) +/*++ + +Routine Description: + + This routine is called when a new path is available for a device + and has a desired state of ACTIVE_O. Since this will be an ACTIVE_O + path we see if there are any paths with a desired state of Standby + but that are currently active. These paths can be safely moved by + to standby. + + This routine assumes that the lock is held + +Arguements: + + Group is the multipath group + +Return Value: + + None +--*/ +{ + PDSM_DEVICE_INFO existingDeviceInfo; + ULONG inx; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpAllowStandbyPathsToRest (Group %p): Entering function.\n", + Group)); + + for (inx = 0; inx < Group->NumberDevices; inx++) { + + existingDeviceInfo = Group->DeviceList[inx]; + + if ((existingDeviceInfo->DesiredState == DSM_DEV_STANDBY) && + (existingDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED)) { + + existingDeviceInfo->State = DSM_DEV_STANDBY; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpAllowStandbyPathsToRest (Group %p): DevInfo %p changed to state %d at %d\n", + Group, + existingDeviceInfo, + existingDeviceInfo->State, + __LINE__)); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpAllowStandbyPathsToRest (Group %p): Exiting function.\n", + Group)); + return; +} + + +PDSM_DEVICE_INFO +DsmpGetAnyActivePath( + _In_ PDSM_GROUP_ENTRY Group, + _In_ BOOLEAN Exception, + _In_opt_ PDSM_DEVICE_INFO DeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine will return an active path from the list + + This routine assumes that the DSM lock is held + +Arguements: + + Group is the multipath group + Exception - if TRUE, indicates that the returned devInfo must not be the same + as the one passed in. + DeviceInfo - the must-not-match devInfo. Valid parameter only if Exception is + TRUE. + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + active path or NULL + +--*/ +{ + PDSM_DEVICE_INFO existingDeviceInfo; + PDSM_DEVICE_INFO candidateDevInfo = NULL; + ULONG inx; + + UNREFERENCED_PARAMETER(SpecialHandlingFlag); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetAnyActivePath (Group %p): Entering function.\n", + Group)); + + for (inx = 0; inx < DSM_MAX_PATHS; inx++) { + + existingDeviceInfo = Group->DeviceList[inx]; + + if (existingDeviceInfo && + existingDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED && + DsmpIsDeviceInitialized(existingDeviceInfo) && + DsmpIsDeviceUsable(existingDeviceInfo) && + DsmpIsDeviceUsablePR(existingDeviceInfo)) { + + + if (Exception && existingDeviceInfo == DeviceInfo) { + continue; + } + + candidateDevInfo = existingDeviceInfo; + break; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetAnyActivePath (Group %p): Exiting function with DevInfo %p\n", + Group, + candidateDevInfo)); + + return candidateDevInfo; +} + + +PDSM_DEVICE_INFO +DsmpGetActivePathToBeUsed( + _In_ PDSM_GROUP_ENTRY Group, + _In_ BOOLEAN Symmetric, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine will return an active path from the list that should + be the next one used by the DSM + + This routine assumes that the DSM lock is held + +Arguements: + + Group is the multipath group + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + active path or NULL + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetActivePathToBeUsed (Group %p): Entering function.\n", + Group)); + + deviceInfo = NULL; + + switch (Group->LoadBalanceType) { + + case DSM_LB_LEAST_BLOCKS: + case DSM_LB_DYN_LEAST_QUEUE_DEPTH: { + + // + // Since we choose the path with the smallest queue or cumulative size in + // DsmpGetPath, we just pick any path now + // + + // fall through + } + + case DSM_LB_ROUND_ROBIN_WITH_SUBSET: + case DSM_LB_ROUND_ROBIN: { + + // + // For RR and RRS we just pick any active path to start with + // and the DsmpGetPath will do the round robining + // + } + + case DSM_LB_FAILOVER: { + + deviceInfo = DsmpGetAnyActivePath(Group, FALSE, NULL, SpecialHandlingFlag); + + break; + } + + case DSM_LB_WEIGHTED_PATHS: { + + PDSM_DEVICE_INFO workDeviceInfo; + ULONG weight = (ULONG) -1; + ULONG inx; + + for (inx = 0; inx < Group->NumberDevices; inx++) { + + workDeviceInfo = Group->DeviceList[inx]; + + if ((workDeviceInfo) && + (DsmpIsDeviceInitialized(workDeviceInfo)) && + (DsmpIsDeviceUsable(workDeviceInfo)) && + (DsmpIsDeviceUsablePR(workDeviceInfo)) && + (workDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) && + (workDeviceInfo->PathWeight < weight)) { + + // + // We found a path that is active and is at + // the lowest weight. Remember it. + // + weight = workDeviceInfo->PathWeight; + + deviceInfo = workDeviceInfo; + } + } + + break; + } + + default: { + + break; + } + } + + if (!deviceInfo && !Symmetric) { + + // + // In the case of implicit transitions, it is possible that a TPG hasn't yet + // been made A/O. So instead of not setting any path, fall back to using some + // other path. IO sent down this path may fail, but will be retried in + // InterpretError(). Hopefully by then, at least one TPG will have transitioned + // to A/O state. + // + // The same argument holds true if the storage supports both implicit and + // explicit transitions, since it is possible that after we explicitly changed + // the TPG states, an implicit transition left us with no path in A/O state. + // + // In the case of explicit only transitions, we tried making at least one path + // as A/O and failed. This can happen, for example, when STPG fails because + // this initiator is not registered or does not hold exclusive reservation over + // the target. Instead of not using any path, we can consider a path in A/U state, + // A/U being just a functional path state. + // + BOOLEAN sendTPG = FALSE; + + deviceInfo = DsmpFindStandbyPathToActivateALUA(Group, &sendTPG, SpecialHandlingFlag); + + if ((deviceInfo != NULL) && + ((deviceInfo->ALUASupport != DSM_DEVINFO_ALUA_EXPLICIT) || + ((deviceInfo->ALUASupport == DSM_DEVINFO_ALUA_EXPLICIT) && + (deviceInfo->State <= DSM_DEV_ACTIVE_UNOPTIMIZED)))) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpGetActivePathToBeUsed (Group %p): Using best alternative candidate device %p\n", + Group, + deviceInfo)); + } else { + + deviceInfo = NULL; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpGetActivePathToBeUsed (Group %p): No active/alternative path available for group\n", + Group)); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetActivePathToBeUsed (Group %p): Exiting function with devInfo %p.\n", + Group, + deviceInfo)); + + return deviceInfo; +} + + +PDSM_DEVICE_INFO +DsmpFindStandbyPathToActivate( + _In_ PDSM_GROUP_ENTRY Group, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine will find another path in the group that is active + + This routine assumes that the DSM lock is held + + This is used by devices that support symmetric LUA. + +Arguements: + + Group is the multipath group + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Standby path or NULL if no standby path is available + +--*/ +{ + PDSM_DEVICE_INFO existingDeviceInfo; + ULONG inx; + PDSM_DEVICE_INFO candidateDevInfo = NULL; + + UNREFERENCED_PARAMETER(SpecialHandlingFlag); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindStandbyPathToActivate(Group %p): Entering function.\n", + Group)); + + for (inx = 0; inx < Group->NumberDevices; inx++) { + + existingDeviceInfo = Group->DeviceList[inx]; + + if (existingDeviceInfo && + existingDeviceInfo->State == DSM_DEV_STANDBY && + DsmpIsDeviceInitialized(existingDeviceInfo) && + DsmpIsDeviceUsable(existingDeviceInfo) && + DsmpIsDeviceUsablePR(existingDeviceInfo)) { + + // + // If we don't as yet have a candidate, pick the first available one. + // However, our preference is one that is through the preferred TPG. + // + if (!candidateDevInfo || + existingDeviceInfo->TargetPortGroup && existingDeviceInfo->TargetPortGroup->Preferred) { + + candidateDevInfo = existingDeviceInfo; + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindStandbyPathToActivate (Group %p): Exiting function with devInfo %p.\n", + Group, + candidateDevInfo)); + + return candidateDevInfo; +} + + +PDSM_DEVICE_INFO +DsmpFindStandbyPathToActivateALUA( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PBOOLEAN SendTPG, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine will find another path in the group that is active + + This is used by devices that don't support symmetric LUA. + + N.B: This routine MUST be called with DsmContextLock held in either Shared or + Exclusive mode. + +Arguements: + + Group is the multipath group + SendTPG - output parameter that indicates if TPG command need to be sent down. + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Standby path or NULL if no standby path is available + +--*/ +{ + PDSM_DEVICE_INFO existingDeviceInfo; + ULONG inx; + PDSM_DEVICE_INFO candidateDevInfo = NULL; + + UNREFERENCED_PARAMETER(SpecialHandlingFlag); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindStandbyPathToActivateALUA (Group %p): Entering function.\n", + Group)); + + for (inx = 0; inx < Group->NumberDevices; inx++) { + + existingDeviceInfo = Group->DeviceList[inx]; + + // + // The candidate for making A/O obviously mustn't be in a failed state + // and should have a path assigned. + // + if (existingDeviceInfo && + !DsmpIsDeviceFailedState(existingDeviceInfo->State) && + DsmpIsDeviceInitialized(existingDeviceInfo) && + DsmpIsDeviceUsable(existingDeviceInfo) && + DsmpIsDeviceUsablePR(existingDeviceInfo)) { + + // + // If we don't have any candidate currently, choose the very first + // one that is in a non-failure state, regardless of what state it + // may be in. + // + if (!candidateDevInfo) { + + candidateDevInfo = existingDeviceInfo; + *SendTPG = TRUE; + } + + // + // Might as well use one that the Admin desires for to be in A/O + // + if (existingDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) { + + // + // However, such a devInfo is not a better candidate if our candidate + // devInfo is also one that the Admin desires be in A/O, and it is + // through a preferred TPG. + // + if (!(existingDeviceInfo->DesiredState == candidateDevInfo->DesiredState && + candidateDevInfo->TargetPortGroup->Preferred)) { + + candidateDevInfo = existingDeviceInfo; + *SendTPG = TRUE; + } + } + + // + // Check if the current one is at least better than the candidate. + // + if (DsmpIsBetterDeviceState(candidateDevInfo->State, existingDeviceInfo->State)) { + + candidateDevInfo = existingDeviceInfo; + *SendTPG = TRUE; + } + + // + // We found one that we may have just masked as non-A/O. This is the + // best option as we don't have to send down an STPG. + // + if (existingDeviceInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { + + candidateDevInfo = existingDeviceInfo; + *SendTPG = FALSE; + break; + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindStandbyPathToActivateALUA (Group %p): Exiting function with devInfo %p.\n", + Group, + candidateDevInfo)); + + return candidateDevInfo; +} + + +PDSM_DEVICE_INFO +DsmpFindStandbyPathInAlternateTpgALUA( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine will find another path in the group that is not in the same + TPG as the passed in DeviceInfo. + + This routine assumes that the DSM lock is held + + This is used by devices that support ALUA. + +Arguements: + + Group is the multipath group + DeviceInfo is the devInfo whose TPG must not be matched + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Standby path not in same TPG as passed in DeviceInfo + or NULL if no standby path is available + +--*/ +{ + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = DeviceInfo->TargetPortGroup; + PDSM_DEVICE_INFO existingDeviceInfo; + ULONG inx; + PDSM_DEVICE_INFO candidateDevInfo = NULL; + + UNREFERENCED_PARAMETER(SpecialHandlingFlag); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindStandbyPathInAlternateTpgALUA (DevInfo %p): Entering function.\n", + DeviceInfo)); + + for (inx = 0; inx < Group->NumberDevices; inx++) { + + existingDeviceInfo = Group->DeviceList[inx]; + + // + // We only care about deviceInfo if TPG is different + // + if (existingDeviceInfo && existingDeviceInfo->TargetPortGroup != targetPortGroup) { + + // + // The candidate for making A/O obviously mustn't be in a failed state + // and must be initialized + // + if (!DsmpIsDeviceFailedState(existingDeviceInfo->State) && + DsmpIsDeviceInitialized(existingDeviceInfo) && + DsmpIsDeviceUsable(existingDeviceInfo) && + DsmpIsDeviceUsablePR(existingDeviceInfo)) { + + // + // If we don't have any candidate currently, choose the very first + // one that is in a non-failure state, regardless of what state it + // may be in. + // + if (!candidateDevInfo) { + + candidateDevInfo = existingDeviceInfo; + continue; + } + + // + // Check if the current one is at least better than the candidate. + // + if (DsmpIsBetterDeviceState(candidateDevInfo->State, existingDeviceInfo->State)) { + + candidateDevInfo = existingDeviceInfo; + } + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFindStandbyPathInAlternateTpgALUA (DevInfo %p): Exiting function with devInfo %p.\n", + DeviceInfo, + candidateDevInfo)); + + return candidateDevInfo; +} + + +NTSTATUS +DsmpSetLBForDsmPolicyAdjustment( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ) + +/*++ + +Routine Description: + + This routine is called when a change is made to the DSM-wide default + load balance policy. It goes through each LUN representation (ie. Group + entry) and updates the appropriate ones (ie. ones for which the policy + was not chosen based on VID/PID or because of an explicit settings on + the LUN). It also then updates the path states in accordance with the + new LB policy. + +Arguements: + + DsmContext is the DSM context + LoadBalanceType is the new load balance policy to be applied + PreferredPath is the preferred failback path to be used (applicable only + if LB policy is Failover) + +Return Value: + + Success + +--*/ + +{ + NTSTATUS status = STATUS_SUCCESS; + KIRQL oldIrql; + PLIST_ENTRY entry; + ULONG groupIndex = 0; + ULONG devInfoIndex; + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO devInfo; + DSM_LOAD_BALANCE_TYPE newLoadBalancePolicy; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetLBForDsmPolicyAdjustment (DsmContext %p): Entering function.\n", + DsmContext)); + + oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + for (entry = DsmContext->GroupList.Flink; entry != &(DsmContext->GroupList); entry = entry->Flink, groupIndex++) { + + group = CONTAINING_RECORD(entry, DSM_GROUP_ENTRY, ListEntry); + + newLoadBalancePolicy = LoadBalanceType; + + // + // Only LUNs that don't have their policy explicitly set + // and ones that don't have it set based on VID/PID are + // of interest to us here. + // + if (group->LBPolicySelection == DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY || + group->LBPolicySelection == DSM_DEFAULT_LB_POLICY_DSM_WIDE) { + + // + // Also, if the caller is trying to clear the DSM-wide + // default policy, then we don't even care about those + // LUNs whose policies were not set using this value. + // + if (newLoadBalancePolicy < DSM_LB_FAILOVER && + group->LBPolicySelection != DSM_DEFAULT_LB_POLICY_DSM_WIDE) { + + continue; + } + + // + // If the DSM-wide setting is being cleared, we need to fall back + // to using the default based on the array's ALUA capabilities. + // + if (newLoadBalancePolicy < DSM_LB_FAILOVER) { + + newLoadBalancePolicy = DSM_LB_ROUND_ROBIN; + group->PreferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; + + + } else { + + // + // Since a new policy has been selected for the DSM-wide + // one, it needs to be applied to this LUN. + // + group->PreferredPath = (ULONGLONG)((ULONG_PTR)PreferredPath); + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; + } + + // + // If Round Robin is set and ALUA is enabled, we need to change the + // policy to Round Robin with Subset. + // + if (!DsmpIsSymmetricAccess(group->DeviceList[0]) && newLoadBalancePolicy == DSM_LB_ROUND_ROBIN) { + + newLoadBalancePolicy = DSM_LB_ROUND_ROBIN_WITH_SUBSET; + } + + // + // Finally set the new load balance policy. + // + group->LoadBalanceType = newLoadBalancePolicy; + + // + // Path states need to be updated in accordance with the new policy. + // + for (devInfoIndex = 0; devInfoIndex < DSM_MAX_PATHS; devInfoIndex++) { + + devInfo = group->DeviceList[devInfoIndex]; + DsmpSetNewDefaultLBPolicy(DsmContext, devInfo, group->LoadBalanceType, SpecialHandlingFlag); + } + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetLBForDsmPolicyAdjustment (DsmContext %p): Exiting function with status %x\n", + DsmContext, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForVidPidPolicyAdjustment( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PWSTR TargetHardwareId, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ) + +/*++ + +Routine Description: + + This routine is called when a change is made to the default load balance + policy for a VID/PID. It goes through each LUN representation (ie. Group + entry) and updates the appropriate ones (ie. ones for which the policy + was not because of an explicit settings on the LUN). It also then updates + the path states in accordance with the new LB policy. + +Arguements: + + DsmContext is the DSM context + TargetHardwareId is the VID/PID whose matching LUNs policy need to be updated + LoadBalanceType is the new load balance policy to be applied + PreferredPath is the preferred failback path to be used (applicable only + if LB policy is Failover) + +Return Value: + + Success + +--*/ + +{ + NTSTATUS status = STATUS_SUCCESS; + KIRQL oldIrql; + PLIST_ENTRY entry; + ULONG groupIndex = 0; + ULONG devInfoIndex; + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO devInfo; + DSM_LOAD_BALANCE_TYPE dsmLoadBalanceType; + ULONGLONG dsmPreferredPath; + BOOLEAN useDsmLBSettings = FALSE; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetLBForVidPidPolicyAdjustment (%ws): Entering function.\n", + TargetHardwareId)); + + status = DsmpQueryDsmLBPolicyFromRegistry(&dsmLoadBalanceType, &dsmPreferredPath); + + if (NT_SUCCESS(status)) { + + useDsmLBSettings = TRUE; + + } else { + + if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + status = STATUS_SUCCESS; + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_WMI, + "DsmpSetLBForVidPidPolicyAdjustment (%ws): MSDSM-wide default LB policy not set.\n", + TargetHardwareId)); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLBForVidPidPolicyAdjustment (%ws): Failed to query MSDMS-wide default LB setting. Status %x.\n", + TargetHardwareId, + status)); + } + } + + oldIrql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + for (entry = DsmContext->GroupList.Flink; entry != &(DsmContext->GroupList); entry = entry->Flink, groupIndex++) { + + group = CONTAINING_RECORD(entry, DSM_GROUP_ENTRY, ListEntry); + + // + // Only LUNs that don't have their policy explicitly set + // are of interest to us here. + // + if (group->LBPolicySelection < DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT) { + + // + // Figure out if this LUN matches the VID/PID of interest + // Device not of interest if it doesn't match the passed in target ID + // + if (wcscmp(group->HardwareId, TargetHardwareId) != 0) { + + continue; + } + + // + // Also, if the caller is trying to clear the VID/PID + // default policy, then we don't even care about those + // LUNs whose policies were not set using this value. + // + if (LoadBalanceType < DSM_LB_FAILOVER && + group->LBPolicySelection != DSM_DEFAULT_LB_POLICY_VID_PID) { + + continue; + } + + // + // If the VID/PID setting is being cleared, we need to fall back + // to using the DSM-wide default policy if it has been set, else + // we need to use the default based on the array's ALUA capabilities. + // + if (LoadBalanceType < DSM_LB_FAILOVER) { + + if (useDsmLBSettings) { + + // + // Even if the MSDSM-wide policy is specified as RR, if the storage + // is ALUA, we can't have the policy as RR, so we'll change it to + // RRWS instead. + // + if (!DsmpIsSymmetricAccess(group->DeviceList[0]) && dsmLoadBalanceType == DSM_LB_ROUND_ROBIN) { + + group->LoadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; + + } else { + + group->LoadBalanceType = dsmLoadBalanceType; + } + + group->PreferredPath = (ULONGLONG)((ULONG_PTR)dsmPreferredPath); + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; + + } else { + + // + // Default LB type: + // is Round Robin if ALUA is not supported, or if ALUA support is implicit but access is symmetric, + // else Round Robin With Subset (since in ALUA, all paths aren't in A/O). + // + if (DsmpIsSymmetricAccess(group->DeviceList[0])) { + + group->LoadBalanceType = DSM_LB_ROUND_ROBIN; + + } else { + + group->LoadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; + } + + + group->PreferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; + } + + } else { + + // + // Since a new policy has been selected for the DSM-wide + // one, it needs to be applied to this LUN. + // + // However, if the VID/PID policy is specified as RR but the storage + // is ALUA, we can't have the policy as RR, so we'll change it to + // RRWS instead. + // + if (!DsmpIsSymmetricAccess(group->DeviceList[0]) && LoadBalanceType == DSM_LB_ROUND_ROBIN) { + + group->LoadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; + + } else { + + group->LoadBalanceType = LoadBalanceType; + } + + group->PreferredPath = (ULONGLONG)((ULONG_PTR)PreferredPath); + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_VID_PID; + } + + // + // Path states need to be updated in accordance with the new policy. + // + for (devInfoIndex = 0; devInfoIndex < DSM_MAX_PATHS; devInfoIndex++) { + + devInfo = group->DeviceList[devInfoIndex]; + DsmpSetNewDefaultLBPolicy(DsmContext, devInfo, group->LoadBalanceType, SpecialHandlingFlag); + } + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), oldIrql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetLBForVidPidPolicyAdjustment (%ws): Exiting function with status %x\n", + TargetHardwareId, + status)); + + return status; +} + + +NTSTATUS +DsmpSetNewDefaultLBPolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_opt_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called to adjust the path state of an instance of a + LUN for which a new default load balance policy was applied + following an admin request for such a change. + + This routine must be called with spinlock held. + +Arguements: + + DsmContext is the DSM context + DeviceInfo is the device info on which the new path state needs to be set + LoadBalanceType is the load balance policy in accordance with which the path state needs to be adjusted + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + NTSTATUS status = STATUS_SUCCESS; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetNewDefaultLBPolicy (DevInfo %p): Entering function\n", + DeviceInfo)); + + if (!DeviceInfo) { + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpSetNewDefaultLBPolicy; + } + + if (!(DsmpIsDeviceInitialized(DeviceInfo) && DsmpIsDeviceUsable(DeviceInfo) && DsmpIsDeviceUsablePR(DeviceInfo)) || + DsmpIsDeviceFailedState(DeviceInfo->State)) { + + status = STATUS_UNSUCCESSFUL; + goto __Exit_DsmpSetNewDefaultLBPolicy; + } + + + group = DeviceInfo->Group; + + if (!DsmpIsSymmetricAccess(DeviceInfo)) { + + DsmpAdjustDeviceStatesALUA(group, NULL, SpecialHandlingFlag); + + } else { + + switch (LoadBalanceType) { + + // + // For failover, it is important the right path is + // chosen, ie. preferred path needs to be taken into + // consideration. + // + case DSM_LB_FAILOVER: { + + DsmpSetLBForPathArrival(DsmContext, DeviceInfo, SpecialHandlingFlag); + + break; + } + + // + // For all other policies, the state must be A/O. + // + default: { + + DeviceInfo->PreviousState = DeviceInfo->State; + DeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + break; + } + } + } + +__Exit_DsmpSetNewDefaultLBPolicy: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetNewDefaultLBPolicy (DevInfo %p): Exiting function with status %x\n", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForPathArrival( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called when a new path arrives for a multipath + group that doesn't support ALUA. The routine will set the path + to the appropriate state and fix up the other paths state if + they need to change. + + This is used by devices NOT supporting ALUA. + + This routine must be called with spinlock held. + +Arguements: + + DsmContext is the DSM context + NewDeviceInfo is the device info for the newly arrived path + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO deviceInfo; + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): Entering function.\n", + NewDeviceInfo)); + + group = NewDeviceInfo->Group; + + if (!(DsmpIsDeviceInitialized(NewDeviceInfo) && DsmpIsDeviceUsable(NewDeviceInfo) && DsmpIsDeviceUsablePR(NewDeviceInfo))) { + + // + // Bad device instance. Nothing can be done about it. + // + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_UNDETERMINED; + + NT_ASSERT(NewDeviceInfo->FailGroup == NULL); + + goto __Exit_DsmpSetLBForPathArrival; + } + + + if (group->NumberDevices == 1) { + + // + // if this is the only device for the group then we will always + // be active as every group must have at least one active path + // + if (NewDeviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { + + // + // All's good + // + goto __Exit_DsmpSetLBForPathArrival; + + } else { + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): State changed to %d at %d\n", + NewDeviceInfo, + NewDeviceInfo->State, + __LINE__)); + + goto __Exit_DsmpSetLBForPathArrival; + } + + switch(group->LoadBalanceType) { + case DSM_LB_FAILOVER: { + + // + // Get the current active path. + // + deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); + + // + // If the newly arriving path is the preferred path, this now should + // become our active path. + // + if (group->PreferredPath == ((ULONGLONG)((ULONG_PTR)(NewDeviceInfo->FailGroup->PathId)))) { + + // + // If current active path is not the preferred path, change its + // path state to standby. + // + if (deviceInfo && deviceInfo != NewDeviceInfo) { + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_STANDBY; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (Group %p): Preferred path back online. DevInfo %p changed to state %d\n", + group, + deviceInfo, + deviceInfo->State)); + } + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + } else { + + // + // In the case of failover, we must have only a single + // active path. If this newly added path is configured as + // the one that is desired to be active then we make this + // active and set the standby path that was active back to + // standby unless the preferred path is the currently active + // path. If the newly added path is supposed to be + // standby then we leave it as standby. + // + if (NewDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) { + + if (deviceInfo) { + + // + // If the preferred path is currently active, don't change + // it regardless of this path wanting to be in active state. + // + if (group->PreferredPath == ((ULONGLONG)((ULONG_PTR)(deviceInfo->FailGroup->PathId)))) { + + if (NewDeviceInfo != deviceInfo) { + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_STANDBY; + } + + } else { + + // + // Since the preferred path is not active, make this + // path active since it wants to be so. This means + // changing the current active path to standby. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_STANDBY; + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + } + } else { + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + } + + } else { + + if (deviceInfo) { + + if (deviceInfo != NewDeviceInfo) { + + // + // This newly arrived device doesn't want to be in + // A/O, and we already have an active path, so make + // it standby. + // + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_STANDBY; + } + } else { + + // + // Since we currently don't have an active path, this one + // needs to be made active, regardless of its path it wishes + // to be in. + // + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + } + } + } + + break; + } + + case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { + + // + // In RRWS, a set of paths can be active and another set of + // paths can be standby. We set the new path to the desired + // state unless the desired state is standby, but there are + // no active paths. Also if the desired state is Active we + // need to check if there are any existing paths that are + // also active but have a desired state of standby. For + // those we can move them back to standby. + // + if (NewDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) { + + // + // We are the active path coming back. Find out who has + // been the active one and place him back to standby + // + DsmpAllowStandbyPathsToRest(group); + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): Changed to state %d at %d\n", + NewDeviceInfo, + NewDeviceInfo->State, + __LINE__)); + + } else { + + // + // if there are no paths already active then we've got + // to make this one AO, otherwise we can be non-AO + // + deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); + + if (!deviceInfo || deviceInfo == NewDeviceInfo) { + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + } else { + + NewDeviceInfo->State = DSM_DEV_STANDBY; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (%p): Changed to state %d at %d. Status %x\n", + NewDeviceInfo, + NewDeviceInfo->State, + __LINE__, + status)); + } + + status = STATUS_SUCCESS; + + break; + } + + case DSM_LB_LEAST_BLOCKS: + case DSM_LB_ROUND_ROBIN: + case DSM_LB_DYN_LEAST_QUEUE_DEPTH: + case DSM_LB_WEIGHTED_PATHS: { + + // + // In RR, LWP, LB and LQD all paths are active so the new device + // becomes AO or AU. + // + if (NewDeviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED) { + + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): Changed to state %d at %d. Status %x\n", + NewDeviceInfo, + NewDeviceInfo->State, + __LINE__, + status)); + + status = STATUS_SUCCESS; + + break; + } + + default: { + status = STATUS_INVALID_PARAMETER; + break; + } + } + +__Exit_DsmpSetLBForPathArrival: + + // + // Update the next path to be used for the group + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess(NewDeviceInfo), + SpecialHandlingFlag); + if (deviceInfo != NULL) { + + InterlockedExchangePointer(&(group->PathToBeUsed), (PVOID)deviceInfo->FailGroup); + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): Updating PathToBeUsed in %p to %p\n", + NewDeviceInfo, + group, + group->PathToBeUsed)); + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): No FOG available for group %p\n", + NewDeviceInfo, + group)); + + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrival (DevInfo %p): Exiting function with status %x\n", + NewDeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForPathArrivalALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called when a new path arrives for a multipath + group. The routine will set the path to the appropriate state and + fix up the other paths state if they need to change. + + Spin lock must NOT be held by caller + +Arguements: + + DsmContext is the DSM context + NewDeviceInfo is the device info for the newly arrived path + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO deviceInfo = NULL; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 warnings; + BOOLEAN lockHeld = FALSE; + PDSM_DEVICE_INFO preferredActiveDeviceInfo = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): Entering function.\n", + NewDeviceInfo)); + + group = NewDeviceInfo->Group; + + if (!(DsmpIsDeviceInitialized(NewDeviceInfo) && DsmpIsDeviceUsable(NewDeviceInfo) && DsmpIsDeviceUsablePR(NewDeviceInfo))) { + + // + // Bad device instance. Nothing can be done about it. + // + NewDeviceInfo->PreviousState = NewDeviceInfo->State; + NewDeviceInfo->State = DSM_DEV_UNDETERMINED; + + NT_ASSERT(NewDeviceInfo->FailGroup == NULL); + + goto __Exit_DsmpSetLBForPathArrivalALUA; + } + + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + lockHeld = TRUE; + + if (group->NumberDevices == 1) { + + // + // If this is the only device for the group then it should be the + // active instance as every group must have at least one active path. + // + if (NewDeviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED) { + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + lockHeld = FALSE; + + if (NewDeviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { + + // + // If the device supports explicit transitions, set its state to A/O + // + status = DsmpSetDeviceALUAState(DsmContext, NewDeviceInfo, DSM_DEV_ACTIVE_OPTIMIZED); + + } else { + + // + // Since the device supports only implicit transitions, send down + // RTPG and hope that the controller has made this one the A/O path. + // + status = DsmpGetDeviceALUAState(DsmContext, NewDeviceInfo, NULL); + + if (NT_SUCCESS(status)) { + + // + // Remember that at this point it is possible that this path + // is still non-A/O. We'll need to handle this in DsmGetPath + // as a special case where we don't find an A/O path but the + // storage supports implicit-only transitions. At that time, + // we mustn't blindly return a NULL path back. + // + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): RTPG returned state = %x, ALUA state = %x.\n", + NewDeviceInfo, + NewDeviceInfo->State, + NewDeviceInfo->ALUAState)); + } + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): State changed to %d at %d\n", + NewDeviceInfo, + NewDeviceInfo->State, + __LINE__)); + + } else { + + deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); + + // + // Irrespecitve of the policy, we must have at least one A/O path. + // + // For RRWS and FOO, this path is of interest if it is desired to be in A/O. + // + // Also, for failover-only, this new path is of interest if it is + // the preferred path. + // + // This path is also of interest if it is not A/O and desired state has not + // explicitly been set to non-A/O and it has been exposed through the + // preferred TPG. + // + if ((!deviceInfo) || + ((NewDeviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) && + (group->LoadBalanceType == DSM_LB_FAILOVER || + group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET)) || + (group->PreferredPath == (ULONGLONG)((ULONG_PTR)(NewDeviceInfo->FailGroup->PathId)) && + group->LoadBalanceType == DSM_LB_FAILOVER) || + (NewDeviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED && + NewDeviceInfo->DesiredState == DSM_DEV_UNDETERMINED && + NewDeviceInfo->TargetPortGroup->Preferred)) { + + // + // Since this path is supposed to be active, we make it + // active and then allow any paths that are supposed to + // be standby go back to being standby + // + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + lockHeld = FALSE; + + // + // If explicit ALUA is supported, we need to send down STPG to make the change. + // + if (NewDeviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { + + status = DsmpSetDeviceALUAState(DsmContext, NewDeviceInfo, DSM_DEV_ACTIVE_OPTIMIZED); + + } else { + + // + // If implicit ALUA, the controller may have made some + // changes to the TPG states. We just need to query it. + // We'll try and honor the Admin's request but can't + // guarantee it. + // + status = DsmpGetDeviceALUAState(DsmContext, NewDeviceInfo, NULL); + } + + // + // We prefer this newly arrived devInfo to be A/O + // + preferredActiveDeviceInfo = NewDeviceInfo; + } + } + + if (!lockHeld) { + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + lockHeld = TRUE; + } + + if (NT_SUCCESS(status)) { + + DsmpAdjustDeviceStatesALUA(group, preferredActiveDeviceInfo, SpecialHandlingFlag); + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): Trying to query ALUA state failed with %x\n", + NewDeviceInfo, + status)); + } + + status = STATUS_SUCCESS; + +__Exit_DsmpSetLBForPathArrivalALUA: + + // + // Update the next path to be used for the group + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess(NewDeviceInfo), + SpecialHandlingFlag); + if (deviceInfo != NULL) { + + InterlockedExchangePointer(&(group->PathToBeUsed), (PVOID)deviceInfo->FailGroup); + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): Updating PathToBeUsed in %p to %p\n", + NewDeviceInfo, + group, + group->PathToBeUsed)); + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): No active/alternative path available for group %p\n", + NewDeviceInfo, + group)); + + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + } + + if (lockHeld) { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathArrivalALUA (DevInfo %p): Exiting function with status %x\n", + NewDeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForPathRemoval( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, + _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called when a path is removed from a multipath + group. The routine will set the path to the appropriate state and + fix up the other paths state if they need to change. + + Note: This is used by devices NOT supporting ALUA. + +Arguements: + + DsmContext is the DSM context + + RemovedDeviceInfo is the device info for failing/going-away path + + Group is an optional group override. That is, if Group is not NULL, this + function will run the load balance policy on the given Group and not + the Group from the RemovedDeviceInfo. This should only be used when + it's impossible to get a pointer to the RemovedDeviceInfo. + + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO deviceInfo; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p, Group %p): Entering function.\n", + RemovedDeviceInfo, + Group)); + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + if (Group == NULL) { + + if (!(DsmpIsDeviceFailedState(RemovedDeviceInfo->State))) { + + RemovedDeviceInfo->LastKnownGoodState = RemovedDeviceInfo->State; + } + + RemovedDeviceInfo->PreviousState = RemovedDeviceInfo->State; + RemovedDeviceInfo->State = DSM_DEV_FAILED; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): changed to state %d at %d\n", + RemovedDeviceInfo, + RemovedDeviceInfo->State, + __LINE__)); + + group = RemovedDeviceInfo->Group; + + } else { + // + // The caller has chosen to override the RemovedDeviceInfo->Group. + // + group = Group; + } + + switch(group->LoadBalanceType) { + case DSM_LB_FAILOVER: + case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { + + // + // In the case of failover, we must have only a single + // active path. If the removed path was the active path we + // need to find another path to become active + // + // In RRWS, a set of paths can be active and another set of + // paths can be standby. If the removed path is an active + // path then we need to make sure there is another active + // path. If there is already another active path then there + // is nothing to do. If not then a path needs to be made + // active. + // + if (!DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag)) { + + deviceInfo = DsmpFindStandbyPathToActivate(group, SpecialHandlingFlag); + if (deviceInfo) { + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): DevInfo %p changed to state %d at %d\n", + RemovedDeviceInfo, + deviceInfo, + deviceInfo->State, + __LINE__)); + } + } else { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): LB Policy FO/RRWS and other paths active, no path made active at %d\n", + RemovedDeviceInfo, + __LINE__)); + } + + break; + } + + case DSM_LB_LEAST_BLOCKS: + case DSM_LB_ROUND_ROBIN: + case DSM_LB_WEIGHTED_PATHS: + case DSM_LB_DYN_LEAST_QUEUE_DEPTH: { + + // + // In RR, LQD, LB and LWP, all paths are active so we don't + // need to worry about activating a new path + // + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): LB Policy RR, LWP or LQD, no path made active at %d\n", + RemovedDeviceInfo, + __LINE__)); + break; + } + + default: { + status = STATUS_INVALID_PARAMETER; + break; + } + } + + // + // Update the next path to be used for the group + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess(RemovedDeviceInfo), + SpecialHandlingFlag); + if (deviceInfo != NULL) { + + InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): Removal: Updating PathToBeUsed in %p to %p\n", + RemovedDeviceInfo, + group, + group->PathToBeUsed)); + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): After remove No FOG available for group %p\n", + RemovedDeviceInfo, + group)); + + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemoval (DevInfo %p): Exiting function with status %x\n", + RemovedDeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForPathRemovalALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, + _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called when a path is removed from a multipath + group. The routine will set the path to the appropriate state and + fix up the other paths state if they need to change. + + Note: This should NOT be called with DsmContext Lock held + This is used for devices supporting ALUA. + +Arguements: + + DsmContext is the DSM context + + RemovedDeviceInfo is the device info for the failing/going-away path + + Group is an optional group override. That is, if Group is not NULL, this + function will run the load balance policy on the given Group and not + the Group from the RemovedDeviceInfo. This should only be used when + it's impossible to get a pointer to the RemovedDeviceInfo. + + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO deviceInfo = NULL; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + BOOLEAN lockHeld = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p, Group %p): Entering function.\n", + RemovedDeviceInfo, + Group)); + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + lockHeld = TRUE; + + if (Group == NULL) { + + if (!(DsmpIsDeviceFailedState(RemovedDeviceInfo->State))) { + + RemovedDeviceInfo->LastKnownGoodState = RemovedDeviceInfo->State; + } + + RemovedDeviceInfo->PreviousState = RemovedDeviceInfo->State; + RemovedDeviceInfo->State = DSM_DEV_FAILED; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): changed to state %d at %d\n", + RemovedDeviceInfo, + RemovedDeviceInfo->State, + __LINE__)); + + group = RemovedDeviceInfo->Group; + + } else { + // + // The caller has chosen to override the RemovedDeviceInfo->Group. + // + group = Group; + } + + if (group->LoadBalanceType < DSM_LB_FAILOVER || + group->LoadBalanceType > DSM_LB_LEAST_BLOCKS) { + + status = STATUS_INVALID_PARAMETER; + + } else { + + // + // In the case of failover, we must have only a single + // active path. If the removed path was the active path we + // need to find another path to become active + // + // In rest of policies, set of paths can be active and another set of + // paths can be standby. If the removed path is an active + // path then we need to make sure there is another active + // path. If there is already another active path then there + // is nothing to do. If not then a path needs to be made + // active. + // + if (!DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag)) { + + BOOLEAN sendTPG = TRUE; + + deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); + + if (deviceInfo) { + + if (sendTPG) { + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + lockHeld = FALSE; + + // + // If explicit transition supported, we need to send down STPG to make the change. + // + if (deviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { + + status = DsmpSetDeviceALUAState(DsmContext, deviceInfo, DSM_DEV_ACTIVE_OPTIMIZED); + + } else { + + // + // If implicit ALUA, the controller may have made necessary + // changes to the TPG states. We just need to query it. + // + status = DsmpGetDeviceALUAState(DsmContext, deviceInfo, NULL); + } + + if (!lockHeld) { + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + lockHeld = TRUE; + } + + if (NT_SUCCESS(status)) { + + DsmpAdjustDeviceStatesALUA(group, deviceInfo, SpecialHandlingFlag); + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): Trying to query for ALUA state failed with status %x\n", + RemovedDeviceInfo, + status)); + } + } else { + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + } + + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): Device %p changed to state %d at %d\n", + RemovedDeviceInfo, + deviceInfo, + deviceInfo->State, + __LINE__)); + } + } + } else { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): Other paths active, no path made active at %d\n", + RemovedDeviceInfo, + __LINE__)); + } + + status = STATUS_SUCCESS; + } + + // + // Update the next path to be used for the group + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess(RemovedDeviceInfo), + SpecialHandlingFlag); + if (deviceInfo != NULL) { + + InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): Removal: Updating PathToBeUsed in %p to %p\n", + RemovedDeviceInfo, + group, + group->PathToBeUsed)); + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): No active/alternative path available for group %p\n", + RemovedDeviceInfo, + group)); + + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + } + + if (lockHeld) { + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): Exiting function with status %x.\n", + RemovedDeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForPathFailing( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, + _In_ IN BOOLEAN MarkDevInfoFailed, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called when an IO that was sent using this path fails with + a fatal error. The routine will set the path to the appropriate state and + fix up the other paths state if they need to change. + + Note: This is used by devices NOT supporting ALUA. + +Arguements: + + DsmContext is the DSM context + + FailingDeviceInfo is the device info for the path on which IO failed + + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + NTSTATUS status; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailing (DevInfo %p): Entering function.\n", + FailingDeviceInfo)); + + // + // We need to do exactly what DsmpSetLBForPathRemoval() does, except + // that the devInfo may not really go away (may come back before a + // Pnp remove comes down for the real LUN) + // + if (MarkDevInfoFailed) { + status = DsmpSetLBForPathRemoval(DsmContext, FailingDeviceInfo, NULL, SpecialHandlingFlag); + } else { + status = DsmpSetLBForPathRemoval(DsmContext, FailingDeviceInfo, FailingDeviceInfo->Group, SpecialHandlingFlag); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailing (DevInfo %p): Exiting function with status %x\n", + FailingDeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLBForPathFailingALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, + _In_ IN BOOLEAN MarkDevInfoFailed, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + This routine is called when an IO that was sent using this path fails with + a fatal error. The routine will set the path to the appropriate state and + send down a Set Target Port Groups command asynchronously to fix up the + other paths state if they need to change (actual work done in the completion + routine). + + Note: This should NOT be called with DsmContext Lock held + This is used for devices supporting ALUA. + +Arguements: + + DsmContext is the DSM context + + FailingDeviceInfo is the device info for the failing/going-away path + + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; + PDSM_DEVICE_INFO deviceInfo = NULL; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength; + PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR tpgDescriptor = NULL; + PDSM_COMPLETION_CONTEXT completionContext = NULL; + PVOID senseInfo = NULL; + PSCSI_REQUEST_BLOCK srb = NULL; + PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Entering function.\n", + FailingDeviceInfo)); + + if (MarkDevInfoFailed) { + if (!(DsmpIsDeviceFailedState(FailingDeviceInfo->State))) { + + FailingDeviceInfo->LastKnownGoodState = FailingDeviceInfo->State; + } + + FailingDeviceInfo->PreviousState = FailingDeviceInfo->State; + FailingDeviceInfo->State = DSM_DEV_FAILED; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): changed to state %d at %d\n", + FailingDeviceInfo, + FailingDeviceInfo->State, + __LINE__)); + } + + group = FailingDeviceInfo->Group; + + if (group->LoadBalanceType < DSM_LB_FAILOVER || + group->LoadBalanceType > DSM_LB_LEAST_BLOCKS) { + + status = STATUS_INVALID_PARAMETER; + + } else { + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Check if there are any active paths that can be used. + // + deviceInfo = DsmpGetAnyActivePath(group, FALSE, NULL, SpecialHandlingFlag); + if (!deviceInfo) { + + // + // Check if an Set/Report TPG has already been sent for this failing devInfo + // + failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(DsmContext, group, FailingDeviceInfo); + + if (!failDevInfoListEntry) { + + BOOLEAN sendTPG = TRUE; + + deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); + + if (deviceInfo) { + + if (sendTPG) { + + tpgCompletionContext = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_TPG_COMPLETION_CONTEXT), + DSM_TAG_TPG_COMPLETION_CONTEXT); + + if (tpgCompletionContext) { + UCHAR senseInfoLength = SENSE_BUFFER_SIZE_EX; + + senseInfo = DsmpAllocatePool(NonPagedPoolNx, + senseInfoLength, + DSM_TAG_SCSI_SENSE_INFO); + + if (senseInfo) { + + srb = DsmpAllocatePool(NonPagedPoolNx, + sizeof(SCSI_REQUEST_BLOCK), + DSM_TAG_SCSI_REQUEST_BLOCK); + + if (srb) { + + srb->Length = SCSI_REQUEST_BLOCK_SIZE; + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); + if (completionContext) { + + // + // Update the target port group that needs to be made + // active/optimized. We will send down an STPG for + // storages that support both implicit and explicit. + // If the storage does NOT like our choice of A/O TPG, + // it will make an implicit transition. This is still + // a better option than solely relying on the storage's + // implicit transitions at this stage and ending up with + // no path in A/O state. + // + if (deviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { + + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); + + } else { + + // + // Find an active/optimized target port group that should + // have been set by the controller + // + // Take care of worst case scenario, which is: + // 1. 4-byte header (for allocation length) + // 2. 32 8-byte descriptors (for TPGs) + // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) + // + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + DSM_MAX_PATHS * sizeof(ULONG))); + } + + targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, + targetPortGroupsInfoLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo) { + + failDevInfoListEntry = DsmpBuildFailPathDevInfoEntry(DsmContext, + group, + FailingDeviceInfo, + deviceInfo); + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + if (failDevInfoListEntry) { + + tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)(targetPortGroupsInfo + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE); + tpgDescriptor->AsymmetricAccessState = DSM_DEV_ACTIVE_OPTIMIZED; + REVERSE_BYTES_SHORT(&tpgDescriptor->TPG_Identifier, &deviceInfo->TargetPortGroup->Identifier); + + // + // Prevent the device info from being removed when a TPG is in-flight. + // + InterlockedIncrement(&FailingDeviceInfo->BlockRemove); + + completionContext->DeviceInfo = FailingDeviceInfo; + completionContext->DsmContext = DsmContext; + completionContext->RequestUnique1 = deviceInfo; + completionContext->RequestUnique2 = FALSE; + + tpgCompletionContext->CompletionContext = completionContext; + tpgCompletionContext->Srb = srb; + tpgCompletionContext->SenseInfoBuffer = senseInfo; + tpgCompletionContext->SenseInfoBufferLength = senseInfoLength; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Sending down TPG asynchronously for %p using devInfo %p (path %p).\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId, + deviceInfo, + deviceInfo->FailGroup->PathId)); + + if (deviceInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT) { + + status = DsmpSetTargetPortGroupsAsync(deviceInfo, + DsmpPhase1ProcessPathFailingALUA, + tpgCompletionContext, + targetPortGroupsInfoLength, + targetPortGroupsInfo); + } else { + + status = DsmpReportTargetPortGroupsAsync(deviceInfo, + DsmpPhase2ProcessPathFailingALUA, + tpgCompletionContext, + targetPortGroupsInfoLength, + targetPortGroupsInfo); + } + + if (status != STATUS_PENDING) { + + // + // Request not sent down successfully. Free the allocations. + // + DsmpFreePool(targetPortGroupsInfo); + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + DsmpFreePool(srb); + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + + // + // Allow the failing device to be removed. + // + InterlockedDecrement(&FailingDeviceInfo->BlockRemove); + } + } else { + + // + // Fail to build DevInfo entry. Free the allocations. + // + DsmpFreePool(targetPortGroupsInfo); + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + DsmpFreePool(srb); + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + DsmpFreePool(srb); + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + NT_ASSERT(completionContext != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate completion context. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + DsmpFreePool(srb); + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + NT_ASSERT(srb != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate SRB. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + NT_ASSERT(senseInfo != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate senseInfo. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + DsmpFreePool(tpgCompletionContext); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + NT_ASSERT(tpgCompletionContext != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Failed to allocate TPG completion context. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Found alternative devInfo %p for failing path %p without need for TPG\n", + FailingDeviceInfo, + deviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Couldn't find a standby path to activate for failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + deviceInfo = failDevInfoListEntry->TempDeviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): There is an RTPG/STPG already in progress for this path %p. Returning alternative %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId, + deviceInfo)); + } + } else { + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Other paths active, no path made active at %d\n", + FailingDeviceInfo, + __LINE__)); + } + + status = STATUS_SUCCESS; + } + + if (deviceInfo) { + + // + // Update temporarily the next path to be used for the group as this devInfo + // + InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Updating PathToBeUsed in %p to %p\n", + FailingDeviceInfo, + group, + group->PathToBeUsed)); + + } else { + + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpSetLBForPathRemovalALUA (DevInfo %p): No FOG available for group %p\n", + FailingDeviceInfo, + group)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetLBForPathFailingALUA (DevInfo %p): Exiting function with status %x.\n", + FailingDeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpSetPathForIoRetryALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, + _In_ IN BOOLEAN TPGException, + _In_ IN BOOLEAN DeviceInfoException + ) +/*++ + +Routine Description: + + This routine is called when an IO that was sent using this path fails with + a retry-able "ALUA" error. What this basically means is that most likely an + implicit transition has taken place and we need an RTPG to get the updated + path states. The routine will send down a Report Target Port Groups command + asynchronously to get the paths states (actual work done in the completion + routine). + + Note: This should NOT be called with DsmContext Lock held + This is used for devices supporting ALUA. + +Arguements: + + DsmContext is the DSM context + + FailingDeviceInfo is the device info for the failing/going-away path + + TPGException is a flag used to indicate if the selected path must be from a + TPG that is different from FailingDeviceInfo's. This is + special handling for UA with sense "TPG in SB/UA state" + + DeviceInfoException is a flag used to indicate that the current FailindDeviceInfo + itself needs to be used again. This is special handling for + UA with sense "Asymmetric Access State Changed" + + (NOTE: TPGException and DeviceInfoException are mutually exclusive, although + it is okay for both to be FALSE) + +Return Value: + + Status + +--*/ +{ + PDSM_GROUP_ENTRY group; + PDSM_DEVICE_INFO deviceInfo = NULL; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength; + PDSM_COMPLETION_CONTEXT completionContext = NULL; + PVOID senseInfo = NULL; + PSCSI_REQUEST_BLOCK srb = NULL; + PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = NULL; + NTSTATUS throttleStatus = STATUS_UNSUCCESSFUL; + ULONG inflightRTPG; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Entering function.\n", + FailingDeviceInfo)); + + group = FailingDeviceInfo->Group; + + + if (group->LoadBalanceType < DSM_LB_FAILOVER || + group->LoadBalanceType > DSM_LB_LEAST_BLOCKS) { + + status = STATUS_INVALID_PARAMETER; + + } else { + + // + // First check to see if we need to find a candidate from a different TPG. + // + if (TPGException) { + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Find a candidate in a TPG that is different from this one + // + deviceInfo = DsmpFindStandbyPathInAlternateTpgALUA(group, FailingDeviceInfo, SpecialHandlingFlag); + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Need to try a different TPG deviceInfo %p.\n", + FailingDeviceInfo, + deviceInfo)); + + } else if (DeviceInfoException) { + + // + // Retry on the same path + // + deviceInfo = FailingDeviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Will retry using same deviceInfo %p.\n", + FailingDeviceInfo, + deviceInfo)); + } + + // + // Check if an Report TPG has already been sent for this group + // + inflightRTPG = InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 0, 0); + + // + // If there is no RTPG currently in flight, use the best candidate found + // above to send down the RTPG. If there is already an RTPG inflight, + // we're done. The result of the RTPG should fix the path states. + // + if (!inflightRTPG) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): No RTPG in flight. Try sending one down.\n", + FailingDeviceInfo)); + + // + // If we need a candidate device, first get the currently active one. + // If we can't find one that way, resort to finding the best alternative. + // Basic idea is find SOME path instead of failing IOs back to the application. + // + if (!deviceInfo) { + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Find the best candidate - ie. either a currently A/O path or + // the best alternative path to be made A/O. + // + deviceInfo = DsmpGetAnyActivePath(group, TRUE, deviceInfo, SpecialHandlingFlag); + if (!deviceInfo) { + + BOOLEAN sendTPG = TRUE; + + deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): No active path. Best alternative %p.\n", + FailingDeviceInfo, + deviceInfo)); + } + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + + if (deviceInfo) { + + tpgCompletionContext = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_TPG_COMPLETION_CONTEXT), + DSM_TAG_TPG_COMPLETION_CONTEXT); + + if (tpgCompletionContext) { + UCHAR senseInfoLength = SENSE_BUFFER_SIZE_EX; + + senseInfo = DsmpAllocatePool(NonPagedPoolNx, + senseInfoLength, + DSM_TAG_SCSI_SENSE_INFO); + + if (senseInfo) { + + srb = DsmpAllocatePool(NonPagedPoolNx, + sizeof(SCSI_REQUEST_BLOCK), + DSM_TAG_SCSI_REQUEST_BLOCK); + + if (srb) { + + srb->Length = SCSI_REQUEST_BLOCK_SIZE; + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + + completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); + + if (completionContext) { + + // + // Find an active/optimized target port group that should + // have been set by the controller + // + // Take care of worst case scenario, which is: + // 1. 4-byte header (for allocation length) + // 2. 32 8-byte descriptors (for TPGs) + // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) + // + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + DSM_MAX_PATHS * sizeof(ULONG))); + + targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, + targetPortGroupsInfoLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo) { + + completionContext->DeviceInfo = FailingDeviceInfo; + completionContext->DsmContext = DsmContext; + completionContext->RequestUnique1 = deviceInfo; + completionContext->RequestUnique2 = TRUE; + + tpgCompletionContext->CompletionContext = completionContext; + tpgCompletionContext->Srb = srb; + tpgCompletionContext->SenseInfoBuffer = senseInfo; + tpgCompletionContext->SenseInfoBufferLength = senseInfoLength; + + // + // Now we are all set to send the RTPG request. + // check and set InFlightRTPG to make sure this thread is the only one with + // the RTPG active for this group, since it is possible to have more than one + // threads reaching up to this point in parallel + // + inflightRTPG = InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 1, 0); + if (inflightRTPG) { + + DsmpFreePool(targetPortGroupsInfo); + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + DsmpFreePool(srb); + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + } else { + + // + // Prevent the device info from being removed when a TPG is in-flight. + // + InterlockedIncrement(&FailingDeviceInfo->BlockRemove); + + // + // First try and throttle the IO. The completion routine will + // take care of resuming the IO. + // + if (!InterlockedCompareExchange((LONG volatile*)&group->Throttled, 1, 0)) { + + DsmNotification(((PDSM_CONTEXT)DsmContext)->MPIOContext, + ThrottleIO_V2, + deviceInfo, + FALSE, + &throttleStatus, + 0); + + if (NT_SUCCESS(throttleStatus)) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Successfully throttled IO. About to send RTPG. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + } else { + + // + // Throttle can fail when the MPDisk is + // 1. Being removed. (or) + // 2. In any other state other than Normal or Degraded. + // + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Throttle before RTPG failed. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + InterlockedDecrement((LONG volatile*)&FailingDeviceInfo->Group->Throttled); + } + } else { + + // + // Currently we don't expect this to happen + // + NT_ASSERT(FALSE); + } + + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Sending RTPG asynchronously. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + if (STATUS_PENDING != DsmpReportTargetPortGroupsAsync(deviceInfo, + DsmpPhase2ProcessPathFailingALUA, + tpgCompletionContext, + targetPortGroupsInfoLength, + targetPortGroupsInfo)) { + + + + // + // Request not sent down successfully. Free the allocations. + // + DsmpFreePool(targetPortGroupsInfo); + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + DsmpFreePool(srb); + DsmpFreePool(senseInfo); + DsmpFreePool(tpgCompletionContext); + + // + // Allow the failing device to be removed. + // + InterlockedDecrement(&FailingDeviceInfo->BlockRemove); + + // + // Resume IO if we throttled requests before calling DsmpReportTargetPortGroupsAsync + // + if (InterlockedCompareExchange((LONG volatile*)&group->Throttled, 0, 1)) { + + NTSTATUS resumeStatus = STATUS_UNSUCCESSFUL; + + DsmNotification(((PDSM_CONTEXT)deviceInfo->DsmContext)->MPIOContext, + ResumeIO_V2, + deviceInfo, + TRUE, + &resumeStatus, + 0); + + if (!NT_SUCCESS(resumeStatus)) { + + // + // Resume can fail when + // 1. The MPDisk is being removed (or) + // 2. The MPDisk is any other state other than throttled (or) + // 3. There is a problem dispatching throttled requests. + // + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Resume IO failed.\n", + deviceInfo)); + } + + } + + InterlockedDecrement((LONG volatile*)&group->InFlightRTPG); + } + } + } else { + + NT_ASSERT(targetPortGroupsInfo != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate TPG info buffer. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + ExFreePool(srb); + ExFreePool(senseInfo); + ExFreePool(tpgCompletionContext); + } + } else { + + NT_ASSERT(completionContext != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate completion context. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + ExFreePool(srb); + ExFreePool(senseInfo); + ExFreePool(tpgCompletionContext); + } + } else { + + NT_ASSERT(srb != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate SRB. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + ExFreePool(senseInfo); + ExFreePool(tpgCompletionContext); + } + } else { + + NT_ASSERT(senseInfo != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate senseInfo. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + + ExFreePool(tpgCompletionContext); + } + } else { + + NT_ASSERT(tpgCompletionContext != NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't allocate TPG completion context. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + } + } else { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Couldn't find a path for RTPG. Failing path %p.\n", + FailingDeviceInfo, + FailingDeviceInfo->FailGroup->PathId)); + } + } else { + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Other paths active, no path made active at %d\n", + FailingDeviceInfo, + __LINE__)); + } + + if(!deviceInfo) { + + // + // It is possible that there are only two TPGs with one of them in U/A + // state and the other in transitioning state. In such a case, we would + // not find an alternative TPG deviceInfo. In addition, if there is an + // RTPG in flight, we won't go down the path of forcibly picking any + // deviceInfo. This is to cover that scenario, else we're left with no + // deviceInfo to do the retry and we'll end up setting the group's PTBU + // to NULL thus failing the retried request (if for eg. the LB is RRWS). + // Need to ensure that we handle this exception case. + // + if (inflightRTPG) { + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Find the best candidate - ie. either a currently A/O path or + // the best alternative path to be made A/O. + // + deviceInfo = DsmpGetAnyActivePath(group, TRUE, deviceInfo, SpecialHandlingFlag); + if (!deviceInfo) { + + BOOLEAN sendTPG = TRUE; + + deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + } + + if(deviceInfo) { + + // + // Update temporarily the next path to be used for the group as this devInfo + // + InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Updating PathToBeUsed in %p to %p\n", + FailingDeviceInfo, + group, + group->PathToBeUsed)); + + } else { + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): No FOG available for group %p\n", + FailingDeviceInfo, + group)); + } + + status = STATUS_SUCCESS; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetPathForIoRetryALUA (DevInfo %p): Exiting function with status %x.\n", + FailingDeviceInfo, + status)); + + return status; +} + + +PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY +DsmpFindFailPathDevInfoEntry( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO FailingDevInfo + ) +/*++ + +Routine Description: + + This routine finds the entry that contains the alternate devInfo to use for + a failing one for the passed in devInfo. + + N.B: This routine MUST be called with DsmContextLock held in either Shared or + Exclusive mode. + +Arguments: + + Context is the DSM's context info. + + Group is the group entry representing the device. + + FailingDevInfo is the device info whose entry needs to be found. + +Return Value: + + Pointer to the entry. NULL if it doesn't exist. + +--*/ +{ + PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; + PLIST_ENTRY entry = NULL; + + UNREFERENCED_PARAMETER(Context); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpFindFailPathDevInfoEntry (DevInfo %p): Entering function.\n", + FailingDevInfo)); + + for (entry = Group->FailingDevInfoList.Flink; + entry != &Group->FailingDevInfoList; + entry = entry->Flink) { + + failDevInfoListEntry = CONTAINING_RECORD(entry, DSM_FAIL_PATH_PROCESSING_LIST_ENTRY, ListEntry); + NT_ASSERT(failDevInfoListEntry); + + if (failDevInfoListEntry) { + + if (failDevInfoListEntry->FailingDeviceInfo == FailingDevInfo) { + + break; + + } else { + + failDevInfoListEntry = NULL; + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpFindFailPathDevInfoEntry (DevInfo %p): Exiting function returning entry %p.\n", + FailingDevInfo, + failDevInfoListEntry)); + + return failDevInfoListEntry; +} + + +PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY +DsmpBuildFailPathDevInfoEntry( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO FailingDevInfo, + _In_ IN PDSM_DEVICE_INFO AlternateDevInfo + ) +/*++ + +Routine Description: + + When InterpretError() is called with an IRP that has failed with a fatal error, + if the device is ALUA it is possible that STPG needs to be sent to update a new + devInfo as being Active/Optimized. However, for in-flight IOs that weren't + queued by MPIO, we still need to return a path that can be used. + + This routine is builds an entry that contains the alternate devInfo to use for + a failing one. + + NOTE: Calling function should be holding the spin lock. + +Arguments: + + Context is the DSM's context info. + + Group is the group entry representing the device. + + FailingDevInfo is the device info that was used when the IRP failed. + + AlternateDevInfo is the new one to temporarily use until its state can be properly set. + +Return Value: + + Pointer to the newly built entry. + NULL if there were any errors building it. + +--*/ +{ + PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; + + UNREFERENCED_PARAMETER(Context); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpBuildFailPathDevInfoEntry (DevInfo %p): Entering function.\n", + FailingDevInfo)); + + failDevInfoListEntry = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_FAIL_PATH_PROCESSING_LIST_ENTRY), + DSM_TAG_FAIL_DEVINFO_LIST_ENTRY); + + if (failDevInfoListEntry) { + + failDevInfoListEntry->FailingDeviceInfo = FailingDevInfo; + failDevInfoListEntry->TempDeviceInfo = AlternateDevInfo; + InsertTailList(&Group->FailingDevInfoList, &failDevInfoListEntry->ListEntry); + InterlockedIncrement((LONG volatile*)&Group->NumberFailingDevInfos); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpBuildFailPathDevInfoEntry (DevInfo %p): Failed to allocate memory for entry.\n", + FailingDevInfo)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpBuildFailPathDevInfoEntry (DevInfo %p): Exiting function returning entry %p.\n", + FailingDevInfo, + failDevInfoListEntry)); + + return failDevInfoListEntry; +} + + +NTSTATUS +DsmpPhase1ProcessPathFailingALUA( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +/*++ + +Routine Description: + + This is the completion routine that is called when the STPG is sent down by + DsmpSetLBForPathFailingALUA. + + The caller SHOULD NOT acquire the DSM Context lock before calling this routine. + +Arguements: + + DeviceObject is the target device object to which Irp was sent + + Irp is the scsi pass through request for STPG + + Context is the completion context. + +Return Value: + + Status + +--*/ +{ + PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); + PDSM_TPG_COMPLETION_CONTEXT context = (PDSM_TPG_COMPLETION_CONTEXT)Context; + PSCSI_REQUEST_BLOCK srb = context->Srb; + PVOID senseData = context->SenseInfoBuffer; + UCHAR senseDataLength = context->SenseInfoBufferLength; + NTSTATUS status = Irp->IoStatus.Status; + ULONG targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); + PUCHAR targetPortGroupsInfo; + PDSM_DEVICE_INFO deviceInfo = (PDSM_DEVICE_INFO)(context->CompletionContext->RequestUnique1); + PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; + BOOLEAN releaseCompletionContextResources = TRUE; + KIRQL irql; + UCHAR scsiStatus = SrbGetScsiStatus(srb); + + UNREFERENCED_PARAMETER(DeviceObject); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): Entering function.\n", + deviceInfo)); + +#if DBG + KeQuerySystemTime(&context->CompletionContext->TickCount); +#endif + + if ((scsiStatus == SCSISTAT_GOOD) && + (NT_SUCCESS(status))) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): STPG succeeded.\n", + deviceInfo)); + + } else if (NT_SUCCESS(status) && + scsiStatus == SCSISTAT_CHECK_CONDITION && + DsmpShouldRetryTPGRequest(senseData, senseDataLength)) { + + if ((context->NumberRetries)--) { + + // + // Retry the request + // + + NT_ASSERT(SrbGetDataBuffer(srb) == MmGetMdlVirtualAddress(Irp->MdlAddress)); + + // + // Reset byte count of transfer in SRB Extension. + // + SrbSetDataTransferLength(srb, Irp->MdlAddress->ByteCount); + + // + // Zero SRB statuses. + // + srb->SrbStatus = 0; + SrbSetScsiStatus(srb, 0); + + nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + nextIrpStack->MinorFunction = IRP_MN_SCSI_CLASS; + + // + // Save SRB address in next stack for port driver. + // + nextIrpStack->Parameters.Scsi.Srb = srb; + IoSetCompletionRoutine(Irp, DsmpPhase1ProcessPathFailingALUA, Context, TRUE, TRUE, TRUE); + + IoMarkIrpPending(Irp); + + // + // Send the IRP asynchronously + // + DsmSendRequestEx(context->CompletionContext->DsmContext->MPIOContext, + deviceInfo->TargetObject, + Irp, + deviceInfo, + DSM_CALL_COMPLETION_ON_MPIO_ERROR); + + // + // We know that the completion routine will always be called. + // + status = STATUS_PENDING; + goto __Exit_DsmpPhase1ProcessPathFailingALUA; + } + } else { + + irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); + + failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + context->CompletionContext->DeviceInfo); + + if (failDevInfoListEntry) { + + DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + failDevInfoListEntry); + } + + ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): NTStatus 0%x, ScsiStatus 0x%x.\n", + deviceInfo, + status, + scsiStatus)); + } + + if (NT_SUCCESS(status)) { + + // + // An explicit transition may cause changes to some other TPGs. + // So we need to query for the states of all the TPGs and update + // our internal list and its elements. + // + + // + // Take care of worst case scenario, which is: + // 1. 4-byte header (for allocation length) + // 2. 32 8-byte descriptors (for TPGs) + // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) + // + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + DSM_MAX_PATHS * sizeof(ULONG))); + + targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, + targetPortGroupsInfoLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo) { + + if (STATUS_PENDING == DsmpReportTargetPortGroupsAsync(deviceInfo, + DsmpPhase2ProcessPathFailingALUA, + Context, + targetPortGroupsInfoLength, + targetPortGroupsInfo)) { + + releaseCompletionContextResources = FALSE; + + } else { + + DsmpFreePool(targetPortGroupsInfo); + } + } else { + + irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); + + failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + context->CompletionContext->DeviceInfo); + + if (failDevInfoListEntry) { + + DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + failDevInfoListEntry); + } + + ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); + } + } + + // + // Free the allocations. + // + IoFreeMdl(Irp->MdlAddress); + Irp->MdlAddress = NULL; + + DsmpFreePool(Irp->UserBuffer); + + IoFreeIrp(Irp); + Irp = (PIRP) NULL; + + if (releaseCompletionContextResources) { + + // + // Release our hold on the device info so that it can be removed. + // + InterlockedDecrement(&context->CompletionContext->DeviceInfo->BlockRemove); + + ExFreeToNPagedLookasideList(&(context->CompletionContext->DsmContext)->CompletionContextList, context->CompletionContext); + DsmpFreePool(context->Srb); + DsmpFreePool(context->SenseInfoBuffer); +#pragma warning(suppress:6001) // DevDiv 818965 + DsmpFreePool(context); + } + +__Exit_DsmpPhase1ProcessPathFailingALUA: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpPhase1ProcessPathFailingALUA (DevInfo %p): Exiting function.\n", + deviceInfo)); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + + +NTSTATUS +DsmpRemoveFailPathDevInfoEntry( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY FailPathDevInfoEntry + ) +/*++ + +Routine Description: + + This routine removes the entry pointed to from the passed in Group's list. + + NOTE: Calling function should be holding the spin lock. + +Arguments: + + Context is the DSM's context info. + + Group is the group entry representing the device. + + FailingPathDevInfoEntry is the entry that needs to be removed. + +Return Value: + + STATUS_SUCCESS if successful, else appropriate NT error code. + +--*/ +{ + PLIST_ENTRY entry = &FailPathDevInfoEntry->ListEntry; + PDSM_DEVICE_INFO deviceInfo = FailPathDevInfoEntry->FailingDeviceInfo; + NTSTATUS status = STATUS_SUCCESS; + + UNREFERENCED_PARAMETER(Context); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpRemoveFailPathDevInfoEntry (DevInfo %p): Entering function.\n", + deviceInfo)); + + RemoveEntryList(entry); + DsmpFreePool(FailPathDevInfoEntry); + InterlockedDecrement((LONG volatile*)&Group->NumberFailingDevInfos); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpRemoveFailPathDevInfoEntry (DevInfo %p): Exiting function with status %x.\n", + deviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpPhase2ProcessPathFailingALUA( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +/*++ + +Routine Description: + + This is the completion routine that is called when the RTPG is sent down by + DsmpPhase1ProcessPathFailingALUA. + + The caller SHOULD NOT acquire the DSM Context lock before calling this routine. + +Arguements: + + DeviceObject is the target device object to which Irp was sent + + Irp is the scsi pass through request for RTPG + + Context is the completion context. + +Return Value: + + Status + +--*/ +{ + PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); + PDSM_TPG_COMPLETION_CONTEXT context = (PDSM_TPG_COMPLETION_CONTEXT)Context; + PSCSI_REQUEST_BLOCK srb = context->Srb; + PVOID senseData = context->SenseInfoBuffer; + UCHAR senseDataLength = context->SenseInfoBufferLength; + NTSTATUS status = Irp->IoStatus.Status; + PUCHAR header; + ULONG returnedDataLength = 0; + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength = 0; + PDSM_DEVICE_INFO deviceInfo = (PDSM_DEVICE_INFO)(context->CompletionContext->RequestUnique1); + BOOLEAN decrementRTPGcount = (BOOLEAN)(context->CompletionContext->RequestUnique2); + KIRQL irql; + ULONG index; + PDSM_DEVICE_INFO devInfo; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = NULL; + PDSM_GROUP_ENTRY group = deviceInfo->Group; + PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failDevInfoListEntry = NULL; + UCHAR scsiStatus = SrbGetScsiStatus(srb); + + UNREFERENCED_PARAMETER(DeviceObject); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Entering function.\n", + deviceInfo)); + +#if DBG + KeQuerySystemTime(&(context->CompletionContext)->TickCount); +#endif + + if ((status == STATUS_BUFFER_OVERFLOW) || + (NT_SUCCESS(status) && + (scsiStatus == SCSISTAT_GOOD))) { + + header = (PUCHAR)((PUCHAR)SrbGetDataBuffer(srb)); + GetUlongFrom4ByteArray(header, returnedDataLength); + + status = STATUS_SUCCESS; + if (returnedDataLength > SrbGetDataTransferLength(srb)) { + + status = STATUS_BUFFER_OVERFLOW; + } + } + + if ((scsiStatus == SCSISTAT_GOOD) && + (NT_SUCCESS(status))) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): RTPG using path %p succeeded.\n", + deviceInfo, + deviceInfo->FailGroup->PathId)); + + header = (PUCHAR)((PUCHAR)SrbGetDataBuffer(srb)); + GetUlongFrom4ByteArray(header, returnedDataLength); + + // + // Allocate a buffer to hold the TPG info. + // + targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + returnedDataLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo) { + + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + returnedDataLength; + + // + // Copy it over. + // + RtlCopyMemory(targetPortGroupsInfo, + header, + targetPortGroupsInfoLength); + + } else { + + irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); + + failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + context->CompletionContext->DeviceInfo); + + if (failDevInfoListEntry) { + + DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + failDevInfoListEntry); + } + + ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Failed to allocate mem for TPG.\n", + deviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + + } else if (NT_SUCCESS(status) && + scsiStatus == SCSISTAT_CHECK_CONDITION && + DsmpShouldRetryTPGRequest(senseData, senseDataLength)) { + + if ((context->NumberRetries)--) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Retrying check condition using path %p. Retries remaining %u.\n", + deviceInfo, + deviceInfo->FailGroup->PathId, + context->NumberRetries)); + + // + // Retry the request + // + + NT_ASSERT(SrbGetDataBuffer(srb) == MmGetMdlVirtualAddress(Irp->MdlAddress)); + + // + // Reset byte count of transfer in SRB Extension to true length. + // + SrbSetDataTransferLength(srb, targetPortGroupsInfoLength); + + // + // Zero SRB statuses. + // + srb->SrbStatus = 0; + SrbSetScsiStatus(srb, 0); + + nextIrpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + nextIrpStack->MinorFunction = IRP_MN_SCSI_CLASS; + + // + // Save SRB address in next stack for port driver. + // + nextIrpStack->Parameters.Scsi.Srb = srb; + IoSetCompletionRoutine(Irp, DsmpPhase2ProcessPathFailingALUA, Context, TRUE, TRUE, TRUE); + + IoMarkIrpPending(Irp); + + // + // Send the IRP asynchronously + // + DsmSendRequestEx(context->CompletionContext->DsmContext->MPIOContext, + deviceInfo->TargetObject, + Irp, + deviceInfo, + DSM_CALL_COMPLETION_ON_MPIO_ERROR); + + // + // We know that the completion routine will always be called. + // + status = STATUS_PENDING; + goto __Exit_DsmpPhase2ProcessPathFailingALUA; + } + } else { + + irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); + + failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + context->CompletionContext->DeviceInfo); + + if (failDevInfoListEntry) { + + DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + failDevInfoListEntry); + } + + ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): NTStatus 0%x, ScsiStatus 0x%x.\n", + deviceInfo, + status, + SrbGetScsiStatus(srb))); + + // Failed to get TPG Info. + // Here it is possible status is success, but scsiStatus is not. + // If so, set status to unsuccessful. + + if (NT_SUCCESS(status)) { + status = STATUS_UNSUCCESSFUL; + } + } + + if (NT_SUCCESS(status)) { + + irql = ExAcquireSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock)); + + // + // Parse the TPG information and update the device path states + // + status = DsmpParseTargetPortGroupsInformation(context->CompletionContext->DsmContext, + deviceInfo->Group, + targetPortGroupsInfo, + targetPortGroupsInfoLength); + + for (index = 0; index < DSM_MAX_PATHS; index++) { + + targetPortGroup = deviceInfo->Group->TargetPortGroupList[index]; + + if (targetPortGroup) { + + DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); + } + } + + if (NT_SUCCESS(status)) { + + PDSM_DEVICE_INFO tempDevice = NULL; + + // + // Update all the devInfo states. If the device is AO but + // not this device, make it fake AU. + // If device not in AO, make sure that it matches the TPG + // state. + // Ensure that: + // 1. All devices match their ALUA state. + // 2. For RRWS, if a device's desired state is non-A/O, but ALUA state is A/O, mask it. + // 3. For FOO there must be only one A/O device. Preferably the preferred path. + // + for (index = 0; index < DSM_MAX_PATHS; index++) { + + devInfo = group->DeviceList[index]; + + if (devInfo) { + + if (devInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { + + // + // In implicit transitions, there is no guarantee that + // the TPG of chosen "deviceInfo" is in A/O state. So + // to play it safe, we hang on to the very first devInfo + // whose TPG is in A/O state. + // + if (!tempDevice && + !DsmpIsDeviceFailedState(devInfo->State)) { + + devInfo->PreviousState = devInfo->State; + devInfo->State = devInfo->ALUAState; + + tempDevice = devInfo; + } + + if (devInfo != deviceInfo) { + + if (!DsmpIsDeviceFailedState(devInfo->State)) { + + // + // For FOO, only one path can be in A/O. + // For RRWS, mask an A/O path if that isn't the desired state. + // + if ((group->LoadBalanceType == DSM_LB_FAILOVER) || + (group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET && + devInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + devInfo->DesiredState != DSM_DEV_UNDETERMINED)) { + + // + // For implicit transitions, we may have saved off an A/O path. + // Don't undo that. + // + if (tempDevice != devInfo) { + + devInfo->PreviousState = devInfo->State; + devInfo->State = DSM_DEV_ACTIVE_UNOPTIMIZED; + } + + } else { + + devInfo->PreviousState = devInfo->State; + devInfo->State = devInfo->ALUAState; + } + } + } else { + + devInfo->PreviousState = devInfo->State; + + // + // For FOO, only one path can be in A/O state. + // The TPG of the selected "deviceInfo" is in A/O, so this + // can now very well be made the candidate. However, since + // it is possible that we saved off another candidate, we + // now need to replace that with this. + // + if (!DsmpIsDeviceFailedState(devInfo->State) && + devInfo->Group->LoadBalanceType == DSM_LB_FAILOVER && + tempDevice) { + + tempDevice->State = DSM_DEV_ACTIVE_UNOPTIMIZED; + } + + devInfo->State = devInfo->ALUAState; + + tempDevice = devInfo; + } + } else { + + if (!DsmpIsDeviceFailedState(devInfo->State)) { + + devInfo->PreviousState = devInfo->State; + devInfo->State = devInfo->ALUAState; + } + } + } + } + } + + failDevInfoListEntry = DsmpFindFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + context->CompletionContext->DeviceInfo); + + if (failDevInfoListEntry) { + + DsmpRemoveFailPathDevInfoEntry(context->CompletionContext->DsmContext, + context->CompletionContext->DeviceInfo->Group, + failDevInfoListEntry); + } + + ExReleaseSpinLockExclusive(&(context->CompletionContext->DsmContext->DsmContextLock), irql); + } + + + // + // Resume IO if we throttled requests. + // + if (InterlockedCompareExchange((LONG volatile*)&group->Throttled, 0, 1)) { + + NTSTATUS resumeStatus = STATUS_UNSUCCESSFUL; + + DsmNotification(((PDSM_CONTEXT)deviceInfo->DsmContext)->MPIOContext, + ResumeIO_V2, + deviceInfo, + TRUE, + &resumeStatus, + 0); + + if (!NT_SUCCESS(resumeStatus)) { + + // + // Resume can fail when + // 1. The MPDisk is being removed (or) + // 2. The MPDisk is any other state other than throttled (or) + // 3. There is a problem dispatching throttled requests. + // + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevObj %p): Resume IO failed.\n", + DeviceObject)); + } + + } + + if (decrementRTPGcount) { + + // + // Resetting InFlightRTPG after resume so that we don't get into situation where + // new DsmpSetPathForIoRetryALUA caller thread finds that InFlightRTPG is not set but Throttled is set + // + ULONG count = InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 0, 1); + + // + // If decrementRTPGCount flag is set, there must be atleast one RTPG in flight. + // + NT_ASSERT(count); + + UNREFERENCED_PARAMETER(count); + + } + + // + // Free the allocations. + // + if (targetPortGroupsInfo) { + + DsmpFreePool(targetPortGroupsInfo); + } + + // + // Release our hold on the device info so that it can be removed. + // + InterlockedDecrement(&context->CompletionContext->DeviceInfo->BlockRemove); + + IoFreeMdl(Irp->MdlAddress); + Irp->MdlAddress = NULL; + + DsmpFreePool(Irp->UserBuffer); + + IoFreeIrp(Irp); + Irp = (PIRP) NULL; + + ExFreeToNPagedLookasideList(&(context->CompletionContext->DsmContext)->CompletionContextList, context->CompletionContext); + DsmpFreePool(srb); + DsmpFreePool(senseData); +#pragma warning(suppress:6001) // DevDiv 818965 + DsmpFreePool(context); + +__Exit_DsmpPhase2ProcessPathFailingALUA: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpPhase2ProcessPathFailingALUA (DevInfo %p): Exiting function.\n", + deviceInfo)); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + + +NTSTATUS +DsmpPersistentReserveOut( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ) +/*++ + +Routine Description: + + This routine will handle determine which devices to send the request to based + on the service action of the PR-out command. + On REGISTER/REGISTER_AND_IGNORE_EXISTING, it will send the command down all + paths. If any path succeeds, the PR key will be stored. If failure down any + path, return failure. + On REGISTER/REGISTER_AND_IGNORE_EXISTING with key == 0 (ie. UNREGISTER), + the request is sent down every path. Failure is returned if request fails down + any path (but error is ignored if path happens to be one where prior + REGISTER/REGISTER_AND_IGNORE_EXISTING had failed in the first place). The + stored PR key is cleared irrespective of success/failure being returned. + On RESERVE/RELEASE, the command is sent down one path. If it fails, another + path is tried. Failure is returned only if none succeed. + On CLEAR, command is sent down one path. If it fails, another path is tried. + Failure is returned only if none succeed. The stored PR key is cleared + irrespective of success/failure being returned. + On PREEMPT, command is sent down one path. If it fails, another path is + tried. Failure is returned only if none succeed. + On PREEMPT_AND_ABORT, command is sent down one path. Failed request is not + retried. + + NOTE: If a path shows up later, REGISTER_AND_IGNORE_EXISTING request is + built by the IsPathActive routine using the saved PR key and sent down new path. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DsmIds - The collection of DSM IDs that pertain to the MPDISK. + Irp - Irp containing SRB. + Srb - Scsi request block + Event - The event to + +Return Value: + + NTSTATUS of the operation. + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo; + PDSM_DEVICE_INFO servicingDeviceInfo = NULL; + PDSM_GROUP_ENTRY group; + LONG i; + ULONG count; + NTSTATUS status = STATUS_UNSUCCESSFUL; + PDSM_COMPLETION_CONTEXT completionContext; + PCDB cdb = SrbGetCdb(Srb); + UCHAR serviceAction; + NTSTATUS returnStatus = STATUS_SUCCESS; + BOOLEAN sendDownAll = FALSE; + BOOLEAN savePRKeyIfAnySucceed = FALSE; + BOOLEAN retryOnAnother = FALSE; + BOOLEAN passOnlyIfAllSucceed = FALSE; + BOOLEAN ignoreIfPreviousFailed = FALSE; + BOOLEAN clearPRKey = FALSE; + KEVENT event; + PPRO_PARAMETER_LIST prOutParam = Irp->AssociatedIrp.SystemBuffer; + PUCHAR index = NULL; + UCHAR prKey[8] = {0}; + PSTORAGE_REQUEST_BLOCK_HEADER srbCopy = NULL; + PIO_STACK_LOCATION irpStack; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + BOOLEAN statusUpdated = FALSE; + ULONGLONG currentTickCount; + ULONGLONG finalTickCount; + ULONG tickLength = KeQueryTimeIncrement(); + PVOID senseInfoBuffer = NULL; + UCHAR senseInfoBufferLength = 0; + BOOLEAN srbCopySucceeded = FALSE; + UCHAR prType; + UCHAR prScope; + ULONGLONG saKey; + ULONGLONG resKey; + ULONG SpecialHandlingFlag = 0; + + UNREFERENCED_PARAMETER(Event); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // Cache away a copy of the SRB + // + srbCopy = SrbAllocateCopy(Srb, NonPagedPoolNx, DSM_TAG_SCSI_REQUEST_BLOCK); + if (srbCopy == NULL) { + returnStatus = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpPersistentReserveOut; + } + + deviceInfo = DsmIds->IdList[0]; + group = deviceInfo->Group; + + prType = cdb->PERSISTENT_RESERVE_OUT.Type; + prScope = cdb->PERSISTENT_RESERVE_OUT.Scope; + serviceAction = cdb->PERSISTENT_RESERVE_OUT.ServiceAction; + + NT_ASSERT(serviceAction >= RESERVATION_ACTION_REGISTER && serviceAction <= RESERVATION_ACTION_REGISTER_IGNORE_EXISTING); + + index = prOutParam->ServiceActionReservationKey; + RtlCopyMemory(&prKey, index, 8); + REVERSE_BYTES_QUAD(&saKey, &prOutParam->ServiceActionReservationKey); + + REVERSE_BYTES_QUAD(&resKey, &prOutParam->ReservationKey); + + switch (serviceAction) { + case RESERVATION_ACTION_REGISTER: + case RESERVATION_ACTION_REGISTER_IGNORE_EXISTING: { + + // + // The command must be sent down all paths. + // + sendDownAll = TRUE; + + // + // Return failure if it fails down even one of the paths. + // + passOnlyIfAllSucceed = TRUE; + + if (DsmpIsPersistentReservationKeyZeroKey(ARRAY_SIZE(prKey), prKey)) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): NULL PR key, service action %u\n", + DsmIds, + serviceAction)); + + // + // If unregister fails, don't report it back as error if the + // previous register/register_and_ignore_existing down that + // path had failed too. + // + ignoreIfPreviousFailed = TRUE; + + // + // Clear the group PR key irrespective of the status that is + // going to be returned to clusdisk. + // + clearPRKey = TRUE; + + } else { + + // + // If register/register_and_ignore_existing succeed down any of + // the paths, save off the PR key for the group entry. + // + savePRKeyIfAnySucceed = TRUE; + } + + break; + } + + case RESERVATION_ACTION_RESERVE: + case RESERVATION_ACTION_RELEASE: + case RESERVATION_ACTION_PREEMPT: + case RESERVATION_ACTION_PREEMPT_ABORT: + case RESERVATION_ACTION_CLEAR: { + + if (serviceAction != RESERVATION_ACTION_PREEMPT_ABORT) { + + // + // Apart from preempt_abort, all the others must be retried + // (down another path) if they fail down the chosen path. + // + retryOnAnother = TRUE; + } + + if (serviceAction == RESERVATION_ACTION_CLEAR) { + + // + // Clear the stored PR key for the group entry irrespective of + // the status that is going to be returned back. + // + clearPRKey = TRUE; + } + + break; + } + + default: { + + returnStatus = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): Invalid service action %u.\n", + DsmIds, + serviceAction)); + + goto __Exit_DsmpPersistentReserveOut; + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): Srb %p, Service Action %u, Type %u, Scope %u, \ + \n\t\t\t\tservice action reservation key %I64x, reservation key %I64x.\n", + DsmIds, + Srb, + serviceAction, + prType, + prScope, + saKey, + resKey)); + + // + // Allocate a context for the completion routine. + // + completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); + if (!completionContext) { + + returnStatus = STATUS_INSUFFICIENT_RESOURCES; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Failed to allocate completion context.\n", + DsmIds, + serviceAction)); + + goto __Exit_DsmpPersistentReserveOut; + } + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Indicate the target for this request. + // + completionContext->DsmContext = DsmContext; + completionContext->RequestUnique1 = (PVOID)&event; + completionContext->RequestUnique2 = cdb->PERSISTENT_RESERVE_OUT.OperationCode; + + count = group->NumberDevices; + + for (i = count - 1; i >= 0; i--) { + + // + // A PR command may fail with a "retry-able" UA when reservation is + // released or preempted (on every I_T_L nexus except the one on which + // it was released/preempted). In such a case we should retry the PR + // command on the same path. + // + KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); + finalTickCount = currentTickCount + (DSM_SECONDS_TO_TICKS(group->MaxPRRetryTimeDuringStateTransition) / tickLength); + + if (!sendDownAll && !retryOnAnother) { + + // + // If the request doesn't need to be retried (down another path) on + // failure, better choose the path that has maximum chances of + // success. + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmIds->IdList[0]), + SpecialHandlingFlag); + + if (!deviceInfo) { + + returnStatus = STATUS_UNSUCCESSFUL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - No active/alternative path for device %p.\n", + DsmIds, + serviceAction, + group)); + + break; + } + + } else { + + deviceInfo = group->DeviceList[i]; + + // + // Ignore "bad" paths for now. If the path becomes "good" again, + // IsPathActive() will send down the register. + // Also, don't consider newly arrived paths for which the group has + // a reservation but register has not yet been sent down. This rule + // applies only to requests that are not Register. + // + if ((DsmpIsDeviceFailedState(deviceInfo->State) || !DsmpIsDeviceInitialized(deviceInfo)) || + (!DsmpIsDeviceUsablePR(deviceInfo) && !sendDownAll)) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): Ignoring bad instance - state %x, init %x, key reg %x (key valid %x).\n", + DsmIds, + deviceInfo->State, + deviceInfo->Initialized, + deviceInfo->PRKeyRegistered, + deviceInfo->Group->PRKeyValid)); + + deviceInfo = NULL; + } + + } + + if (!deviceInfo) { + + // + // Maybe a remove came through and caused a collapse of the device + // list, thus making this entry empty. + // + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Couldn't find path for device %p.\n", + DsmIds, + serviceAction, + group)); + + continue; + } + +__DsmpPersistentReserveOut_RetryRequest: + + IoMarkIrpPending(Irp); + + completionContext->DeviceInfo = deviceInfo; + + // + // Set-up a completion routine. + // + IoSetCompletionRoutine(Irp, + DsmpPersistentReserveCompletion, + completionContext, + TRUE, + TRUE, + TRUE); + + // + // Always send the original request down a new path + // + irpStack = IoGetNextIrpStackLocation(Irp); + srbCopySucceeded = SrbCopySrb(Srb, SrbGetSrbLength(Srb), srbCopy); + NT_ASSERT(srbCopySucceeded == TRUE); + irpStack->Parameters.Scsi.Srb = Srb; + + // + // Clear the sense buffer if it exists + // + senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); + senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); + if (senseInfoBuffer) { + RtlZeroMemory(senseInfoBuffer, senseInfoBufferLength); + } + + servicingDeviceInfo = deviceInfo; + + // + // Issue the request and wait. + // + status = DsmSendRequest(DsmContext->MPIOContext, + deviceInfo->TargetObject, + Irp, + deviceInfo); + + if (status == STATUS_PENDING) { + + KeWaitForSingleObject(&event, + Executive, + KernelMode, + FALSE, + NULL); + + status = Irp->IoStatus.Status; + } + + if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u sent down successfully on %p.\n", + DsmIds, + serviceAction, + deviceInfo->FailGroup->PathId)); + + if (!passOnlyIfAllSucceed) { + + // + // Success down any one path means success + // + returnStatus = status; + } + + if (savePRKeyIfAnySucceed) { + + RtlCopyMemory(&group->PersistentReservationRegisteredKey, &prKey, 8); + + group->PRServiceAction = serviceAction; + group->PRType = prType; + group->PRScope = prScope; + group->PRKeyValid = TRUE; + deviceInfo->PRKeyRegistered = TRUE; + } + + if (!sendDownAll) { + + // + // Need for retrying on another path only necessary in the case + // of request failing down the chosen path. Since the request + // succeeded down this path, we are done. + // + break; + } + } else { + + BOOLEAN recordFailure; + + // + // Check to see if the request failed because of a "transient error", + // like reservations released for example. If so, this is NOT an actual + // error and the request must be retried. Multiple retries may be required + // if for example the UA indicates that the TPGs are in transitioning state. + // + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && + Srb->SrbStatus & SRB_STATUS_ERROR && + SrbGetScsiStatus(Srb) == SCSISTAT_CHECK_CONDITION) { + + KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); + + senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); + senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); + + if (DsmpShouldRetryPersistentReserveCommand(senseInfoBuffer, senseInfoBufferLength) && + currentTickCount < finalTickCount) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u returned UA with error %x. Retrying same path %p.\n", + DsmIds, + serviceAction, + status, + deviceInfo->FailGroup->PathId)); + + KeResetEvent(&event); + Irp->IoStatus.Status = 0; + + goto __DsmpPersistentReserveOut_RetryRequest; + } + } + + // + // The return status is STATUS_SUCCESS by default. This means that if the + // request failed on the first path and was retried down every other path + // but fails down all of them, the return status is never updated. + // So cache the first failure status to cover the above scenario. + // + if (!statusUpdated) { + + returnStatus = status; + statusUpdated = TRUE; + } + + recordFailure = TRUE; + if (ignoreIfPreviousFailed && !deviceInfo->PRKeyRegistered) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Ignoring status %x for path %p.\n", + DsmIds, + serviceAction, + status, + deviceInfo->FailGroup->PathId)); + + // + // Okay to ignore this failure if the previous failed. + // + recordFailure = FALSE; + } + + if (passOnlyIfAllSucceed && recordFailure) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u - Saving status %x for return.\n", + DsmIds, + serviceAction, + status)); + + // + // Save the failure status to return back. + // + returnStatus = status; + } + + // + // If the request is not to be sent down all paths, and also + // a retry (along a different path) on failure is not required, + // we're done - just return this failure. + // + if (!(sendDownAll || retryOnAnother)) { + + returnStatus = status; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u sent down %p failed with %x. Breaking out.\n", + DsmIds, + serviceAction, + deviceInfo->FailGroup->PathId, + status)); + + break; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT %u sent down %p failed with %x. Sending down another path.\n", + DsmIds, + serviceAction, + deviceInfo->FailGroup->PathId, + status)); + } + } + + // + // If we are here, it is either because the request needs to be sent down + // all paths, or because the request failed down the chosen path and needs + // to be retried down a new path. + // + KeResetEvent(&event); + Irp->IoStatus.Status = 0; + } + + if (clearPRKey) { + + for (i = 0; (ULONG)i < group->NumberDevices; i++) { + + deviceInfo = group->DeviceList[i]; + + if (deviceInfo) { + + deviceInfo->RegisterServiced = FALSE; + deviceInfo->PRKeyRegistered = FALSE; + } + } + group->PersistentReservationRegisteredKey[0] = group->PersistentReservationRegisteredKey[1] = + group->PersistentReservationRegisteredKey[2] = group->PersistentReservationRegisteredKey[3] = + group->PersistentReservationRegisteredKey[4] = group->PersistentReservationRegisteredKey[5] = + group->PersistentReservationRegisteredKey[6] = group->PersistentReservationRegisteredKey[7] = 0; + + group->PRKeyValid = FALSE; + group->ReservationList = 0; + } + + if (savePRKeyIfAnySucceed && group->PRKeyValid) { + + ULONG ordinal; + + for (i = 0; (ULONG)i < group->NumberDevices; i++) { + + deviceInfo = group->DeviceList[i]; + + if (deviceInfo) { + + deviceInfo->RegisterServiced = TRUE; + ordinal = (1 << i); + group->ReservationList |= ordinal; + } + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): PR_OUT for %u completed with status %x.\n", + DsmIds, + serviceAction, + returnStatus)); + + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + +__Exit_DsmpPersistentReserveOut: + + if (srbCopy != NULL) { + DsmpFreePool(srbCopy); + } + + currentIrpStack->Parameters.Others.Argument3 = servicingDeviceInfo; + Irp->IoStatus.Status = returnStatus; + if ((!NT_SUCCESS(returnStatus)) && + (SrbGetSrbStatus(Srb) == SRB_STATUS_SUCCESS)) { + SrbSetSrbStatus(Srb, DsmpNtStatusToSrbStatus(returnStatus)); + } + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveOut (DsmIds %p): Exiting function returning IRP status %x.\n", + DsmIds, + returnStatus)); + + return returnStatus; +} + + + +NTSTATUS +DsmpPersistentReserveIn( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ) +/*++ + +Routine Description: + + This routine will handle determine which devices to send the request to based + on the service action of the PR-in command. + On READ KEYS, it will send down one path. In case of failure, other paths will + be tried until one succeeds. Failure is returned only if it fails down all paths. + On READ_RESERVATION/REPORT_CAPABILITIES, command is sent down one path. Failed + request is not retried. + +Arguments: + + DsmContext - DSM context given to MPIO during initialization + DsmIds - The collection of DSM IDs that pertain to the MPDISK. + Irp - Irp containing SRB. + Srb - Scsi request block + Event - The event to + +Return Value: + + NTSTATUS of the operation. + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo; + PDSM_DEVICE_INFO servicingDeviceInfo = NULL; + PDSM_GROUP_ENTRY group; + LONG i; + ULONG count; + NTSTATUS status = STATUS_UNSUCCESSFUL; + PDSM_COMPLETION_CONTEXT completionContext; + PCDB cdb = SrbGetCdb(Srb); + UCHAR serviceAction; + BOOLEAN retryOnAnother = FALSE; + KEVENT event; + PSTORAGE_REQUEST_BLOCK_HEADER srbCopy = NULL; + PIO_STACK_LOCATION irpStack; + PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); + ULONGLONG currentTickCount; + ULONGLONG finalTickCount; + ULONG tickLength = KeQueryTimeIncrement(); + PVOID senseInfoBuffer = NULL; + UCHAR senseInfoBufferLength = 0; + BOOLEAN srbCopySucceeded = FALSE; + ULONG SpecialHandlingFlag = 0; + + UNREFERENCED_PARAMETER(Event); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // Cache away a copy of the SRB + // + srbCopy = SrbAllocateCopy(Srb, NonPagedPoolNx, DSM_TAG_SCSI_REQUEST_BLOCK); + if (srbCopy == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpPersistentReserveIn; + } + + deviceInfo = DsmIds->IdList[0]; + group = deviceInfo->Group; + + serviceAction = cdb->PERSISTENT_RESERVE_IN.ServiceAction; + + switch (serviceAction) { + case RESERVATION_ACTION_READ_RESERVATIONS: + case RESERVATION_ACTION_READ_KEYS: { + + // + // If there is a failure on the chosen path, retry on another path. + // + retryOnAnother = TRUE; + break; + } + + case SPC3_RESERVATION_ACTION_REPORT_CAPABILITIES: { + + break; + } + + default: { + + NT_ASSERT(FALSE); + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpPersistentReserveIn; + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): Srb %p. Service Action %u.\n", + DsmIds, + Srb, + serviceAction)); + + // + // Allocate a context for the completion routine. + // + completionContext = ExAllocateFromNPagedLookasideList(&DsmContext->CompletionContextList); + if (!completionContext) { + + status = STATUS_INSUFFICIENT_RESOURCES; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u - Failed to allocate completion context.\n", + DsmIds, + serviceAction)); + + goto __Exit_DsmpPersistentReserveIn; + } + + KeInitializeEvent(&event, NotificationEvent, FALSE); + + // + // Indicate the target for this request. + // + completionContext->DsmContext = DsmContext; + completionContext->RequestUnique1 = (PVOID)&event; + completionContext->RequestUnique2 = cdb->PERSISTENT_RESERVE_IN.OperationCode; + + count = group->NumberDevices; + + for (i = count - 1; i >= 0; i--) { + + // + // A PR command may fail with a "retry-able" UA when reservation is + // released or preempted (on every I_T_L nexus except the one on which + // it was released/preempted). In such a case we should retry the PR + // command on the same path. + // + KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); + finalTickCount = currentTickCount + (DSM_SECONDS_TO_TICKS(group->MaxPRRetryTimeDuringStateTransition) / tickLength); + + if (!retryOnAnother) { + + // + // If the request doesn't need to be retried (down another path) on + // failure, better choose the path that has maximum chances of + // success. + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmIds->IdList[0]), + SpecialHandlingFlag); + + if (!deviceInfo) { + + status = STATUS_UNSUCCESSFUL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u - No active/alternative path for device %p.\n", + DsmIds, + serviceAction, + group)); + + break; + } + + } else { + + deviceInfo = group->DeviceList[i]; + + if (DsmpIsDeviceFailedState(deviceInfo->State) || !DsmpIsDeviceInitialized(deviceInfo)) { + + // + // Ignore "bad" paths for now. + // + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): Ignoring bad instance - state %x, init %x.\n", + DsmIds, + deviceInfo->State, + deviceInfo->Initialized)); + + deviceInfo = NULL; + } + } + + if (!deviceInfo) { + + // + // Maybe a remove came through and caused a collapse of the device + // list, thus making this entry empty. + // + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u - Couldn't find path for device %p.\n", + DsmIds, + serviceAction, + group)); + + continue; + } + +__DsmpPersistentReserveIn_RetryRequest: + + IoMarkIrpPending(Irp); + + completionContext->DeviceInfo = deviceInfo; + + // + // Set-up a completion routine. + // + IoSetCompletionRoutine(Irp, + DsmpPersistentReserveCompletion, + completionContext, + TRUE, + TRUE, + TRUE); + + // + // Always send the original request down a new path + // + irpStack = IoGetNextIrpStackLocation(Irp); + srbCopySucceeded = SrbCopySrb(Srb, SrbGetSrbLength(Srb), srbCopy); + NT_ASSERT(srbCopySucceeded == TRUE); + irpStack->Parameters.Scsi.Srb = Srb; + + // + // Clear the sense buffer if it exists + // + senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); + senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); + if (senseInfoBuffer) { + RtlZeroMemory(senseInfoBuffer, senseInfoBufferLength); + } + + servicingDeviceInfo = deviceInfo; + + // + // Issue the request and wait. + // + status = DsmSendRequest(DsmContext->MPIOContext, + deviceInfo->TargetObject, + Irp, + deviceInfo); + + if (status == STATUS_PENDING) { + + KeWaitForSingleObject(&event, + Executive, + KernelMode, + FALSE, + NULL); + + status = Irp->IoStatus.Status; + } + + if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u sent down successfully on %p.\n", + DsmIds, + serviceAction, + deviceInfo->FailGroup->PathId)); +#if DBG + if (serviceAction == RESERVATION_ACTION_READ_KEYS) { + + PPRI_REGISTRATION_LIST prInRegistrationList = Irp->AssociatedIrp.SystemBuffer; + ULONG numberOfKeys; + ULONG keyIndex; + ULONGLONG prKey; + + REVERSE_BYTES(&numberOfKeys, &prInRegistrationList->AdditionalLength); + numberOfKeys /= 8; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): %u registrations keys present:\n", + DsmIds, + numberOfKeys)); + + for (keyIndex = 0; keyIndex < numberOfKeys; keyIndex++) { + + REVERSE_BYTES_QUAD(&prKey, &(prInRegistrationList->ReservationKeyList[keyIndex])); + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): Registration Key %u: %I64x\n", + DsmIds, + keyIndex, + prKey)); + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "\n")); + + } else if (serviceAction == RESERVATION_ACTION_READ_RESERVATIONS) { + + PPRI_RESERVATION_LIST prInReservationList = Irp->AssociatedIrp.SystemBuffer; + ULONG numberOfDescriptors; + PPRI_RESERVATION_DESCRIPTOR prInReservationDescriptor = prInReservationList->Reservations; + ULONGLONG prKey = 0; + + REVERSE_BYTES(&numberOfDescriptors, &prInReservationList->AdditionalLength); + numberOfDescriptors /= sizeof(PRI_RESERVATION_DESCRIPTOR); + NT_ASSERT(numberOfDescriptors <= 1); + + if (numberOfDescriptors == 1) { + REVERSE_BYTES_QUAD(&prKey, &prInReservationDescriptor->ReservationKey); + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): %u Reservation Key: %I64x\n", + DsmIds, + numberOfDescriptors, + prKey)); + } +#endif + // + // Done. + // + break; + + } else { + + // + // Check to see if the request failed because of a "transient error", + // like reservations released for example. If so, this is NOT an actual + // error and the request must be retried. Multiple retries may be required + // if for example the UA indicates that the TPGs are in transitioning state. + // + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && + Srb->SrbStatus & SRB_STATUS_ERROR && + SrbGetScsiStatus(Srb) == SCSISTAT_CHECK_CONDITION) { + + KeQueryTickCount((PLARGE_INTEGER)¤tTickCount); + + senseInfoBuffer = SrbGetSenseInfoBuffer(Srb); + senseInfoBufferLength = SrbGetSenseInfoBufferLength(Srb); + + if (group->PRKeyValid && + DsmpShouldRetryPersistentReserveCommand(senseInfoBuffer, senseInfoBufferLength) && + currentTickCount < finalTickCount) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN %u returned UA with error %x. Retrying same path %p.\n", + DsmIds, + serviceAction, + status, + deviceInfo->FailGroup->PathId)); + + KeResetEvent(&event); + Irp->IoStatus.Status = 0; + + goto __DsmpPersistentReserveIn_RetryRequest; + } + } + + // + // If a retry (along a different path) on failure is not required, + // we're done - just return this failure. + // + if (!retryOnAnother) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u down %p failed with %x. Breaking out.\n", + DsmIds, + serviceAction, + deviceInfo->FailGroup->PathId, + status)); + + break; + } + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u down %p failed with %x. Sending down another path.\n", + DsmIds, + serviceAction, + deviceInfo->FailGroup->PathId, + status)); + + // + // If we are here, it is because the request failed down the chosen path + // and needs to be retried down a new path. + // + KeResetEvent(&event); + Irp->IoStatus.Status = 0; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): PR_IN for %u completed with status %x.\n", + DsmIds, + serviceAction, + status)); + + ExFreeToNPagedLookasideList(&DsmContext->CompletionContextList, completionContext); + +__Exit_DsmpPersistentReserveIn: + + if (srbCopy != NULL) { + DsmpFreePool(srbCopy); + } + + currentIrpStack->Parameters.Others.Argument3 = servicingDeviceInfo; + Irp->IoStatus.Status = status; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveIn (DsmIds %p): Exiting function returning IRP status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpPersistentReserveCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +/*++ + +Routine Description: + + General-purpose completion routine for PR in and out commands sent synchronously. + +Arguments: + + DeviceObject - Target of the request. + Irp - Command being sent. + Context - The event on which the caller is waiting. + +Return Value: + + NTSTATUS + +--*/ + +{ + PDSM_COMPLETION_CONTEXT context = Context; + PKEVENT event; + + // It is required to specify a DSM completion context + // when setting DsmpPersistentReserveCompletion as completion routine. + _Analysis_assume_(context != NULL); + + event = (PKEVENT)(context->RequestUnique1); + + UNREFERENCED_PARAMETER(DeviceObject); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpPersistentReserveCompletion: DevInfo %p, IRP %p, Context %p\n", + context->DeviceInfo, + Irp, + Context)); + + if (Irp->PendingReturned) { + + IoMarkIrpPending(Irp); + } + + KeSetEvent(event, 0, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + diff --git a/tests/projects/windows/driver/wdm/msdsm/dsmtrace.mof b/tests/projects/windows/driver/wdm/msdsm/dsmtrace.mof new file mode 100644 index 000000000..d9e8cf4cc --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/dsmtrace.mof @@ -0,0 +1,111 @@ +#pragma classflags("forceupdate") +#pragma namespace("\\\\.\\root\\WMI") +// +// Copyright (C) 2004 Microsoft Corporation +// +// WPP Generated File +// + +//ModuleName = wppCtlGuid (Init called in Function DriverEntry) +[Dynamic, + Description("MSDSM Driver Tracing Provider"), + guid("{DEDADFF5-F99F-4600-B8C9-2D4D9B806B5B}"), + locale("MS\\0x409")] +class MSDSMGuid : EventTrace +{ + [Description ("Enable Flags"), + ValueDescriptions{ + "TRACE_FLAG_GENERAL Flag", + "TRACE_FLAG_PNP Flag", + "TRACE_FLAG_POWER Flag", + "TRACE_FLAG_RW Flag", + "TRACE_FLAG_IOCTL Flag", + "TRACE_FLAG_QUEUE Flag", + "TRACE_FLAG_WMI Flag", + "TRACE_FLAG_TIMER Flag", + "TRACE_FLAG_INIT Flag", + "TRACE_FLAG_LOCK Flag", + "TRACE_FLAG_DEBUG1 Flag", + "TRACE_FLAG_DEBUG2 Flag", + "TRACE_FLAG_MCN Flag", + "TRACE_FLAG_ISR Flag", + "TRACE_FLAG_ENUM Flag"}, + DefineValues{ + "TRACE_FLAG_GENERAL", + "TRACE_FLAG_PNP", + "TRACE_FLAG_POWER", + "TRACE_FLAG_RW", + "TRACE_FLAG_IOCTL", + "TRACE_FLAG_QUEUE", + "TRACE_FLAG_WMI", + "TRACE_FLAG_TIMER", + "TRACE_FLAG_INIT", + "TRACE_FLAG_LOCK", + "TRACE_FLAG_DEBUG1", + "TRACE_FLAG_DEBUG2", + "TRACE_FLAG_MCN", + "TRACE_FLAG_ISR", + "TRACE_FLAG_ENUM"}, + Values{ + "TRACE_FLAG_GENERAL", + "TRACE_FLAG_PNP", + "TRACE_FLAG_POWER", + "TRACE_FLAG_RW", + "TRACE_FLAG_IOCTL", + "TRACE_FLAG_QUEUE", + "TRACE_FLAG_WMI", + "TRACE_FLAG_TIMER", + "TRACE_FLAG_INIT", + "TRACE_FLAG_LOCK", + "TRACE_FLAG_DEBUG1", + "TRACE_FLAG_DEBUG2", + "TRACE_FLAG_MCN", + "TRACE_FLAG_ISR", + "TRACE_FLAG_ENUM"}, + ValueMap{ + "0x00000001", + "0x00000002", + "0x00000004", + "0x00000008", + "0x00000010", + "0x00000020", + "0x00000040", + "0x00000080", + "0x00000100", + "0x00000200", + "0x00000400", + "0x00000800", + "0x00001000", + "0x00002000", + "0x00004000"} + ] + uint32 Flags; + [Description ("Levels"), + ValueDescriptions{ + "Abnormal exit or termination", + "Severe errors that need logging", + "Warnings such as allocation failure", + "Includes non-error cases", + "Detailed traces from intermediate steps" }, + DefineValues{ + "TRACE_LEVEL_FATAL", + "TRACE_LEVEL_ERROR", + "TRACE_LEVEL_WARNING" + "TRACE_LEVEL_INFORMATION", + "TRACE_LEVEL_VERBOSE" }, + Values{ + "Fatal", + "Error", + "Warning", + "Information", + "Verbose" }, + ValueMap{ + "0x1", + "0x2", + "0x3", + "0x4", + "0x5" }, + ValueType("index") + ] + uint32 Level; +}; diff --git a/tests/projects/windows/driver/wdm/msdsm/intrface.c b/tests/projects/windows/driver/wdm/msdsm/intrface.c new file mode 100644 index 000000000..eeebf7f93 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/intrface.c @@ -0,0 +1,5198 @@ +/*++ + +Copyright (C) 2004-2010 Microsoft Corporation + +Module Name: + + intrface.c + +Abstract: + + This driver is the Microsoft Device Specific Module (DSM) + devices that conform with SPC-3 specs. + It exports behaviors that mpio.sys will use to determine how to + multipath these devices. + + This file contains DriverEntry and all the functions that are + exported to MPIO. + + This DSM is targetted towards Windows 2008 and above. + +Environment: + + kernel mode only + +--*/ + +#include "precomp.h" + +#ifdef DEBUG_USE_WPP +#include "intrface.tmh" +#endif + +#pragma warning (disable:4305) + + +// +// Flag to indicate whether to NT_ASSERT or ignore a particular condition. +// +BOOLEAN DoAssert = TRUE; + +// +// OS Version Info +// MSDSM is targetted towards Windows Server 2008 and above. +// +BOOLEAN gServer2008AndAbove = FALSE; + +// +// Global to cache MPIO's Control Object. +// +PDEVICE_OBJECT gMPIOControlObject = NULL; + +// +// Flag to indicate if the MPIO control object was referenced. +// +BOOLEAN gMPIOControlObjectRefd = FALSE; + +// +// Global to cache the Driver Object. +// +PDRIVER_OBJECT gDsmDriverObject = NULL; + + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(INIT, DriverEntry) +#endif + +// +// The code. +// +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + This routine is called when the driver is loaded. + +Arguments: + + DriverObject - Supplies the driver object. + RegistryPath - Supplies the registry path. + +Return Value: + + NTSTATUS + +--*/ +{ + PDSM_CONTEXT dsmContext = NULL; + PFILE_OBJECT fileObject; + WCHAR dosDeviceName[64] = DSM_MPIO_CONTROL_OBJECT_SYMLINK; + UNICODE_STRING mpUnicodeName; + NTSTATUS status = STATUS_SUCCESS; + MPIO_VERSION_INFO versionInfo = {0}; + DSM_TYPE dsmMode = DsmType3; + DSM_MPIO_CONTEXT mpctlContext; + IO_STATUS_BLOCK ioStatus; + + + // + // Initialize the tracing subsystem. + // Any failure is handled by ETW itself. + // + WPP_INIT_TRACING(DriverObject, RegistryPath); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Entering function.\n", + DriverObject)); + + gDsmDriverObject = DriverObject; + + // + // Determine the OS version. + // + gServer2008AndAbove = RtlIsNtDdiVersionAvailable(NTDDI_VISTA); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Server2008AndAbove is %!bool!.\n", + DriverObject, + gServer2008AndAbove)); + + // + // MSDSM is supported only on Server 2008 and above. + // + if (!gServer2008AndAbove) { + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DriverEntry; + } + + // + // Build the mpio symbolic link name. + // + RtlInitUnicodeString(&mpUnicodeName, dosDeviceName); + + // + // Get a pointer to mpio's deviceObject. + // + status = IoGetDeviceObjectPointer(&mpUnicodeName, + FILE_READ_ATTRIBUTES, + &fileObject, + &gMPIOControlObject); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_FATAL, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Failed to communicate with MPIO control object. Status %x.\n", + DriverObject, + status)); + + goto __Exit_DriverEntry; + } + + ObReferenceObject(gMPIOControlObject); + gMPIOControlObjectRefd = TRUE; + ObDereferenceObject(fileObject); + + status = DsmGetVersion(&versionInfo, sizeof(MPIO_VERSION_INFO)); + + if (!NT_SUCCESS(status)) { + + // + // If we can't get the version, that means we aren't using a compatible + // version of MPIO drivers and so should not continue. + // + TracePrint((TRACE_LEVEL_FATAL, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): MPIO version unknown - DSM exiting.\n", + DriverObject)); + + status = STATUS_UNSUCCESSFUL; + goto __Exit_DriverEntry; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): MPIO version %d.%d.%d.%d.\n", + DriverObject, + versionInfo.MajorVersion, + versionInfo.MinorVersion, + versionInfo.ProductBuild, + versionInfo.QfeNumber)); + + RtlZeroMemory(&gDsmInitData, sizeof(DSM_INIT_DATA)); + + // + // Must be newer than 1.0.7.0 to support DSM type 2 upwards. + // + if ((versionInfo.MajorVersion > 1) || + (versionInfo.MinorVersion >= 1) || + (versionInfo.ProductBuild > 7) || + (versionInfo.QfeNumber >= 1)) { + + // + // Must be newer than 1.18 to support DSM's versioning + // + if (versionInfo.MajorVersion > 1 || + versionInfo.MinorVersion > 17) { + + dsmMode = DsmType6; + + { + RTL_OSVERSIONINFOW osVersion = {0}; + + osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + RtlGetVersion(&osVersion); + + gDsmInitData.DsmVersion.MajorVersion = osVersion.dwMajorVersion; + gDsmInitData.DsmVersion.MinorVersion = osVersion.dwMinorVersion; + gDsmInitData.DsmVersion.ProductBuild = osVersion.dwBuildNumber; + gDsmInitData.DsmVersion.QfeNumber = 0; + } + } + } else { + + // + // We cannot use this DSM with older versions of the MPIO drivers. + // + TracePrint((TRACE_LEVEL_FATAL, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): MPIO version not supported - DSM exiting.\n", + DriverObject)); + + status = STATUS_UNSUCCESSFUL; + goto __Exit_DriverEntry; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Setting DSM type to %d.\n", + DriverObject, + dsmMode)); + + // + // Build the init data structure. + // + dsmContext = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_CONTEXT), + DSM_TAG_DSM_CONTEXT); + if (!dsmContext) { + + TracePrint((TRACE_LEVEL_FATAL, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Failed to allocate memory for DSM Context.\n", + DriverObject)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DriverEntry; + } + + // + // Set-up the init data + // + gDsmInitData.DsmContext = (PVOID) dsmContext; + gDsmInitData.InitDataSize = sizeof(DSM_INIT_DATA); + + gDsmInitData.DsmInquireDriver = DsmInquire; + gDsmInitData.DsmCompareDevices = DsmCompareDevices; + gDsmInitData.DsmGetControllerInfo = DsmGetControllerInfo; + gDsmInitData.DsmSetDeviceInfo = DsmSetDeviceInfo; + gDsmInitData.DsmIsPathActive = DsmIsPathActive; + gDsmInitData.DsmPathVerify = DsmPathVerify; + gDsmInitData.DsmInvalidatePath = DsmInvalidatePath; + gDsmInitData.DsmMoveDevice = DsmMoveDevice; + gDsmInitData.DsmRemovePending = DsmRemovePending; + gDsmInitData.DsmRemoveDevice = DsmRemoveDevice; + gDsmInitData.DsmRemovePath = DsmRemovePath; + gDsmInitData.DsmSrbDeviceControl = DsmSrbDeviceControl; + gDsmInitData.DsmLBGetPath = DsmLBGetPath; + gDsmInitData.DsmInterpretErrorEx = DsmInterpretError; + gDsmInitData.DsmUnload = DsmUnload; + gDsmInitData.DsmSetCompletion = DsmSetCompletion; + gDsmInitData.DsmCategorizeRequest = DsmCategorizeRequest; + gDsmInitData.DsmBroadcastSrb = DsmBroadcastRequest; + gDsmInitData.DsmIsAddressTypeSupported = DsmIsAddressTypeSupported; + gDsmInitData.DsmDeviceNotUsed = DsmDeviceNotUsed; + + // + // Since MSDSM is for SPC-3 compliant devices, MPIO should be able to build + // a serial number for the device. + // + gDsmInitData.DsmDeviceSerialNumber = NULL; + + // + // Notifies MPIO of the appropriate Type support + // + gDsmInitData.DsmType = dsmMode; + + gDsmInitData.DriverObject = DriverObject; + + + // + // Set-up the WMI Info. + // + DsmpWmiInitialize(&gDsmInitData.DsmWmiInfo, RegistryPath); + DsmpDsmWmiInitialize(&gDsmInitData.DsmWmiGlobalInfo, RegistryPath); + + RtlInitUnicodeString(&gDsmInitData.DisplayName, DSM_FRIENDLY_NAME); + + // + // Initialize some of the fields in DSM Context structure. + // + KeInitializeSpinLock(&dsmContext->SupportedDevicesListLock); + InitializeListHead(&dsmContext->GroupList); + InitializeListHead(&dsmContext->DeviceList); + InitializeListHead(&dsmContext->FailGroupList); + InitializeListHead(&dsmContext->ControllerList); + InitializeListHead(&dsmContext->StaleFailGroupList); + + // + // Build the list context structures used for completion processing. + // + ExInitializeNPagedLookasideList(&dsmContext->CompletionContextList, + NULL, + NULL, + POOL_NX_ALLOCATION, + sizeof(DSM_COMPLETION_CONTEXT), + DSM_TAG_GENERIC, + 0); + + RtlZeroMemory(&mpctlContext, sizeof(DSM_MPIO_CONTEXT)); + + // + // Send the IOCTL to mpio.sys to register ourselves. + // + DsmSendDeviceIoControlSynchronous(IOCTL_MPDSM_REGISTER, + gMPIOControlObject, + &gDsmInitData, + &mpctlContext, + sizeof(DSM_INIT_DATA), + sizeof(DSM_MPIO_CONTEXT), + TRUE, + &ioStatus); + + status = ioStatus.Status; + + if (NT_SUCCESS(status)) { + + dsmContext->MPIOContext = mpctlContext.MPIOContext; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Registered with MPIO.\n", + DriverObject)); + + DriverObject->DriverUnload = DsmDriverUnload; + + // + // Query the registry for disabling/enabling statistics gathering + // + if (STATUS_OBJECT_NAME_NOT_FOUND == DsmpGetStatsGatheringChoice(dsmContext, (PULONG)&dsmContext->DisableStatsGathering)) { + + // + // If the value does not exist, write the default to registry. + // + DsmpSetStatsGatheringChoice(dsmContext, (ULONG)dsmContext->DisableStatsGathering); + } + } + +__Exit_DriverEntry: + + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Exiting function successfully.\n", + DriverObject)); + } else { + + // + // Since the DSM is going to be unloaded but without DriverUnload being + // called, we need to perform cleanup here. + // + if (dsmContext != NULL) { + DsmpFreeDSMResources(dsmContext); + dsmContext = NULL; + } + + if (gMPIOControlObjectRefd) { + + // + // Drop the reference on MPIO's control object. + // + ObDereferenceObject(gMPIOControlObject); + gMPIOControlObjectRefd = FALSE; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DriverEntry (DrvObj %p): Exiting function with status %x.\n", + DriverObject, + status)); + + // + // Stop the tracing subsystem. + // NOTE: once we unregister ETW, no more TracePrint can be done, so we + // must ensure that ETW unregister is the last thing that happens. + // + WPP_CLEANUP(gDsmDriverObject); + } + + return status; +} + + +VOID +DsmDriverUnload( + _In_ IN PDRIVER_OBJECT DriverObject + ) +/*++ + +Routine Description: + + This routine is called when the driver is unloaded. + +Arguments: + + DriverObject - Supplies the driver object. + +Return Value: + + Nothing + +--*/ +{ + DSM_DEREGISTER_DATA deregisterData; + IO_STATUS_BLOCK ioStatus; + + deregisterData.DeregisterDataSize = sizeof(DSM_DEREGISTER_DATA); + deregisterData.DriverObject = DriverObject; + deregisterData.DsmContext = gDsmInitData.DsmContext; + deregisterData.MpioContext = ((PDSM_CONTEXT)(gDsmInitData.DsmContext))->MPIOContext; + // + // Send the IOCTL to mpio.sys to de-register ourselves. + // + DsmSendDeviceIoControlSynchronous(IOCTL_MPDSM_DEREGISTER, + gMPIOControlObject, + &deregisterData, + NULL, + sizeof(DSM_DEREGISTER_DATA), + 0, + TRUE, + &ioStatus); + + NT_ASSERT(NT_SUCCESS(ioStatus.Status)); + + + + return; +} + + +NTSTATUS +DsmInquire( + _In_ IN PVOID DsmContext, + _In_ IN PDEVICE_OBJECT TargetDevice, + _In_ IN PDEVICE_OBJECT PortObject, + _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, + _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList, + _Out_ OUT PVOID *DsmIdentifier + ) +/*++ + +Routine Description: + + This routine is used to determine if TargetDevice belongs to + the DSM. If this is a supported device DsmIdentifier will be + updated with 'deviceInfo'. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + TargetDevice - DeviceObject for the child device. + PortObject - The Port driver FDO on which TargetDevice resides. + Descriptor - Pointer to the device descriptor corresponding to TargetDevice. + Rehash of inquiry data, plus serial number information + (if applicable). + DeviceIdList - VPD Page 0x83 information. + DsmIdentifier - Pointer to be filled in by the DSM on success. + +Return Value: + + STATUS_NOT_SUPPORTED - if not on the SupportList. + STATUS_INSUFFICIENT_RESOURCES - No mem. + STATUS_SUCCESS +--*/ +{ + PDSM_CONTEXT dsmContext = DsmContext; + PDSM_DEVICE_INFO deviceInfo = NULL; + PDSM_GROUP_ENTRY group; + BOOLEAN newGroup; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroupEntry = NULL; + PDSM_TARGET_PORT_LIST_ENTRY targetPortEntry = NULL; + PSTR serialNumber = NULL; + SIZE_T serialNumberLength = 0; + NTSTATUS status; + ULONG allocationLength; + BOOLEAN serialNumberAllocated = FALSE; + KIRQL irql = PASSIVE_LEVEL; // Initialize variable to prevent C4701 error + BOOLEAN supported = FALSE; + BOOLEAN spinlockHeld = FALSE; + UCHAR vendorId[9] = {0}; + UCHAR productId[17] = {0}; + INQUIRYDATA inquiryData; + UCHAR alua = DSM_DEVINFO_ALUA_NOT_SUPPORTED; + ULONG index; + PDSM_IDS controllerObjects = NULL; + PDEVICE_OBJECT controllerDeviceObject; + PLIST_ENTRY entry = NULL; + PSTORAGE_DESCRIPTOR_HEADER controllerIdHeader = NULL; + PULONG relativeTargetPortId = NULL; + PUSHORT targetPortGroupId = NULL; + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength = 0; + PSTR controllerSerialNumber; + BOOLEAN match = FALSE; + BOOLEAN doneUpdating = FALSE; + PDSM_CONTROLLER_LIST_ENTRY controllerEntry = NULL; + PDSM_TARGET_PORT_DEVICELIST_ENTRY tp_device = NULL; + PWSTR hardwareId = NULL; + PWCHAR deviceName = NULL; + ULONG tempResult = 0; + ULONG maxPRRetryTimeDuringStateTransition = DSM_MAX_PR_UNIT_ATTENTION_RETRY_TIME; + BOOLEAN useCacheForLeastBlocks = FALSE; + ULONGLONG cacheSizeForLeastBlocks = 0; + BOOLEAN fakeControllerEntryExists = FALSE; + STORAGE_IDENTIFIER_CODE_SET serialNumberCodeSet = StorageIdCodeSetReserved; + +#if DBG + BOOLEAN multiport; +#endif + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Entering function.\n", + TargetDevice)); + + // + // 1. Get standard inquiry for the device. Check if SPC-3 compliant. + // If not compliant, check SupportedDeviceList. + // 2. Create device serial number. + // 3. Create a partially populated deviceInfo. + // DeviceDescriptor. + // SCSI address. + // Save off serial number. + // ALUA, port FDO, etc. + // 4. Create device name. + // 5. If ALUA support, send down Report Target Port Groups. + // 6. Find the group. If none, build one. + // 7. If new group, build target port groups and target ports info. + // Else, update target port groups and target ports info. + // 8. If both implicit as well as explicit transitions allowed, disable implicit. + // 9. Get list of controllers objects and get VPD 0x83 for each (only if no + // match for existing ones). + // Match returned ids of type 0x5 with what was returned in Report Target Port Groups. + // If no type 0x5 identifier, use SCSI address. + // Create controller list (delete stale entries). + // + + + // + // Query the registry to find out what devices are being supported + // on this machine. + // + DsmpGetDeviceList(dsmContext); + + status = DsmpGetStandardInquiryData(TargetDevice, &inquiryData); + + if (NT_SUCCESS(status)) { + + supported = DsmpCheckScsiCompliance(TargetDevice, + &inquiryData, + Descriptor, + DeviceIdList); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to get inquiry data with status %x.\n", + TargetDevice, + status)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // Since the device isn't SPC-3 compliant, check if the device is on the + // SupportedDeviceList. + // + if (!supported) { + + + if (!supported) { + + // + // Get the inquiry data embedded in the device descriptor. + // + RtlStringCchCopyA((LPSTR)vendorId, + sizeof(vendorId) / sizeof(vendorId[0]), + (LPCSTR)(&inquiryData.VendorId)); + + RtlStringCchCopyA((LPSTR)productId, + sizeof(productId) / sizeof(productId[0]), + (LPCSTR)(&inquiryData.ProductId)); + + supported = DsmpDeviceSupported(dsmContext, + (PCSZ)vendorId, + (PCSZ)productId); + } + + if (!supported) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Unsupported Device.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + } + + // + // Find out if device can be accessed via mulitple ports. This info is + // important since it will determine whether or not to send down a + // ReportTargetPortGroups command. + // +#if DBG + multiport = (inquiryData.MultiPort & 0x10) ? TRUE : FALSE; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Is %ws multiported.\n", + TargetDevice, + multiport ? L"" : L"not")); +#endif + + // + // Query the assymmetric states transition method + // + switch ((inquiryData.Reserved >> 0x4) & 0x3) { + case 1: alua = DSM_DEVINFO_ALUA_IMPLICIT; + break; + + case 2: alua = DSM_DEVINFO_ALUA_EXPLICIT; + break; + + case 3: alua = DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT; + break; + + default: alua = DSM_DEVINFO_ALUA_NOT_SUPPORTED; + break; + } + + // + // Get some information about this device. The preferred info is + // from the Device ID Page. + // + if (DeviceIdList) { + + // + // This will parse out the 'best' identifier and return + // a NULL-terminated ascii string. + // + serialNumber = (PSTR)DsmpParseDeviceID(DeviceIdList, + DSM_DEVID_SERIAL_NUMBER, + NULL, + &serialNumberCodeSet, + FALSE); + + if (!serialNumber) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): NULL serial number.\n", + TargetDevice)); + + // + // Either an allocation failed, or the DeviceIdList is malformed. + // + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // Indicate that the serialnumber buffer is allocated. + // + serialNumberAllocated = TRUE; + serialNumberLength = strlen((const char*)serialNumber); + + } else { + + // + // Get the serial number of this device. Use the serial number + // page (0x80). Ensure that the device's serial number is + // present. If not, can't claim support for this drive. + // + + if (!Descriptor || + (Descriptor->SerialNumberOffset == MAXULONG) || + (Descriptor->SerialNumberOffset == 0)) { + + // + // The port driver currently doesn't get the VPD page 0x80, + // if the device doesn't support GET_SUPPORTED_PAGES. Check to + // see whether there actually is a serial number. + // + serialNumber = DsmpGetSerialNumber(TargetDevice); + + if (!serialNumber) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): serialNumber = NULL.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + + } else { + serialNumberAllocated = TRUE; + serialNumberLength = strlen((const char*)serialNumber); + } + } + } + + // + // Allocate for the device. This is also used as DsmId. + // + allocationLength = sizeof(DSM_DEVICE_INFO); + + // + // As DSM_DEVICE_INFO has storage for the descriptor, add only + // the additional stuff that's at the end. + // + if (Descriptor) { + status = RtlULongSub(Descriptor->Size, sizeof(STORAGE_DEVICE_DESCRIPTOR), &tempResult); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Arithmetic underflow - status %x.\n", + TargetDevice, + status)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + } + + status = RtlULongAdd(allocationLength, tempResult, &allocationLength); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Arithmetic overflow - status %x.\n", + TargetDevice, + status)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + deviceInfo = DsmpAllocatePool(NonPagedPoolNx, + allocationLength, + DSM_TAG_DEV_INFO); + if (!deviceInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to allocate Device Info.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + deviceInfo->State = deviceInfo->PreviousState = deviceInfo->TempPreviousStateForLB = deviceInfo->ALUAState = deviceInfo->LastKnownGoodState = DSM_DEV_NOT_USED_STATE; + deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; + // + // Copy over the StorageDescriptor. + // + if (Descriptor) { + RtlCopyMemory(&deviceInfo->Descriptor, + Descriptor, + Descriptor->Size); + } + + // + // Get the scsi address for this device. Note that on success, DsmGetScsiAddress() + // will allocate memory which we are responsible for freeing. + // + status = DsmGetScsiAddress(TargetDevice, + &deviceInfo->ScsiAddress); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Error %x while getting scsi address.\n", + TargetDevice, + status)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // Capture the serial number allocated flag. + // + deviceInfo->SerialNumberAllocated = serialNumberAllocated; + + // + // Set the serial number. + // + if (!serialNumberAllocated) { + + PSTORAGE_DEVICE_DESCRIPTOR descriptor; + + // + // serialNumber is not pointing to the buffer passed by MPIO. Update + // it to point to the Device Descriptor allocated by the DSM. + // + descriptor = &(deviceInfo->Descriptor); + + NT_ASSERT(descriptor->SerialNumberOffset != 0 && descriptor->SerialNumberOffset != MAXULONG); + + serialNumber = (PCHAR)descriptor + descriptor->SerialNumberOffset; + serialNumberLength = strlen((const char*)serialNumber); + } + + if (alua == (DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT)) { + + BOOLEAN disableImplicit = FALSE; + + status = DsmpDisableImplicitStateTransition(TargetDevice, &disableImplicit); + + if (NT_SUCCESS(status)) { + + if (disableImplicit) { + + alua &= ~DSM_DEVINFO_ALUA_IMPLICIT; + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Disabled implicit ALUA state transition.\n", + TargetDevice)); + + // + // Record that the storage actually supported implicit also, but we + // turned it OFF. + // + deviceInfo->ImplicitDisabled = TRUE; + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Storage support both transitions but does NOT allow disabling Implicit.\n", + TargetDevice)); + } + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to disable implicit ALUA state transitions - status %x.\n", + TargetDevice, + status)); + } + } + + deviceInfo->SerialNumber = serialNumber; + + // + // Save the Physical Device Object (PDO) of the device. + // Used to verify that no two devices have the same PDO. + // + deviceInfo->PortPdo = TargetDevice; + + // + // Save the FDO of the adapter. Used for handling reserve\release + // + deviceInfo->PortFdo = PortObject; + + // + // Set the signature. + // + deviceInfo->DeviceSig = DSM_DEVICE_SIG; + + deviceInfo->DsmContext = DsmContext; + + deviceInfo->ALUASupport = alua; + + // + // Build the name (using serialnumber) that will be used as registry key + // to store Load Balance settings for this device. + // + deviceName = DsmpBuildDeviceName(deviceInfo, serialNumber, serialNumberLength); + + if (!deviceName) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to allocate device name for %p.\n", + TargetDevice, + deviceInfo)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + + // + // Send down ReportTargetPortGroups command and keep the info handy. + // + if (alua != DSM_DEVINFO_ALUA_NOT_SUPPORTED) { + + status = DsmpReportTargetPortGroups(TargetDevice, + &targetPortGroupsInfo, + &targetPortGroupsInfoLength); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to report target port groups for %p. Status %x.\n", + TargetDevice, + deviceInfo, + status)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // We've just sent down an RTPG (relatively expensive operation), and it + // succeeded, so sending down one more as part part of the initialization + // in PathVerify() since it is going to be called almost immediately. + // + deviceInfo->IgnorePathVerify = TRUE; + } + + // + // Query the registry for max time to retry failed PR requests + // + DsmpGetMaxPRRetryTime(DsmContext, &maxPRRetryTimeDuringStateTransition); + + // + // Query the registry to see if the user has overridden the default + // Least Blocks settings. + // + status = DsmpQueryCacheInformationFromRegistry(DsmContext, + &useCacheForLeastBlocks, + &cacheSizeForLeastBlocks); + + if (!NT_SUCCESS(status)) { + // + // Couldn't get the settings from the registry so fall back on the + // default for Least Blocks. + // + useCacheForLeastBlocks = TRUE; + cacheSizeForLeastBlocks = DSM_LEAST_BLOCKS_DEFAULT_THRESHOLD; + } + + // + // Build LUN's hardware id. Needs to be called at PASSIVE_LEVEL, so + // do it before grabbing the lock. The hardware id of the group is + // later set under the protection of the lock. + // + hardwareId = DsmpBuildHardwareId(deviceInfo); + + irql = ExAcquireSpinLockExclusive(&(((PDSM_CONTEXT)DsmContext)->DsmContextLock)); + spinlockHeld = TRUE; + + status = STATUS_SUCCESS; + + // + // See if there is an existing Multi-path group to which this belongs. + // (same serial number). + // + group = DsmpFindDevice(DsmContext, deviceInfo, FALSE); + if (!group) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): First device %p in the group.\n", + TargetDevice, + deviceInfo)); + + newGroup = TRUE; + + // + // This device doesn't belong to any group yet. So Build a multi-path + // group entry. This'll represents all paths to a particular device. + // + group = DsmpBuildGroupEntry(DsmContext, deviceInfo); + if (group) { + + // + // Set the registry key name for the new group + // + group->RegistryKeyName = deviceName; + deviceName = NULL; + + // + // Cache the LUN's hardware id + // + if (!hardwareId) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to build a hardwareId for %p.\n", + TargetDevice, + deviceInfo)); + } + + group->HardwareId = hardwareId; + hardwareId = NULL; + + group->UseCacheForLeastBlocks = useCacheForLeastBlocks; + group->CacheSizeForLeastBlocks = cacheSizeForLeastBlocks; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to allocate Group Entry for %p.\n", + TargetDevice, + deviceInfo)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + } else { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Found group %p for device %p.\n", + TargetDevice, + group, + deviceInfo)); + + newGroup = FALSE; + + if (!group->HardwareId) { + + // + // If we weren't successful in previously building the hardware id for this LUN, + // retry doing it again now. + // + hardwareId = DsmpBuildHardwareId(deviceInfo); + if (!hardwareId) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to build a hardwareId for %p.\n", + TargetDevice, + deviceInfo)); + } + + group->HardwareId = hardwareId; + hardwareId = NULL; + } + + // + // Sanity check that we haven't been presented with device instances + // with different ALUA support. So compare with the first device instance. + // + for (index = 0; index < DSM_MAX_PATHS; index++) { + + if (group->DeviceList[index]) { + + break; + } + } + + if (index < DSM_MAX_PATHS) { + + // + // Only acceptable conditions are: + // 1. both have same support, + // 2. one has explicit, while other has both explicit-and-implicit (this + // is a potential valid case because DsmpDisableImplicitStateTransition + // may have failed). + // + if (!((deviceInfo->ALUASupport == group->DeviceList[index]->ALUASupport) || + ((deviceInfo->ALUASupport == DSM_DEVINFO_ALUA_EXPLICIT && deviceInfo->ImplicitDisabled) && + (group->DeviceList[index]->ALUASupport == (DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT))) || + ((group->DeviceList[index]->ALUASupport == DSM_DEVINFO_ALUA_EXPLICIT && group->DeviceList[index]->ImplicitDisabled) && + (deviceInfo->ALUASupport == (DSM_DEVINFO_ALUA_IMPLICIT | DSM_DEVINFO_ALUA_EXPLICIT))))) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Mismatch in device instances' ALUA support %d vs %d.\n", + TargetDevice, + deviceInfo->ALUASupport, + group->DeviceList[index]->ALUASupport)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + } + } + + if (NT_SUCCESS(status)) { + + NT_ASSERT(group); + + group->MaxPRRetryTimeDuringStateTransition = maxPRRetryTimeDuringStateTransition; + + if (alua == DSM_DEVINFO_ALUA_NOT_SUPPORTED) { + + // + // Since the device doesn't support ALUA, it is automatically + // symmetric LU access. + // + group->Symmetric = TRUE; + + if (newGroup) { + + // + // This is the first in the group, so make it the active device. + // The actual active/passive devices will be set-up when + // LB policies are set by the user. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + } else { + + // + // Already something active, this will be the fail-over device + // until the load-balance groups are set-up. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_STANDBY; + } + + } else { + + if (DeviceIdList == NULL) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): No Device ID List.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + if (alua == DSM_DEVINFO_ALUA_IMPLICIT) { + + // + // Assume that the LU access is symmetric. When parsing the TPG + // info, if we find that not all TPGs are in the same LU access + // state, then we know that this the access is asymmetric. + // + group->Symmetric = TRUE; + } + + // + // Build TPG and TP info + // + status = DsmpParseTargetPortGroupsInformation(DsmContext, + group, + targetPortGroupsInfo, + targetPortGroupsInfoLength); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to build TPG information - status %x.\n", + TargetDevice, + status)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + for (index = 0; index < DSM_MAX_PATHS; index++) { + + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup; + + targetPortGroup = group->TargetPortGroupList[index]; + + if (targetPortGroup) { + + DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); + } + } + + // + // Find the target port through which this devInfo was exposed. + // + relativeTargetPortId = (PULONG)DsmpParseDeviceID(DeviceIdList, + DSM_DEVID_RELATIVE_TARGET_PORT, + NULL, + NULL, + FALSE); + NT_ASSERT(relativeTargetPortId); + + if (!relativeTargetPortId) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Couldn't retrieve relative TP id.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // Find the target port group + // + targetPortGroupId = (PUSHORT)DsmpParseDeviceID(DeviceIdList, + DSM_DEVID_TARGET_PORT_GROUP, + NULL, + NULL, + FALSE); + NT_ASSERT(targetPortGroupId); + + if (targetPortGroupId) { + + // + // Find the target port group entry + // + targetPortGroupEntry = DsmpFindTargetPortGroup(DsmContext, + group, + targetPortGroupId); + + NT_ASSERT(targetPortGroupEntry); + + if (targetPortGroupEntry) { + + // + // Look through the target port group to find the target port + // + targetPortEntry = DsmpFindTargetPort(DsmContext, + targetPortGroupEntry, + relativeTargetPortId); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Couldn't find TPG Id %x's entry.\n", + TargetDevice, + *targetPortGroupId)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + NT_ASSERT(targetPortEntry); + + if (!targetPortEntry) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Couldn't find relative TP %x's entry.\n", + TargetDevice, + *relativeTargetPortId)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // Update the devInfo with the target port and target port group + // info + // + deviceInfo->TargetPortGroup = targetPortGroupEntry; + deviceInfo->TargetPort = targetPortEntry; + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = deviceInfo->ALUAState = deviceInfo->TargetPortGroup->AsymmetricAccessState; + + tp_device = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_TARGET_PORT_DEVICELIST_ENTRY), + DSM_TAG_TP_DEVICE_LIST_ENTRY); + + if (!tp_device) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Insufficient resources allocating TP device list entry.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + + // + // Add the device to the list of devices that are exposed via this target port. + // + tp_device->DeviceInfo = deviceInfo; + InterlockedIncrement((LONG volatile*)&targetPortEntry->Count); + InsertTailList(&targetPortEntry->TP_DeviceList, &tp_device->ListEntry); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to retrieve TPG Id.\n", + TargetDevice)); + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + } + + if (NT_SUCCESS(status)) { + + // + // Add the deviceInfo to the list. DO NOT modify the status + // variable if this function returns SUCCESS. + // + status = DsmpAddDeviceEntry(DsmContext, + group, + deviceInfo); + if (NT_SUCCESS(status)) { + + *DsmIdentifier = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Added device %p to group %p.\n", + TargetDevice, + *DsmIdentifier, + group)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to add device %p to group %p - status %x.\n", + TargetDevice, + deviceInfo, + group, + status)); + + // + // We weren't able to add this deviceInfo to the list so we must + // remove its entry on the target port list before the deviceInfo + // is freed. + // + DsmpRemoveDeviceFromTargetPortList(deviceInfo); + + if (newGroup) { + + DsmpRemoveGroupEntry(DsmContext, group, FALSE); + + DsmpFreePool(group); + group = NULL; + } + + status = STATUS_NOT_SUPPORTED; + goto __Exit_DsmInquire; + } + } + } + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + spinlockHeld = FALSE; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Device %p added. State %d, Desired State %d\n", + TargetDevice, + deviceInfo, + deviceInfo->State, + deviceInfo->DesiredState)); + + // + // Update the global list of controller objects + // + controllerObjects = DsmGetAssociatedDevice(dsmContext->MPIOContext, + PortObject, + 0x0C); + if (controllerObjects) { + + // + // This loop needs its own status variable so that it does not + // inadvertently overwrite a STATUS_SUCCESS from the code above. + // + NTSTATUS matchStatus = STATUS_SUCCESS; + PSCSI_ADDRESS controllerScsiAddress = NULL; + + // + // Walk through the list and get VPD 0x83 data and associate the devInfo + // with the controller object. + // + for (index = 0; index < controllerObjects->Count; index++) { + + STORAGE_IDENTIFIER_CODE_SET codeSet = StorageIdCodeSetReserved; + + // + // Free the previously allocated SCSI address, if any. + // + if (controllerScsiAddress) { + DsmpFreePool(controllerScsiAddress); + controllerScsiAddress = NULL; + } + + controllerDeviceObject = (PDEVICE_OBJECT)controllerObjects->IdList[index]; + NT_ASSERT(controllerDeviceObject); + + if (!controllerDeviceObject) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Controller list %p's index %x is NULL.\n", + TargetDevice, + controllerObjects, + index)); + + continue; + } + + matchStatus = DsmpGetDeviceIdList(controllerDeviceObject, &controllerIdHeader); + NT_ASSERT(NT_SUCCESS(matchStatus)); + + if (!NT_SUCCESS(matchStatus)) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to get DeviceId list for controller %p - status %x.\n", + TargetDevice, + controllerDeviceObject, + matchStatus)); + + continue; + } + + controllerSerialNumber = DsmpParseDeviceID((PSTORAGE_DEVICE_ID_DESCRIPTOR)controllerIdHeader, + DSM_DEVID_SERIAL_NUMBER, + NULL, + &codeSet, + FALSE); + NT_ASSERT(controllerSerialNumber); + DsmpFreePool(controllerIdHeader); + + if (!controllerSerialNumber) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to parse serial number for controller %p.\n", + TargetDevice, + controllerDeviceObject)); + + continue; + } + + // + // Note that on success, DsmGetScsiAddress() will allocate memory + // which we are responsible for freeing. + // + matchStatus = DsmGetScsiAddress(controllerDeviceObject, &controllerScsiAddress); + NT_ASSERT(NT_SUCCESS(matchStatus)); + + if (!NT_SUCCESS(matchStatus)) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to get controller %p's scsi address - status %x.\n", + TargetDevice, + controllerDeviceObject, + matchStatus)); + + continue; + } + + controllerEntry = DsmpFindControllerEntry(DsmContext, + PortObject, + controllerScsiAddress, + controllerSerialNumber, + strlen(controllerSerialNumber), + codeSet, + TRUE); + + if (!controllerEntry) { + + controllerEntry = DsmpBuildControllerEntry(DsmContext, + controllerDeviceObject, + PortObject, + controllerScsiAddress, + controllerSerialNumber, + codeSet, + TRUE); + + if (!controllerEntry) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to build an entry for controller %p.\n", + TargetDevice, + controllerDeviceObject)); + + continue; + } + + InsertHeadList(&dsmContext->ControllerList, &controllerEntry->ListEntry); + InterlockedIncrement((LONG volatile*)&dsmContext->NumberControllers); + } + + controllerEntry->DeviceObject = controllerDeviceObject; + + // + // Parse the DeviceIdList for all the 0x5 type identifiers + // and for each, compare the target port groups and target ports to match + // the device to its controller. + // + if (!match) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Failed to match devInfo %p with controller %p's Ids.\n", + TargetDevice, + deviceInfo, + controllerDeviceObject)); + + match = DsmpIsDeviceBelongsToController(DsmContext, + deviceInfo, + controllerEntry); + } + + if (match && !doneUpdating) { + + InterlockedIncrement((LONG volatile*)&(controllerEntry->RefCount)); + deviceInfo->Controller = controllerEntry; + doneUpdating = TRUE; + } + } + + // + // Free the last SCSI address allocated in the loop, if any. + // + if (controllerScsiAddress) { + DsmpFreePool(controllerScsiAddress); + controllerScsiAddress = NULL; + } + } + + // + // If there was no controller to associate this device with, use a fake one. + // Note that we only really care about matching on the Port and Target + // portions of the SCSI address. + // + if (!deviceInfo->Controller) { + + for (entry = dsmContext->ControllerList.Flink; + entry != &dsmContext->ControllerList; + entry = entry->Flink) { + + controllerEntry = CONTAINING_RECORD(entry, DSM_CONTROLLER_LIST_ENTRY, ListEntry); + + if ((controllerEntry->IsFakeController) && + (controllerEntry->ScsiAddress->PortNumber == deviceInfo->ScsiAddress->PortNumber) && + (controllerEntry->ScsiAddress->TargetId == deviceInfo->ScsiAddress->TargetId)) { + + fakeControllerEntryExists = TRUE; + break; + } + } + + // + // If no fake one exists as yet for this port FDO, create one now. + // + if (!fakeControllerEntryExists) { + + CHAR fakeControllerSerialNumber[] = "FakeController"; + SCSI_ADDRESS fakeControllerScsiAddress = {0}; + fakeControllerScsiAddress.PortNumber = deviceInfo->ScsiAddress->PortNumber; + fakeControllerScsiAddress.TargetId = deviceInfo->ScsiAddress->TargetId; + + controllerEntry = DsmpBuildControllerEntry(DsmContext, + NULL, + PortObject, + &fakeControllerScsiAddress, + fakeControllerSerialNumber, + StorageIdCodeSetBinary, + TRUE); + + if (controllerEntry) { + + InsertHeadList(&dsmContext->ControllerList, &controllerEntry->ListEntry); + InterlockedIncrement((LONG volatile*)&dsmContext->NumberControllers); + controllerEntry->IsFakeController = TRUE; + } + } + + if (controllerEntry) { + InterlockedIncrement((LONG volatile*)&(controllerEntry->RefCount)); + } + + deviceInfo->Controller = controllerEntry; + } + +__Exit_DsmInquire: + + if (spinlockHeld) { + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + } + + if (NT_SUCCESS(status)) { + + NT_ASSERT(*DsmIdentifier); + + } else { + + // + // If there was any sort of ERROR, the deviceInfo will NOT be put on + // MSDSM's internal list that is accessible to other threads. Thus, + // we are safe to free the memory below and we do not require any + // synchronization mechanism to do so. + // + + // + // Check to see whether the serial number buffer was allocated, or just + // an offset into the Descriptor. + // + if (serialNumberAllocated) { + + // + // Need to free this before returning. + // + DsmpFreePool(serialNumber); + } + + if (deviceInfo) { + + if (deviceInfo->ScsiAddress) { + DsmpFreePool(deviceInfo->ScsiAddress); + } + + DsmpFreePool(deviceInfo); + } + } + + // + // If deviceName is not NULL then it hasn't been assigned to any GROUP. + // Free the allocated memory. + // + if (deviceName) { + DsmpFreePool(deviceName); + } + + // + // If hardwareId is not NULL then it hasn't been assigned to any GROUP. + // Free the allocated memory. + // + if (hardwareId) { + DsmpFreePool(hardwareId); + } + + if (targetPortGroupsInfo) { + DsmpFreePool(targetPortGroupsInfo); + } + + if (relativeTargetPortId) { + DsmpFreePool(relativeTargetPortId); + } + + if (targetPortGroupId) { + DsmpFreePool(targetPortGroupId); + } + + if (controllerObjects) { + DsmpFreePool(controllerObjects); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmInquire (DevObj %p): Exiting function with status %x.\n", + TargetDevice, + status)); + + return status; +} + + +BOOLEAN +DsmCompareDevices( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId1, + _In_ IN PVOID DsmId2 + ) +/*++ + +Routine Description: + + This routine is called to determine if the device ids represent + the same underlying physical device. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + DsmId1/2 - Identifers returned from DMS_INQUIRE_DRIVER. + +Return Value: + + TRUE if DsmIds correspond to the same underlying device. + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo0 = DsmId1; + PDSM_DEVICE_INFO deviceInfo1 = DsmId2; + PSTR serialNumber0; + PSTR serialNumber1; + SIZE_T length; + BOOLEAN match = FALSE; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmCompareDevices (DevInfo %p): Entering function - comparing with %p.\n", + deviceInfo0, + deviceInfo1)); + + // + // Get the two serial numbers. They were either embedded in + // the STORAGE_DEVICE_DESCRIPTOR or built by directly issuing + // the VPD request. + // + serialNumber0 = deviceInfo0->SerialNumber; + serialNumber1 = deviceInfo1->SerialNumber; + + if (serialNumber0 && serialNumber1) { + + // + // Get the length of the base-device Serial Number. + // + length = strlen((const char*)serialNumber0); + + // + // If the lengths match, compare the contents. + // + if (length == strlen((const char*)serialNumber1)) { + + if (RtlEqualMemory(serialNumber0, serialNumber1, length)) { + match = TRUE; + } + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmCompareDevices (DevInfo %p): Serialnumber not assigned for %p and\\or %p.\n", + DsmId1, + deviceInfo0, + deviceInfo1)); + } + + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmCompareDevices (DevInfo %p): Exiting function with match = %!bool!.\n", + DsmId1, + match)); + + return match; +} + + +NTSTATUS +DsmGetControllerInfo( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN ULONG Flags, + _Inout_ IN OUT PCONTROLLER_INFO *ControllerInfo + ) +/*++ + +Routine Description: + + This routine is used to get information about the controller that + the device corresponding to DsmId in on. Currently this DSM controls + hardware that doesn't expose controllers directly. Therefore State + is always NO_CNTRL. This information is used mainly by whatever + WMI admin utilities want it. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + + DsmId - Value returned from DMSInquireDriver. + + Flags - Bitfield of modifiers. If ALLOCATE is not set, ControllerInfo + will have a valid buffer for the DSM to operate on. + + ControllerInfo - Pointer for the DSM to place the allocated controller + info pertaining to DsmId + +Return Value: + + STATUS_INSUFFICIENT_RESOURCES if memory allocation fails. + + STATUS_SUCCESS on success + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo = DsmId; + PDSM_CONTROLLER_LIST_ENTRY controllerEntry = deviceInfo->Controller; + PCONTROLLER_INFO controllerInfo = NULL; + LARGE_INTEGER time; + ULONG controllerId = 0; + NTSTATUS status = STATUS_SUCCESS; + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmGetControllerInfo (DevInfo %p): Entering function.\n", + DsmId)); + + // + // Check to see whether a controller id has already been made-up. + // + if (!controllerEntry) { + + // + // Since this device is in an enclosure that doesn't have controllers, + // e.g. JBOD, make one up. + // + KeQuerySystemTime(&time); + + // + // Use only the lower 32-bits. + // + controllerId = time.LowPart; + } + + // + // Check the Flags + // + if (Flags & DSM_CNTRL_FLAGS_ALLOCATE) { + + // + // This is the first call. Need to allocate the controller structure. + // + controllerInfo = DsmpAllocatePool(NonPagedPoolNx, + sizeof(CONTROLLER_INFO), + DSM_TAG_CTRL_INFO); + if (!controllerInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmGetControllerInfo (DevInfo %p): Failed to allocate memory for Controller Info\n", + DsmId)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmGetControllerInfo; + } + + if (!controllerEntry) { + + // + // Indicate that there are no specific controllers. + // + controllerInfo->State = DSM_CONTROLLER_NO_CNTRL; + + // + // Set the identifier to the value generated earlier. + // Indicate that it's Binary, not ASCII. + // + controllerInfo->Identifier.Type = StorageIdCodeSetBinary; + controllerInfo->Identifier.Length = 8; + + RtlCopyMemory(controllerInfo->Identifier.SerialNumber, + &controllerId, + sizeof(controllerId)); + + } else { + + // + // If either implicit or explicit ALUA state transition is supported, + // every controller is active. Else, if the devInfo's is in Active + // state, the controller is obviously in the active state. + // + if ((deviceInfo->ALUASupport != DSM_DEVINFO_ALUA_NOT_SUPPORTED) || + (DsmpIsDeviceStateActive(deviceInfo->State))) { + + controllerInfo->State = DSM_CONTROLLER_ACTIVE; + + } else { + + controllerInfo->State = DSM_CONTROLLER_STANDBY; + } + + controllerInfo->Identifier.Type = controllerEntry->IdCodeSet; + controllerInfo->Identifier.Length = controllerEntry->IdLength; + + if (controllerInfo->Identifier.Length > 32) { + + controllerInfo->Identifier.Length = 32; + } + + RtlCopyMemory(controllerInfo->Identifier.SerialNumber, + controllerEntry->Identifier, + controllerInfo->Identifier.Length); + + controllerInfo->DeviceObject = controllerEntry->DeviceObject; + } + + *ControllerInfo = controllerInfo; + + } else if (Flags & DSM_CNTRL_FLAGS_CHECK_STATE) { + + // + // Get the passed in struct. + // + controllerInfo = *ControllerInfo; + + // + // If the enclosures supported by this DSM actually had controllers, + // there would be a list of them and a search based on + // ControllerIdentifier would be made. + // + controllerEntry = deviceInfo->Controller; + + if (!controllerEntry) { + + controllerInfo->State = DSM_CONTROLLER_NO_CNTRL; + + } else { + + // + // If either implicit or explicit ALUA state transition is supported, + // every controller is active. Else, if the devInfo's is in Active + // state, the controller is obviously in the active state. + // + if ((deviceInfo->ALUASupport != DSM_DEVINFO_ALUA_NOT_SUPPORTED) || + (DsmpIsDeviceStateActive(deviceInfo->State))) { + + controllerInfo->State = DSM_CONTROLLER_ACTIVE; + + } else { + + controllerInfo->State = DSM_CONTROLLER_STANDBY; + } + } + } + +__Exit_DsmGetControllerInfo: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmGetControllerInfo (DevInfo %p): Exiting function with status %x.\n", + DsmId, + status)); + + return status; +} + + +NTSTATUS +DsmSetDeviceInfo( + _In_ IN PVOID DsmContext, + _In_ IN PDEVICE_OBJECT TargetObject, + _In_ IN PVOID DsmId, + _Inout_ IN OUT PVOID *PathId + ) +/*++ + +Routine Description: + + This routine associates the DsmId to the controlling MPDisk PDO, + the targetObject for DSM-initiated requests, and to a Path + (given by PathId). + This routine will update the PathId in a way that better explains + the topology to MPIO. + Additionally, if we are in failover LB policy, failback if this + path is preferred path. + Also, if PR is being used, send registration down this path. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + TargetObject - The D.O. to which DSM-initiated requests should be sent. + DsmId - Value returned from DMSInquireDriver. + PathId - Id that represents the path. The value passed in may be used + as is, or the DSM optionally can update it if it requires + additional state info to be kept. + +Return Value: + + INSUFFICENT_RESOURCES for no-mem conditions. + STATUS_SUCCESS + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo = DsmId; + PDSM_GROUP_ENTRY group = deviceInfo->Group; + PDSM_FAILOVER_GROUP failGroup; + PDSM_CONTEXT dsmContext; + PSCSI_ADDRESS scsiAddress; + ULONG primaryPath = 0; + ULONG optimizedPath = 0; + ULONG pathWeight = 0; + ULONG pathId; + NTSTATUS status = STATUS_SUCCESS; + WCHAR registryKeyName[256] = {0}; + BOOLEAN newFOGroup = FALSE; + BOOLEAN registryKeyExists = FALSE; + KIRQL irql; + PVOID tempPathId = *PathId; + DSM_LOAD_BALANCE_TYPE loadBalanceType; + ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + UCHAR explicitlySet = FALSE; + BOOLEAN vidpidPolicySet = FALSE; + BOOLEAN overallPolicySet = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Entering function.\n", + DsmId)); + + // + // 1. Set default LB policy. + // 2. Query LB policy from registry and update if necessary. + // 3. Set default value for primaryPath and optimizedPath based on device's + // access state + // 4. Map deviceInfo to real LUN by saving off the target for I/O + // 5. Build pathId from SCSI address + // 6. Find FOG for device. If none found, build one. + // Add deviceInfo to FOG. + // 7. Query registry for pathWeight, primaryPath and optimizedPath + // Update deviceInfo with results of query. + // 8. Compare deviceInfo access state with persistent value (based on + // primaryPath and optimizedPath) and update its DesiredState. + // + + if (!TargetObject) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): No target object.\n", + deviceInfo)); + + // + // This deviceInfo will have no path or targetObject associated with it. + // Mark it in a failed state so it won't be used to handle any requests. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_UNDETERMINED; + + goto __Exit_DsmSetDeviceInfo; + } + + // + // Default LB type is Round Robin. + // + loadBalanceType = DSM_LB_ROUND_ROBIN; + + // + // Override the default with whatever is the overall policy that needs to be + // applied for all LUNs controlled by MSDSM. + // + // Override that policy if one has been set for this device's VID/PID. + // + // Override that policy with whatever has been explicitly set for this particular + // device. + // + // In order to perform the above, first query the policy for this particular device. + // If it has not been explicity set, use MSDSM's overall policy or VID/PID policy. + // + status = DsmpQueryDeviceLBPolicyFromRegistry(deviceInfo, + group->RegistryKeyName, + &loadBalanceType, + &preferredPath, + &explicitlySet); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Failed to query LB policy from registry. Status %x.\n", + deviceInfo, + status)); + + NT_ASSERT(NT_SUCCESS(status)); + + // + // This deviceInfo will have no path or targetObject associated with it. + // Mark it in a failed state so it won't be used to handle any requests. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_UNDETERMINED; + + goto __Exit_DsmSetDeviceInfo; + } + + // + // If this device's policy was not explicitly set, check to see if a policy + // was set for this device's VID/PID and use that. + // If VID/PID policy is not set, query the overall default policy + // that needs to be applied to all devices controlled by this DSM. + // If this setting hasn't been set, we'll fall back to using the default that was + // determined based on the storage's ALUA capabilities. + // + if (!explicitlySet) { + + status = DsmpQueryTargetLBPolicyFromRegistry(deviceInfo, + &loadBalanceType, + &preferredPath); + + if (NT_SUCCESS(status)) { + + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_VID_PID; + vidpidPolicySet = TRUE; + + } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + // + // Since the policy hasn't been set for this VID/PID, check if + // overall MSDSM-wide policy has been set. + // + status = DsmpQueryDsmLBPolicyFromRegistry(&loadBalanceType, + &preferredPath); + if (NT_SUCCESS(status)) { + + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; + overallPolicySet = TRUE; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Failed to query Dsm overall LB policy from registry. Status %x.\n", + deviceInfo, + status)); + + NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); + status = STATUS_SUCCESS; + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Failed to query VID/PID LB policy from registry. Status %x.\n", + deviceInfo, + status)); + + NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); + status = STATUS_SUCCESS; + } + } else { + + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT; + } + + if (!explicitlySet && !vidpidPolicySet && !overallPolicySet) { + + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; + + } + + // + // If ALUA is enabled and the load balance policy is set to Round Robin, + // we need to set it to Round Robin with Subset instead. + // + if (!DsmpIsSymmetricAccess(deviceInfo) && loadBalanceType == DSM_LB_ROUND_ROBIN) { + loadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; + } + + group->LoadBalanceType = loadBalanceType; + group->PreferredPath = preferredPath; + dsmContext = (PDSM_CONTEXT) DsmContext; + + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + + // + // Save the registry key name under which Load balance policies + // are stored. This will be used to query the LB policy later. + // + if (group->RegistryKeyName) { + + registryKeyExists = TRUE; + + if (!NT_SUCCESS(RtlStringCchCopyNW(registryKeyName, + sizeof(registryKeyName) / sizeof(registryKeyName[0]), + group->RegistryKeyName, + ((sizeof(registryKeyName) / sizeof(registryKeyName[0])) - sizeof(WCHAR))))) { + + registryKeyName[(sizeof(registryKeyName) / sizeof(registryKeyName[0])) - 1] = L'\0'; + } + } + + // + // TargetObject is the destination for any requests created by this driver. + // Save this for future reference. + // + deviceInfo->TargetObject = TargetObject; + + // + // Set the PathId - All devices on the same PathId will + // failover together. Currently the pathId is constructed + // from Port Number, Bus Number, and Target Id of the device. + // + scsiAddress = deviceInfo->ScsiAddress; + NT_ASSERT(scsiAddress); + + pathId = 0x77; + pathId <<= 8; + pathId |= scsiAddress->PortNumber; + pathId <<= 8; + pathId |= scsiAddress->PathId; + pathId <<= 8; + pathId |= scsiAddress->TargetId; + + *PathId = ((PVOID)((ULONG_PTR)(pathId))); + + // + // PathId indicates the path on which this device resides. Meaning + // that when a Fail-Over occurs all device's on the same path fail + // together. Search for a matching F.O. Group + // + failGroup = DsmpFindFOGroup(DsmContext, *PathId); + + // + // If not found, create a new failover group + // + if (!failGroup) { + + failGroup = DsmpBuildFOGroup(DsmContext, deviceInfo, PathId); + + if (failGroup) { + + newFOGroup = TRUE; + failGroup->MPIOPath = tempPathId; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Failed to build FO Group.\n", + DsmId)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (NT_SUCCESS(status)) { + + // + // If this path is in the midst of failover processing, mark it as "good" + // again. + // + failGroup->State = DSM_FG_NORMAL; + + // + // add this deviceInfo to the f.o. group. + // + status = DsmpUpdateFOGroup(DsmContext, failGroup, deviceInfo); + NT_ASSERT(NT_SUCCESS(status)); + } + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + + if (NT_SUCCESS(status)) { + + if (registryKeyExists) { + + NTSTATUS queryStatus = STATUS_INVALID_PARAMETER; + ULONGLONG pathId64; + + // + // If the overall default policy or a target-level policy has been set and + // this device's policy has not been explicitly set, there's no use querying + // its individual path (desired) states. + // + if ((!overallPolicySet && !vidpidPolicySet) || (explicitlySet)) { + + // + // Created a new failover group. Query the LB policy + // for this device from registry. + // + pathId64 = (ULONGLONG)((ULONG_PTR)*PathId); + + queryStatus = DsmpQueryLBPolicyForDevice(registryKeyName, + pathId64, + loadBalanceType, + &primaryPath, + &optimizedPath, + &pathWeight); + } + + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + + if (NT_SUCCESS(queryStatus)) { + + deviceInfo->PathWeight = pathWeight; + + // + // If device doesn't support ALUA, update the device state + // based on the primary path info in the registry. + // + if (DsmpIsSymmetricAccess(deviceInfo)) { + + if (primaryPath) { + + deviceInfo->DesiredState = DSM_DEV_ACTIVE_OPTIMIZED; + + } else { + + deviceInfo->DesiredState = DSM_DEV_STANDBY; + } + + } else { + + DSM_DEVICE_STATE devState; + + if (primaryPath) { + + devState = optimizedPath ? DSM_DEV_ACTIVE_OPTIMIZED : DSM_DEV_ACTIVE_UNOPTIMIZED; + + } else { + + devState = optimizedPath ? DSM_DEV_STANDBY : DSM_DEV_UNAVAILABLE; + } + + // + // For ALUA, desired state makes sense for FOO. + // For RRWS, we assume desired state was explicitly selected + // by Admin if the ALUA state is different from the path + // state. Only under such cases would the path state have + // been saved in registry. + // In all other policies, state must just match the TPG state. + // + if (group->LoadBalanceType == DSM_LB_FAILOVER || + group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { + + deviceInfo->DesiredState = devState; + + } else { + + deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; + } + } + } else if (queryStatus == STATUS_OBJECT_NAME_NOT_FOUND) { + + deviceInfo->PathWeight = pathWeight; + deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; + + } else { + + deviceInfo->PathWeight = 0; + deviceInfo->DesiredState = DSM_DEV_UNDETERMINED; + } + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + } + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): PathWeight %x, DesiredState %x, State %x, PrevState %x.\n", + deviceInfo, + deviceInfo->PathWeight, + deviceInfo->DesiredState, + deviceInfo->State, + deviceInfo->PreviousState)); + + if (NT_SUCCESS(status)) { + + deviceInfo->Initialized = TRUE; + + } else if (!NT_SUCCESS(status) && newFOGroup) { + + // + // This deviceInfo will have no path associated with it. + // Mark it in a failed state so it won't be used to handle any requests. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_UNDETERMINED; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): No path associated with instance. Changing state from %u to %u.\n", + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + + DsmpRemoveDeviceFailGroup(DsmContext, failGroup, deviceInfo, TRUE); + + if (failGroup->Count == 0) { + + // + // Yank it from the list. + // + RemoveEntryList(&failGroup->ListEntry); + InterlockedDecrement((LONG volatile*)&dsmContext->NumberFOGroups); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Removing FOGroup %p with path %p. Count of FOGroups %d.\n", + DsmId, + failGroup, + failGroup->PathId, + dsmContext->NumberFOGroups)); + + // + // Free the zombie group list and then the failover group. + // + DsmpFreeZombieGroupList(failGroup); + DsmpFreePool(failGroup); + } + } + +__Exit_DsmSetDeviceInfo: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmSetDeviceInfo (DevInfo %p): Exiting function with status %x.\n", + DsmId, + status)); + + return status; +} + + +BOOLEAN +DsmIsPathActive( + _In_ IN PVOID DsmContext, + _In_ IN PVOID PathId, + _In_ IN PVOID DsmId + ) +/*++ + +Routine Description: + + This routine is used to determine whether the path to DsmId is usable + (ie. able to handle requests without a failover). + + Also, after a failover, the path validity will be queried. + If the path error was transitory and the DSM feels that the path is good, + then this request will be re-issued to determine whether it is usable. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + PathId - Value set in SetPathId. + DsmId - DSM Id returned during DsmInquire. + +Return Value: + + TRUE if the path is active. FALSE otherwise. +--*/ +{ + PDSM_FAILOVER_GROUP foGroup; + PDSM_DEVICE_INFO deviceInfo = DsmId; + PDSM_GROUP_ENTRY group = deviceInfo->Group; + PDSM_CONTEXT dsmContext = (PDSM_CONTEXT) DsmContext; + KIRQL irql; + BOOLEAN retVal; + ULONG SpecialHandlingFlag = 0; + + // + // 1. If PR and reserved by this node, register the PR keys. + // 2. Find the FOG for the passed in PathId + // 3. Depending on the LB policy, set the appropriate devInfo states + // If FailOver, and DesiredState is AO, change the active + // devInfos to non-active state and make this one AO. + // If ALUA supported, send down SetTPG to make this change, + // else directly make the change. + // If RR/LWP/LQD, make this DevInfo ActiveOptimized. + // If RRS, and DesiredState is AO, change the active devInfos to + // their desired states and then make this one AO. + // If DesiredState is not AO, find a devInfo in AO state. If + // one is found, make this devInfo's state its desired state, + // else if one isn't found, make this one AO. + // 3. If this is preferredPath, and LB policy is failover-only, change the + // access state of deviceInfo to AO. + // If there is another devInfo currently in AO, change its state too. + // If ALUA supported, send down SetTPG to make these changes. + // 4. Get the appropriate AO DeviceInfo and mark the group's PTBU to its + // pathId. + // + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): Entering function.\n", + DsmId)); + + // + // Initialize this instance to be usable so that during the possible processing + // of PR register, this device can be a candidate for certain kind of requests. + // + deviceInfo->Usable = TRUE; + + // + // New path arriving. If this Node owns the reservation register this path. + // + if (group->PRKeyValid) { + + NTSTATUS prRegStatus; + ULONG i; + PDSM_DEVICE_INFO devInfo; + ULONG ordinal; + + prRegStatus = DsmpRegisterPersistentReservationKeys(deviceInfo, TRUE); + + deviceInfo->RegisterServiced = TRUE; + + if (NT_SUCCESS(prRegStatus)) { + + deviceInfo->PRKeyRegistered = TRUE; + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): Failed (status %x) to register PR key\n", + deviceInfo, + prRegStatus)); + } + + for (i = 0; i < group->NumberDevices; i++) { + + devInfo = group->DeviceList[i]; + if (devInfo && devInfo == deviceInfo) { + + ordinal = (1 << i); + group->ReservationList |= ordinal; + break; + } + } + } + + + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + + // + // Get the F.O. Group information. + // + foGroup = DsmpFindFOGroup(DsmContext, PathId); + + // + // If there are any devices on this path, and it's not in a failed state + // it's capable of handling requests. So it's active. + // + if ((foGroup) && + (foGroup->Count) && + (foGroup->State == DSM_FG_NORMAL)) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): Path %p is usable.\n", + DsmId, + PathId)); + + retVal = TRUE; + + // + // Update the next path to be used for the group if it not set already. + // + deviceInfo = (PDSM_DEVICE_INFO)DsmId; + + group = deviceInfo->Group; + DSM_ASSERT(group != NULL); + DSM_ASSERT(group->GroupSig == DSM_GROUP_SIG); + + // + // If an invalidated path came back online before PnP removes came in, + // then MPIO's path recovery thread would have sent down a PathVerify + // just moments before by which we changed the state of the FOG to + // normal. Now it is time to change the deviceInfo's state to a "good" + // state. + // + if (deviceInfo->State >= DSM_DEV_FAILED) { + + DSM_ASSERT(deviceInfo->State == DSM_DEV_INVALIDATED); + + if (DsmpIsSymmetricAccess(deviceInfo)) { + + // + // Mark it as AO. The SetLBForPathArrival will update the state + // appropriately. + // + deviceInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + + } else { + + // + // Set it to the state that was reported during the last RTPG + // call that was made. + // + deviceInfo->State = deviceInfo->ALUAState; + } + } + + if (DsmpIsSymmetricAccess(deviceInfo)) { + + DsmpSetLBForPathArrival(DsmContext, deviceInfo, SpecialHandlingFlag); + + } else { + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + DsmpSetLBForPathArrivalALUA(DsmContext, deviceInfo, SpecialHandlingFlag); + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): State set to %d\n", + deviceInfo, + deviceInfo->State)); + + if (group->PathToBeUsed == NULL) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): Will set PathToBeUsed for %p\n", + deviceInfo, + group)); + + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess(deviceInfo), + SpecialHandlingFlag); + if (deviceInfo != NULL) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): FOG %p set for PathToBeUsed for %p\n", + deviceInfo, + deviceInfo->FailGroup, + group)); + + InterlockedExchangePointer(&(group->PathToBeUsed), deviceInfo->FailGroup); + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): No active/alternative path available for group %p\n", + DsmId, + group)); + + InterlockedExchangePointer(&(group->PathToBeUsed), NULL); + } + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): Path %p is NOT usable.\n", + DsmId, + PathId)); + + retVal = FALSE; + } + + ((PDSM_DEVICE_INFO)DsmId)->Usable = retVal; + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmIsPathActive (DevInfo %p): Exiting function with retVal = %!bool!.\n", + DsmId, + retVal)); + + return retVal; +} + + +NTSTATUS +DsmPathVerify( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PVOID PathId + ) +/*++ + +Routine Description: + + This routine ensures that the path to the device indicated by DsmId + is healthy. It's called periodically by the bus driver, and also + after a fail-over condition has been dealt with to ensure that + the path is able to handle requests. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + DsmId - Value returned from DMSInquire. + PathId - Value set in SetPathId. + +Return Value: + + NTSTATUS +--*/ + +{ + PDSM_CONTEXT dsmCtxt = (PDSM_CONTEXT) DsmContext; + PDSM_DEVICE_INFO deviceInfo = DsmId; + PDSM_FAILOVER_GROUP foGroup; + NTSTATUS status = STATUS_UNSUCCESSFUL; + BOOLEAN found = FALSE; + KIRQL irql; + PLIST_ENTRY entry; + PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry = NULL; + PDSM_GROUP_ENTRY group = deviceInfo->Group; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmPathVerify (DevInfo %p): Entering function.\n", + DsmId)); + + if (DsmpIsDeviceInitialized(deviceInfo)) { + + irql = ExAcquireSpinLockExclusive(&(dsmCtxt->DsmContextLock)); + + // + // Get the failover group + // + foGroup = DsmpFindFOGroup(DsmContext, PathId); + + if (foGroup) { + + // + // Find the device. + // + for (entry = foGroup->FOG_DeviceList.Flink; + entry != &foGroup->FOG_DeviceList; + entry = entry->Flink) { + + fogDeviceListEntry = CONTAINING_RECORD(entry, DSM_FOG_DEVICELIST_ENTRY, ListEntry); + + if (fogDeviceListEntry && fogDeviceListEntry->DeviceInfo == deviceInfo) { + + status = STATUS_SUCCESS; + found = TRUE; + + break; + } + } + } else { + + // + // This is not a good thing. It indicates that either we + // returned a bogus path to the bus-driver on a fail-over, + // or that the path evaporated between polls and PnP hasn't + // torn stuff down. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmPathVerify (DevInfo %p): Failed to find failover group for path %p.\n", + DsmId, + PathId)); + + status = STATUS_DEVICE_NOT_CONNECTED; + } + + ExReleaseSpinLockExclusive(&(dsmCtxt->DsmContextLock), irql); + + if (NT_SUCCESS(status)) { + + if (found) { + + // + // Send down TUR if ALUA is not supported. + // Else, send down ReportTargetPortGroups (sending TUR down non-A/O path will + // always result in a check condition). + // + if (deviceInfo->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmPathVerify (DevInfo %p): Sending TUR using %p to verify path %p.\n", + DsmId, + deviceInfo, + deviceInfo->FailGroup->PathId)); + + status = DsmSendTUR(deviceInfo->TargetObject); + + } else { + + // + // Check for whether we should ignore sending down an RTPG: + // Flag set indicates that this PathVerify() is happening in response to device + // arrival and can be skipped since Inquire() has just already sent down an RTPG. + // All that needs to be done is to clear the flag so that subsequent PathVerify() + // sent in response to InitiateFO will send RTPG as a ping. + // This is an optimization with the idea of helping speed up boot time, which is + // is adversely impacted, especially if there are many LUNs, each with many paths. + // + if (deviceInfo->IgnorePathVerify) { + + deviceInfo->IgnorePathVerify = FALSE; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmPathVerify (DevInfo %p): Returning success immediately since RTPG was already just sent.\n", + DsmId)); + + status = STATUS_SUCCESS; + + } else { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmPathVerify (DevInfo %p): Sending RTPG using %p to verify path %p.\n", + DsmId, + deviceInfo, + deviceInfo->FailGroup->PathId)); + + status = DsmpGetDeviceALUAState(dsmCtxt, deviceInfo, NULL); + + // + // Since this RTPG may have resulted in us losing a UA, adjust + // the states if needed. + // + if (NT_SUCCESS(status)) { + + DsmpAdjustDeviceStatesALUA(group, NULL, SpecialHandlingFlag); + } + } + } + } + + if (NT_SUCCESS(status)) { + + if (deviceInfo->State >= DSM_DEV_FAILED) { + + foGroup->State = DSM_FG_NORMAL; + deviceInfo->State = deviceInfo->LastKnownGoodState; + } + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmPathVerify (DevInfo %p): Exiting function with status %x.\n", + DsmId, + status)); + + return status; +} + + +NTSTATUS +DsmInvalidatePath( + _In_ IN PVOID DsmContext, + _In_ IN ULONG ErrorMask, + _In_ IN PVOID PathId, + _Inout_ IN OUT PVOID *NewPathId + ) +/*++ + +Routine Description: + + This routine will mark up devices as failed on PathId, and find + an appropriate path to return to MPIO. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + ErrorMask - Value returned from InterpretError. + PathId - The failing path. + NewPathId - Pointer to the new path. + +Return Value: + + NTSTATUS of the operation. + +--*/ +{ + PDSM_CONTEXT context = DsmContext; + PDSM_FAILOVER_GROUP failGroup; + PDSM_FAILOVER_GROUP newPath = NULL; + PDSM_FAILOVER_GROUP pathId; + PDSM_DEVICE_INFO deviceInfo; + LIST_ENTRY reservedDeviceList; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + PLIST_ENTRY entry; + PDSM_FOG_DEVICELIST_ENTRY fogDeviceListEntry = NULL; + BOOLEAN lockHeld = FALSE; + + UNREFERENCED_PARAMETER(ErrorMask); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): Entering function.\n", + PathId)); + + DSM_ASSERT(ErrorMask & DSM_FATAL_ERROR); + + *NewPathId = NULL; + + InitializeListHead(&reservedDeviceList); + + irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); + lockHeld = TRUE; + + // + // Get the fail-over group corresponding to the PathId. + // + failGroup = DsmpFindFOGroup(DsmContext, PathId); + + if (!failGroup || failGroup->State == DSM_FG_FAILED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): Failed to find FailOver group.\n", + PathId)); + + status = STATUS_NO_SUCH_DEVICE; + goto __Exit_DsmInvalidatePath; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): Context %p, FOG %p failing.\n", + PathId, + DsmContext, + failGroup)); + + // + // Mark the path as failed. + // + failGroup->State = DSM_FG_FAILED; + + // + // Check to see whether the port driver and PnP removed the devices + // BEFORE the fail-over indication actually occurred. Work-around + // of several Fibre miniports. + // + if (failGroup->Count == 0) { + + // + // There are no longer any devices in this fail-over group, which means + // in order to get a back-pointer to the groups using this fail-over + // group, we need to go through the "zombie" group list. This should + // allow us to find a new path ID to return. + //Then go through failGroup->ZombieGroupList to do failover for each group. + // + PDSM_ZOMBIEGROUP_ENTRY group; + PDSM_GROUP_ENTRY groupEntry; + + // + // Initialize all the entries to indicate that they haven't been processed. + // + for (entry = failGroup->ZombieGroupList.Flink; entry != &(failGroup->ZombieGroupList); entry = entry->Flink) { + + group = CONTAINING_RECORD(entry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); + group->Processed = FALSE; + } + + // + // Since we need to drop the spin lock while processing an entry, it is possible + // that a removal in parallel frees up this entry during that time, thus making it + // impossible for us to move to the next entry in the list. + // In order to safely access each of the entries, we mark an entry as being processed + // just before dropping the spinlock, and always start processing from the beginning + // of the list, skipping over the already processed ones. + // + entry = failGroup->ZombieGroupList.Flink; + + while (entry != &(failGroup->ZombieGroupList)) { + + group = CONTAINING_RECORD(entry, DSM_ZOMBIEGROUP_ENTRY, ListEntry); + entry = entry->Flink; + + if (!group || !group->Group || group->Processed) { + continue; + } + + group->Processed = TRUE; + groupEntry = group->Group; + + ExReleaseSpinLockExclusive(&context->DsmContextLock, irql); + lockHeld = FALSE; + + pathId = DsmpSetNewPathUsingGroup((PDSM_CONTEXT)DsmContext, groupEntry); + + if (!newPath) { + newPath = pathId; // Save off first good alternative path that we find + } + + if (!lockHeld) { + irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); + lockHeld = TRUE; + entry = failGroup->ZombieGroupList.Flink; + } + } + + if (!newPath) { + // + // This indicates that all of the devices have already been removed. + // If there were reservations outstanding, the RemoveDevice code + // should have updated them. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): Failed to find new path using zombie group list.\n", + PathId)); + } + + } else { + + + // + // Process each device in the fail-over group + // + for (entry = failGroup->FOG_DeviceList.Flink; + entry != &failGroup->FOG_DeviceList; + entry = entry->Flink) { + + fogDeviceListEntry = CONTAINING_RECORD(entry, DSM_FOG_DEVICELIST_ENTRY, ListEntry); + + if (!fogDeviceListEntry) { + continue; + } + + // + // Get the deviceInfo. + // + deviceInfo = fogDeviceListEntry->DeviceInfo; + + if (!(DsmpIsDeviceFailedState(deviceInfo->State))) { + + deviceInfo->LastKnownGoodState = deviceInfo->State; + } + + // + // Set the state of the Failing Device + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_INVALIDATED; + + InterlockedIncrement(&deviceInfo->BlockRemove); + + ExReleaseSpinLockExclusive(&(context->DsmContextLock), irql); + lockHeld = FALSE; + + pathId = DsmpSetNewPath(DsmContext, deviceInfo); + + if (!newPath) { + newPath = pathId; // Save off first good alternative path that we find + } + + if (!lockHeld) { + irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); + lockHeld = TRUE; + } + + InterlockedDecrement(&deviceInfo->BlockRemove); + } + } + + if (!newPath) { + + // + // This indicates that no acceptable paths + // were found. Return the error to mpctl. + // + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): No valid path found.\n", + PathId)); + + status = STATUS_NO_SUCH_DEVICE; + + } else { + + // + // return the new path. + // + *NewPathId = newPath->PathId; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): Returning %p as newPath.\n", + PathId, + newPath->PathId)); + } + +__Exit_DsmInvalidatePath: + + if (lockHeld) { + ExReleaseSpinLockExclusive(&(context->DsmContextLock), irql); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmInvalidatePath (PathId %p): Exiting function with status %x.\n", + PathId, + status)); + + return status; +} + + +NTSTATUS +DsmMoveDevice( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PVOID MPIOPath, + _In_ IN PVOID SuggestedPath, + _In_ IN ULONG Flags + ) +/*++ + +Routine Description: + + This routine is invoked in response to an administrative request. + The device that's associated with SuggestedPath will be made active, and the + current active device, moved to stand-by. + +Arguments: + + DsmContext - Context value given to the multipath driver during registration. + DsmIds - The collection of DSM IDs that pertain to the MPDisk. + MPIOPath - The original path value passed to SetDeviceInfo. + SuggestedPath - The path which should become the active path. + Flags - Bitmask indicating the intent of the move. + +Return Value: + + NTSTATUS - STATUS_SUCCESS, unless SuggestedPath is somehow invalid. + STATUS_INVALID_PARAMETER is ADMIN is set and the path is invalid. + +--*/ +{ + PDSM_CONTEXT context = DsmContext; + PDSM_DEVICE_INFO deviceInfo; + PDSM_FAILOVER_GROUP failGroup; + ULONG i; + NTSTATUS status; + KIRQL irql; + BOOLEAN adminRequest = FALSE; + PDSM_GROUP_ENTRY group = NULL; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmMoveDevice (DsmIds %p): Entering function - DsmContext %p MPIOPath (%p) SuggestedPath %p.\n", + DsmIds, + DsmContext, + MPIOPath, + SuggestedPath)); + + // + // Capture the value of the ADMIN flag bit. + // Currently, permanent assignment of the device to "preferred path" isn't supported. + // This driver doesn't care about the pending remove flag (currently). + // + adminRequest = (BOOLEAN)(Flags & DSM_MOVE_ADMIN_REQUEST); + + irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); + + group = ((PDSM_DEVICE_INFO)(DsmIds->IdList[0]))->Group; + + // + // Find the first active device. + // + deviceInfo = DsmpGetActivePathToBeUsed(group, + DsmpIsSymmetricAccess((PDSM_DEVICE_INFO)DsmIds->IdList[0]), + SpecialHandlingFlag); + + if (!deviceInfo) { + + // + // Didn't find an active device. Should LOG. + // Use the first one to piggy-back the request. + // + deviceInfo = DsmIds->IdList[0]; + } + + // + // Get the fail-over group associated with the Path. + // + failGroup = DsmpFindFOGroup(DsmContext, + SuggestedPath); + + if (!failGroup) { + + // + // The caller has made a terrible mistake. + // If it's an ADMIN request, blow it off. + // + if (adminRequest) { + status = STATUS_INVALID_PARAMETER; + } else { + + // + // Try to set another path. + // + // Note that failGroup will be NULL going into + // SetNewPath. This is OK. + // + status = STATUS_SUCCESS; + } + } else { + status = STATUS_SUCCESS; + } + + if (status == STATUS_SUCCESS) { + + // + // Set the new path, using SuggestedPath. + // + InterlockedIncrement(&deviceInfo->BlockRemove); + ExReleaseSpinLockExclusive(&context->DsmContextLock, irql); + failGroup = DsmpSetNewPath(context, + deviceInfo); + irql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); + InterlockedDecrement(&deviceInfo->BlockRemove); + + // + // If we were able to make the suggested path active, that should be used. + // + for (i = 0, status = STATUS_UNSUCCESSFUL; i < DsmIds->Count && !NT_SUCCESS(status); i++) { + + deviceInfo = DsmIds->IdList[i]; + + if (deviceInfo->FailGroup == failGroup) { + + if (deviceInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { + + InterlockedExchangePointer(&(group->PathToBeUsed), (PVOID)failGroup); + status = STATUS_SUCCESS; + } + } + } + } + + ExReleaseSpinLockExclusive(&(context->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmMoveDevice (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmRemovePending( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId + ) +/*++ + +Routine Description: + + This routine indicates that the device represented by DsmId will be + removed, so the deviceInfo is marked up to indicate the pending removal, + so that it won't be used. + +Arguments: + + DsmContext - Context value given to the multipath driver + during registration. + DsmId - Value referring to the failed device. + +Return Value: + + STATUS_SUCCESS + +--*/ + +{ + PDSM_CONTEXT dsmContext = DsmContext; + PDSM_DEVICE_INFO deviceInfo = DsmId; + KIRQL irql; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmRemovePending (DevInfo %p): Entering function.\n", + DsmId)); + + // + // DsmpSetNewPath then finds the next available device. This is basically a + // fail-over for just this device. + // + InterlockedIncrement(&deviceInfo->BlockRemove); + DsmpSetNewPath(DsmContext, deviceInfo); + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + InterlockedDecrement(&deviceInfo->BlockRemove); + + if (!(DsmpIsDeviceFailedState(deviceInfo->State))) { + + deviceInfo->LastKnownGoodState = deviceInfo->State; + } + + // + // Mark the device as being unavailable since remove will be sent shortly. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_REMOVE_PENDING; + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmRemovePending (DevInfo %p): Exiting function.\n", + DsmId)); + + return STATUS_SUCCESS; +} + +NTSTATUS +DsmRemoveDevice( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PVOID PathId + ) +/*++ + +Routine Description: + + The device is gone and the port pdo has been removed. This routine will + update the internal structures and free any allocations. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + DsmId - Value referring to the failed device. + PathId - The path on which the Device lives. + +Return Value: + + STATUS_SUCCESS + +--*/ + +{ + PDSM_CONTEXT dsmContext = DsmContext; + PDSM_DEVICE_INFO deviceInfo = DsmId; + KIRQL irql; + PDSM_FAILOVER_GROUP failGroup = deviceInfo->FailGroup; + PDSM_GROUP_ENTRY group = deviceInfo->Group; + LONG block; + + UNREFERENCED_PARAMETER(PathId); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmRemoveDevice (DevInfo %p): Entering function.\n", + DsmId)); + + do { + + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + block = deviceInfo->BlockRemove; + NT_ASSERT(block >= 0); + + if (block) { + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + KeStallExecutionProcessor(10000); + } + + } while (block); + + if (!(DsmpIsDeviceFailedState(deviceInfo->State))) { + + deviceInfo->LastKnownGoodState = deviceInfo->State; + } + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = DSM_DEV_REMOVED; + + // + // Decrement the reference count for this device's controller entry and + // delete the entry if its reference count is now zero. + // + if (deviceInfo->Controller) { + + if (InterlockedDecrement((LONG volatile*)&(deviceInfo->Controller->RefCount)) == 0) { + + RemoveEntryList(&(deviceInfo->Controller->ListEntry)); + DsmpFreeControllerEntry(dsmContext, deviceInfo->Controller); + deviceInfo->Controller = NULL; + InterlockedDecrement((LONG volatile*)&(dsmContext->NumberControllers)); + } + } + + // + // Ensure that the device has been fully initialized before trying to + // remove it from the FOG. If SetDeviceInfo has yet to be invoked, there + // will yet to be an association set. + // + if (failGroup) { + + // + // Remove its entry from the Fail-Over Group. + // + DsmpRemoveDeviceFailGroup(DsmContext, failGroup, deviceInfo, FALSE); + } + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + + // + // Remove it from it's multi-path group. This has the side-effect + // of cleaning up the Group if the number of devices goes to zero. + // + DsmpRemoveDeviceEntry(DsmContext, group, deviceInfo); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmRemoveDevice (DevInfo %p): Exiting function.\n", + DsmId)); + + return STATUS_SUCCESS; +} + + +NTSTATUS +DsmRemovePath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PVOID PathId + ) +/*++ + +Routine Description: + + This routine indicates that the path is no longer valid, and that it should + be removed. Internal counts will be updated and any allocations associated + with this path freed. + +Arguments: + + DsmContext - Context value given to the multipath driver during registration. + PathId - The path to remove. + +Return Value: + + NTSTATUS of the operation. + +--*/ + +{ + PDSM_FAILOVER_GROUP failGroup; + KIRQL irql; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmRemovePath (PathId %p): Entering function.\n", + PathId)); + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + failGroup = DsmpFindFOGroup(DsmContext, PathId); + + if (failGroup) { + + // + // The claim is that a path won't be removed, until all + // the devices on it are. + // + if (failGroup->Count == 0) { + + // + // Yank it from the list. + // + RemoveEntryList(&failGroup->ListEntry); + InterlockedDecrement((LONG volatile*)&DsmContext->NumberFOGroups); + + // + // Move this over to the stale FOG list if there are inflight requests. + // Otherwise free the allocation. + // + if (InterlockedCompareExchange(&failGroup->NumberOfRequestsInFlight, 0, 0) > 0) { + + failGroup->State = DSM_FG_PENDING_REMOVE; + InsertTailList(&DsmContext->StaleFailGroupList, &failGroup->ListEntry); + InterlockedIncrement((LONG volatile*)&DsmContext->NumberStaleFOGroups); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmRemovePath (PathId %p): Outstanding requests %d. Moving FOGroup %p with path %p to stale path list.\n", + PathId, + failGroup->NumberOfRequestsInFlight, + failGroup, + failGroup->PathId)); + } else { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmRemovePath (PathId %p): Removing FOGroup %p with path %p. Count of FOGroups %d.\n", + PathId, + failGroup, + failGroup->PathId, + DsmContext->NumberFOGroups)); + + // + // Free the zombie group list and then the failover group. + // + DsmpFreeZombieGroupList(failGroup); + DsmpFreePool(failGroup); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmRemovePath (PathId %p): Count %d. Not removing FOGroup %p.\n", + PathId, + failGroup->Count, + failGroup)); + + // + // Should never be here. + // + NT_ASSERT(failGroup->Count == 0); + } + } else { + + // + // It's already been removed. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmRemovePath (PathId %p): Did not find the FO group.\n", + PathId)); + + NT_ASSERT(failGroup); + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmRemovePath (PathId %p): Exiting function.\n", + PathId)); + + return STATUS_SUCCESS; +} + + +PVOID +DsmLBGetPath( + _In_ IN PVOID DsmContext, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PDSM_IDS DsmList, + _In_ IN PVOID CurrentPath, + _Out_ OUT NTSTATUS *Status + ) +/*++ + +Routine Description: + + This routine is used by mpio to handle load-balancing. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + Srb - The current read/write Srb. + DsmList - List of our DSM IDs. + CurrentPath - The last path that was returned for this multi-path group. + Status - Storage to place NTSTATUS of the call. + +Return Value: + + The path ID to which the request should be sent. + +--*/ + +{ + PDSM_CONTEXT dsmContext = DsmContext; + PDSM_DEVICE_INFO deviceInfo; + PDSM_GROUP_ENTRY group; + PDSM_FAILOVER_GROUP failGroup = NULL; + PVOID newPath = NULL; + PDSM_FAILOVER_GROUP oldFailGroup = NULL; + PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY failPathDevInfoEntry = NULL; + PCDB cdb = NULL; + UCHAR opCode = 0xFF; + BOOLEAN lockInExclusiveMode = FALSE; + ULONG SpecialHandlingFlag = 0; + + + if (Srb) { + cdb = SrbGetCdb(Srb); + if (cdb) { + opCode = cdb->AsByte[0]; + + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmLBGetPath (DsmIds %p): Entering function.\n", + DsmList)); + + // + // Up-front checking to minimally validate the list of + // DsmId's being passed in. + // + NT_ASSERT(DsmList->Count && DsmList->IdList[0]); + if (!(DsmList->Count && DsmList->IdList[0])) { + + *Status = STATUS_NO_SUCH_DEVICE; + goto __Exit_DsmLBGetPath; + } + + deviceInfo = DsmList->IdList[0]; + group = deviceInfo->Group; + + + failGroup = DsmpGetPath(dsmContext, DsmList, Srb, SpecialHandlingFlag); + + // + // If there wasn't a single active/optimized path found, check to see if + // there is an STPG in progress that may be making a path A/O. + // + if (!failGroup) { + + // + // Take the last path used. + // + oldFailGroup = DsmpFindFOGroup(dsmContext, CurrentPath); + + // + // Find the devInfo corresponding to this path. + // + deviceInfo = DsmpFindDevInfoFromGroupAndFOGroup(dsmContext, + group, + oldFailGroup); + + if (deviceInfo) { + + // + // Check if there is an alternate devInfo to be used temporarily + // for this deviceInfo + // + failPathDevInfoEntry = DsmpFindFailPathDevInfoEntry(dsmContext, + group, + deviceInfo); + + if (failPathDevInfoEntry) { + + // + // Use the alternate devInfo for now temporarily while the STPG + // that was previously sent (asynchronously) works on making the + // appropriate path active/optimized. + // + failGroup = (failPathDevInfoEntry->TempDeviceInfo)->FailGroup; + } + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmLBGetPath (DsmIds %p): Couldn't find FOG but FO in progress, so returning devInfo %p (FOG %p path %p).\n", + DsmList, + deviceInfo, + deviceInfo->FailGroup, + deviceInfo->FailGroup->PathId)); + } else { + + // + // Check if there is an RTPG in progress, if yes, return some path + // for the IO to be sent down. + // + if (InterlockedCompareExchange((LONG volatile*)&group->InFlightRTPG, 0, 0)) { + + BOOLEAN sendTPG = FALSE; + deviceInfo = DsmpFindStandbyPathToActivateALUA(group, &sendTPG, SpecialHandlingFlag); + + if (deviceInfo) { + + failGroup = deviceInfo->FailGroup; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmLBGetPath (DsmIds %p): Couldn't find FOG but RTPG inflight, so returning devInfo %p (FOG %p path %p).\n", + DsmList, + deviceInfo, + deviceInfo->FailGroup, + deviceInfo->FailGroup->PathId)); + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmLBGetPath (DsmIds %p): Couldn't find FOG but RTPG inflight, even then couldn't find alternative devInfo.\n", + DsmList)); + } + } + } + } + + if (failGroup) { + + newPath = failGroup->PathId; + *Status = STATUS_SUCCESS; + + // + // If this is a retried request, our SetCompletion would have been bypassed, + // and our completion routine won't yet get called, so update the old and + // the new paths' stats. + // + if (Srb && DsmIsReadWrite(opCode)) { + + PDSM_FAILOVER_GROUP oldPath; + PIRP irp = (PIRP)SrbGetOriginalRequest(Srb); + PIO_STACK_LOCATION irpStack; + + // + // This indicates that the request is being retried. So we need to: + // 1. Update old path's and new path's request count + // 2. If the old path was supposed to be removed, check if there are + // no more requests are outstanding, and if yes, remove the path + // + + irpStack = IoGetCurrentIrpStackLocation(irp); + oldPath = irpStack->Parameters.Others.Argument3; + + if (oldPath) { + + NT_ASSERT(oldPath->FailOverSig == DSM_FOG_SIG); + + if (DsmpDecrementCounters(oldPath, Srb)) { + + // + // If there are no requests on a path that is supposed to be removed, + // remove it now. + // + if (oldPath->State == DSM_FG_PENDING_REMOVE) { + KIRQL irql; + + NT_ASSERT(oldPath->Count == 0); + + // + // We need to acquire the DsmContextLock in Exclusive mode since + // we are removing a path from the Failover Group list. + // + irql = ExAcquireSpinLockExclusive(&(dsmContext->DsmContextLock)); + lockInExclusiveMode = TRUE; + + RemoveEntryList(&oldPath->ListEntry); + InterlockedDecrement((LONG volatile*)&dsmContext->NumberStaleFOGroups); + + ExReleaseSpinLockExclusive(&(dsmContext->DsmContextLock), irql); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmLBGetPath (DsmIds %p): Removing FOGroup %p with path %p.\n", + DsmList, + oldPath, + oldPath->PathId)); + + DsmpFreePool(oldPath); + } + } + + irpStack->Parameters.Others.Argument3 = failGroup; + + DsmpIncrementCounters(failGroup, Srb); + } + } + + } else { + + *Status = STATUS_NO_SUCH_DEVICE; + + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmLBGetPath (DsmIds %p): Failed to get FO group in LBGetPath.\n", + DsmList)); + + + } + +__Exit_DsmLBGetPath: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmLBGetPath (DsmIds %p): Exiting function returning path %p for request %p.\n", + DsmList, + newPath, + Srb)); + + return newPath; +} + +_Success_(return == DSM_PATH_SET) +ULONG +DsmCategorizeRequest( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PVOID CurrentPath, + _Outptr_result_maybenull_ OUT PVOID *PathId, + _Out_ OUT NTSTATUS *Status + ) +/*++ + +Routine Description: + + This routine is called when a request is received other than a read/write. + It will determine the best path to which the request is to be sent. + + In order to support clusters, reserve and release need to be handled + via SrbControl. + +Arguments: + + DsmContext - Context value given to the multipath driver during + registration. + DsmIds - List of our DSM IDs. + Irp - The Irp containing Srb. + Srb - The current non-read/write Srb. + CurrentPath - The last path that was returned for this multi-path group. + PathId - Placeholder for the PathID + Status - Storage to place NTSTATUS of the call. + +Return Value: + + DSM_PATH_SET - Indicates PathID is valid. + DSM_ERROR - Couldn't get a path. + +--*/ +{ + ULONG dsmStatus; + NTSTATUS status = STATUS_UNSUCCESSFUL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmCategorizeRequest (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // Determine whether this is a special-case request. + // + if (DsmpReservationCommand(Irp, Srb)) { + + dsmStatus = DSM_WILL_HANDLE; + goto __Exit_DsmCategorizeRequest; + } + + + // + // If this is a mpio pass through or a mpio pass through direct request, + // pick the path that corresponds to the pathId specified. + // + if (DsmpMpioPassThroughPathCommand(Irp)) { + + *PathId = DsmpGetPathIdFromPassThroughPath(DsmContext, + DsmIds, + Irp, + &status); + } else { + + // + // For requests other than reservation-handling and pass through, punt + // it back to the bus-driver. Need to get a path for the request first, + // so call the Load-Balance function. + // + *PathId = DsmLBGetPath(DsmContext, + Srb, + DsmIds, + CurrentPath, + &status); + } + + if (NT_SUCCESS(status)) { + + if (!*PathId) { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmCategorizeRequest (DsmIds %p): DSM_PATH_SET didn't return a path.\n", + DsmIds)); + } + + // + // Indicate that the path is updated, and mpctl should handle the request. + // + dsmStatus = DSM_PATH_SET; + + } else { + + // + // Indicate the error back to mpctl. + // + dsmStatus = DSM_ERROR; + + // + // Mark-up the Srb to show that a failure has occurred. + // This value is really only for this DSM to know what to do + // in the InterpretError routine - Fatal Error. + // It could be something more meaningful. + // + if (Srb) { + Srb->SrbStatus = SRB_STATUS_NO_DEVICE; + } + + *PathId = NULL; + } + + // + // Pass back status info to mpctl. + // + *Status = status; + +__Exit_DsmCategorizeRequest: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmCategorizeRequest (DsmIds %p): Exiting function with categorization %x.\n", + DsmIds, + dsmStatus)); + + return dsmStatus; +} + + +NTSTATUS +DsmBroadcastRequest( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ) +/*++ + +Routine Description: + + This routine is called when the DSM has indicated that Srb should be + sent to the device down all paths. The DSM will update IoStatus + information and status, but not complete the request. + + Currently MSDSM doesn't have a need for this. + +Arguments: + + DsmIds - The collection of DSM IDs that pertain to the MPDisk. + Irp - Irp containing SRB. + Srb - Scsi request block + Event - DSM sets this once all sub-requests have completed and + the original request's IoStatus has been setup. + +Return Value: + + NTSTATUS of the operation. + +--*/ +{ + NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; + + UNREFERENCED_PARAMETER(DsmContext); + UNREFERENCED_PARAMETER(Srb); + UNREFERENCED_PARAMETER(Irp); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmBroadcastRequest (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // Currently nothing is handled via Broadcast. Just set the event to + // free up the request handling in the bus-driver. + // + NT_ASSERT(NT_SUCCESS(status)); + KeSetEvent(Event, 0, FALSE); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmBroadcastReqeust (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmSrbDeviceControl( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ) +/*++ + +Routine Description: + + This routine is called when the DSM has indicated that it wants to handle + it internally (via returning DSM_WILL_HANDLE in CategorizeRequest). + + It should set IoStatus (Status and Information) and the Event, but not + complete the request. + +Arguments: + + DsmContext - The DSM's context + DsmIds - The collection of DSM IDs that pertain to the MPDISK. + Irp - Irp containing SRB. + Srb - Scsi request block + Event - Event to be set when the DSM is finished if DsmHandled is TRUE + +Return Value: + + NTSTATUS of the request. + +--*/ +{ + PDSM_CONTEXT dsmContext = DsmContext; + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS status; + UCHAR opCode = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmSrbDeviceControl (DsmIds %p): Entering function.\n", + DsmIds)); + + if (!DsmIds || !DsmIds->Count) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_IOCTL, + "DsmSrbDeviceControl (DsmIds %p): No DsmIds passed in.\n", + DsmIds)); + + status = STATUS_NO_SUCH_DEVICE; + goto __Exit_DsmSrbDeviceControl; + } + + if (irpStack->MajorFunction == IRP_MJ_SCSI) { + + // + // Determine the operation. + // + PCDB cdb = SrbGetCdb(Srb); + if (cdb) { + opCode = cdb->AsByte[0]; + } + + if (opCode == SCSIOP_PERSISTENT_RESERVE_OUT) { + + status = DsmpPersistentReserveOut(dsmContext, + DsmIds, + Irp, + Srb, + Event); + + } else if (opCode == SCSIOP_PERSISTENT_RESERVE_IN) { + + status = DsmpPersistentReserveIn(dsmContext, + DsmIds, + Irp, + Srb, + Event); + + } else { + + // + // Should never be here. + // + DSM_ASSERT(FALSE); + status = STATUS_INVALID_DEVICE_REQUEST; + } + } else { + // + // Should never be here. + // + DSM_ASSERT(irpStack->MajorFunction == IRP_MJ_SCSI); + status = STATUS_INVALID_DEVICE_REQUEST; + } + +__Exit_DsmSrbDeviceControl: + if (status != STATUS_PENDING) { + + // + // Set-up the Irp status for mpio's completion of the request. + // If it was IRP_MJ_SCSI, one of the helper routines set Srb->SrbStatus + // already. + // + if ((irpStack->MajorFunction == IRP_MJ_SCSI) && + (Srb != NULL) && + (Srb->SrbStatus == SRB_STATUS_PENDING)) { + + Srb->SrbStatus = SRB_STATUS_ERROR; + } + + Irp->IoStatus.Status = status; + + // + // Set the event to free up the request handling in the bus-driver. + // + KeSetEvent(Event, 0, FALSE); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmSrbDeviceControl (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +VOID +DsmSetCompletion( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _Inout_ IN OUT PDSM_COMPLETION_INFO DsmCompletion + ) +/*++ + +Routine Description: + + This routine is called before the actual submission of a request, + but after the categorisation of the I/O. This will be called only + for those requests not handled by the DSM directly: + Read/Write + Other requests not handled by SrbControl or Broadcast + +Arguments: + + DsmContext - The DSM's context. + DsmId - Identifer that was indicated when the request was + categorized (or be LBGetPath) + Irp - Irp containing Srb. + Srb - The request + DsmCompletion - Completion info structure to be filled out by DSM. + +Return Value: + + None + +--*/ +{ + PDSM_CONTEXT dsmContext = DsmContext; + PDSM_DEVICE_INFO deviceInfo = DsmId; + PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); + PDSM_FAILOVER_GROUP failGroup = deviceInfo->FailGroup; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmSetCompletion (DevInfo %p): Entering function.\n", + DsmId)); + + // + // Save off the path that was selected to service this request in Argument3. + // + irpStack->Parameters.Others.Argument3 = failGroup; + + DsmpIncrementCounters(failGroup, Srb); + + if (!dsmContext->DisableStatsGathering) { + + // + // Indicate one more request on this device down this path. + // + InterlockedIncrement(&deviceInfo->NumberOfRequestsInProgress); + } + + // + // Update the passed-in struct with our routine and context values. + // + DsmCompletion->DsmCompletionRoutine = DsmpRequestComplete; + DsmCompletion->DsmContext = DsmContext; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmSetCompletion (DevInfo %p): Exiting function.\n", + DsmId)); + + return; +} + + +ULONG +DsmInterpretError( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _Inout_ IN OUT NTSTATUS *Status, + _Out_ OUT PBOOLEAN Retry, + _Out_ OUT PLONG RetryInterval, + ... + ) +/*++ + +Routine Description: + + This routine is invoked by MPIO if Status is other than SUCCESS. + A few NTSTATUS and SRB_STATUS values indicate a fatal error. + Also checked are unit attentions, for which a retry is requested. + +Arguments: + + DsmContext - The DSM's context. + DsmId - Identifers returned from DMS_INQUIRE_DRIVER. + Srb - The Srb with an error. + Status - NTSTATUS of the operation. Can be updated. + Retry - Allows the DSM to indicate whether to retry the IO. + RetryInterval - Lets DSM specify (in seconds) when this specific I/O + should be retried. Use MAXLONG to use the default + retry interval. Use zero to retry immediately. + +Return Value: + + DSM_FATAL_ERROR indicates a fatal error. + +--*/ +{ + // + // The requests that will be encountered can be divided into four categories: + // 1. The request that has failed. + // 2. Subsequent requests that were sent down the failing path that will + // complete with failure. + // 3. Requests that were already submitted to LBGetPath() just before InterpretError() + // was called for the failed request (but have yet to have the LB policy + // algo run). + // 4. Requests that come into the Dispatch() routine after the failed request + // has been processed by InterpretError(). + // + // For the failed request: + // ======================= + // 1. Find a standby path to make active/optimized. + // 2. Send STPG asynchronously as a scsi pass through via IRP_MJ_SCSI (this + // way it can be sent at DISPATCH_IRQL) after setting a completion routine. + // 3. Save the devInfo corresponding to the standby path for the failing devInfo. + // 4. Return FATAL to MPIO so that new IO are queued. + // 5. In the completion routine, update the new states for the devInfos. Then + // clear the saved (previously) standby devInfo for the failing devInfo. + // + // For the subsequent request that will fail (since it was sent on the failing path): + // ================================================================================== + // 1. If a standby devInfo has been saved off, it indicates that an STPG was + // already sent, so no need to send another one. + // 2. Return FATAL to MPIO so that this request gets queued. + // + // For the requests that were already submitted to LBGetPath() during this time: + // ============================================================================= + // 1. If there is no active path, check if a standby devInfo has been saved + // away. If it has, return this path. Such requests will fail with check + // condition saying path used is in standby. + // 2. In InterpretError() retry (since the error indicates that request + // completed before STPG completed) without decrementing the remaining + // retries count. + // + // For new requests that come into Dispatch() after above processing: + // ================================================================== + // We don't need to worry about such requests, since MPIO will queue them + // automatically. + // + + PDSM_DEVICE_INFO deviceInfo = DsmId; + ULONG errorMask = 0; + PVOID senseData = SrbGetSenseInfoBuffer(Srb); + UCHAR senseDataLength = SrbGetSenseInfoBufferLength(Srb); + BOOLEAN failover = FALSE; + BOOLEAN retry = FALSE; + BOOLEAN handled = FALSE; + BOOLEAN sendTPG = FALSE; + BOOLEAN tpgException = FALSE; + BOOLEAN devInfoException = FALSE; + PCDB cdb = SrbGetCdb(Srb); + UCHAR opCode = 0; + UCHAR scsiStatus = SrbGetScsiStatus(Srb); + BOOLEAN validSense = FALSE; + UCHAR senseKey = 0; + UCHAR addSenseCode = 0; + UCHAR addSenseCodeQualifier = 0; + + if (cdb) { + opCode = cdb->AsByte[0]; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Entering function.\n", + DsmId)); + + *RetryInterval = MAXLONG; + + if ((scsiStatus == SCSISTAT_RESERVATION_CONFLICT) || + (*Status == STATUS_DEVICE_BUSY)) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Srb %p. Either busy or res. conflict (%x %x).\n", + DsmId, + Srb, + scsiStatus, + *Status)); + } + + // + // Go ahead and get the sense data if it's valid. + // + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { + + NT_ASSERT(senseData != NULL); + + validSense = ScsiGetSenseKeyAndCodes(senseData, + senseDataLength, + SCSI_SENSE_OPTIONS_FIXED_FORMAT_IF_UNKNOWN_FORMAT_INDICATED, + &senseKey, + &addSenseCode, + &addSenseCodeQualifier); + } + + // + // Sense data relating to logical block provisioning should be failed + // immediately back to the class layer for handling. + // + if (validSense) { + if (senseKey == SCSI_SENSE_NOT_READY && + addSenseCode == SCSI_ADSENSE_LUN_NOT_READY && + addSenseCodeQualifier == SCSI_SENSEQ_SPACE_ALLOC_IN_PROGRESS) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Temporary resource exhaustion. Fail Srb %p.\n", + DsmId, + Srb)); + + handled = TRUE; + + } else if (senseKey == SCSI_SENSE_DATA_PROTECT && + addSenseCode == SCSI_ADSENSE_WRITE_PROTECT && + addSenseCodeQualifier == SCSI_SENSEQ_SPACE_ALLOC_FAILED_WRITE_PROTECT) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Permanent resource exhaustion. Fail Srb %p.\n", + DsmId, + Srb)); + + handled = TRUE; + + } else if (senseKey == SCSI_SENSE_UNIT_ATTENTION && + addSenseCode == SCSI_ADSENSE_LB_PROVISIONING && + addSenseCodeQualifier == SCSI_SENSEQ_SOFT_THRESHOLD_REACHED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Soft threshold reached. Fail Srb %p.\n", + DsmId, + Srb)); + + handled = TRUE; + + } else if (senseKey == SCSI_SENSE_UNIT_ATTENTION && + addSenseCode == SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED && + addSenseCodeQualifier == SCSI_SENSEQ_INQUIRY_DATA_CHANGED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Inquiry data changed. Fail Srb %p.\n", + DsmId, + Srb)); + + handled = TRUE; + } else if (senseKey == SCSI_SENSE_UNIT_ATTENTION && + addSenseCode == SCSI_ADSENSE_PARAMETERS_CHANGED && + addSenseCodeQualifier == SCSI_SENSEQ_CAPACITY_DATA_CHANGED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Capacity data changed. Fail Srb %p.\n", + DsmId, + Srb)); + + handled = TRUE; + } + } + + if (handled) { + return errorMask; + } + + // + // Check the NT Status first. + // Several are clearly failover conditions. + // + switch (*Status) { + case STATUS_DEVICE_NOT_CONNECTED: + case STATUS_DEVICE_DOES_NOT_EXIST: + case STATUS_NO_SUCH_DEVICE: + case STATUS_DELETE_PENDING: { + + // + // The port pdo has either been removed or is + // very broken. A fail-over is necessary. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Will initiate fail over. Status %x. Opcode %x.\n", + DsmId, + *Status, + opCode)); + + handled = TRUE; + failover = TRUE; + break; + } + + case STATUS_IO_DEVICE_ERROR: { + + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) { + + if (validSense) { + + // + // See if it's a unit attention. + // + if (senseKey == SCSI_SENSE_UNIT_ATTENTION) { + + switch (addSenseCode) { + + case SCSI_ADSENSE_PARAMETERS_CHANGED: { + + switch (addSenseCodeQualifier) { + + case SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_CHANGED: + case SPC3_SCSI_SENSEQ_IMPLICIT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): TPG states have changed. Requesting retry on Srb %p. Will send asyn RTPG.\n", + DsmId, + Srb)); + + // + // Retry but after sending RTPG, which will update the path states. + // + sendTPG = TRUE; + retry = TRUE; + handled = TRUE; + errorMask = DSM_RETRY_DONT_DECREMENT; + + if (addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_CHANGED) { + + // + // Worth retrying on the same path. + // + devInfoException = TRUE; + NT_ASSERT(!tpgException); + } + + break; + } + + + case SPC3_SCSI_SENSEQ_RESERVATIONS_RELEASED: { + + // + // This request needs to be immediately retried down the same path. + // + retry = TRUE; + *RetryInterval = 0; + handled = TRUE; + InterlockedExchangePointer(&(deviceInfo->Group->PathToBeUsed), deviceInfo->FailGroup); + break; + } + + case SPC3_SCSI_SENSEQ_MODE_PARAMETERS_CHANGED: + case SPC3_SCSI_SENSEQ_RESERVATIONS_PREEMPTED: + case SPC3_SCSI_SENSEQ_REGISTRATIONS_PREEMPTED: + case SPC3_SCSI_SENSEQ_CAPACITY_DATA_HAS_CHANGED: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Failing request. STATUS_IO_DEVICE_ERROR (params changed). SrbStatus (%x) Scsi (%x) AddQual (%u).\n", + DsmId, + Srb->SrbStatus, + scsiStatus, + addSenseCodeQualifier)); + + // + // Just fail these back. + // + handled = TRUE; + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): UNIT_ATTENTION for params changed. ASCQ %x. Asking for retry on Srb %p.\n", + DsmId, + addSenseCodeQualifier, + Srb)); + + // + // Indicate that a retry is necessary. + // + retry = TRUE; + handled = TRUE; + + break; + } + } + + break; + } + + + case SPC3_SCSI_ADSENSE_COMMANDS_CLEARED_BY_ANOTHER_INITIATOR: { + + if (addSenseCodeQualifier == 0x00) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): UNIT_ATTENTION (commands cleared by another initiator). Fail back to upper level. Srb %p.\n", + DsmId, + Srb)); + + // + // Commands cleared by another Initiator + // + handled = TRUE; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): UNIT_ATTENTION (commands cleared by another initiator). ASCQ %x. Asking for retry on Srb %p.\n", + DsmId, + addSenseCodeQualifier, + Srb)); + + // + // Indicate that a retry is necessary. + // + retry = TRUE; + handled = TRUE; + } + + + break; + } + + case SCSI_ADSENSE_OPERATING_CONDITIONS_CHANGED: { + + if (addSenseCodeQualifier == SCSI_SENSEQ_VOLUME_SET_MODIFIED || + addSenseCodeQualifier == SCSI_SENSEQ_REPORTED_LUNS_DATA_CHANGED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): VolumeSet/LunsData changed. Fail Srb %p.\n", + DsmId, + Srb)); + + // + // Fail back to upper layers. + // + handled = TRUE; + + break; + + } else { + + // + // Fall through to default case (ie. retry the request) + // + } + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): UNIT_ATTENTION. ASC %x, ASCQ %x. Asking for retry on Srb %p.\n", + DsmId, + addSenseCode, + addSenseCodeQualifier, + Srb)); + + // + // Indicate that a retry is necessary. + // + retry = TRUE; + handled = TRUE; + + break; + } + } + } else if (senseKey == SCSI_SENSE_NOT_READY) { + + if (addSenseCode == SCSI_ADSENSE_LUN_NOT_READY) { + + if (scsiStatus == SCSISTAT_CHECK_CONDITION) { + + switch (addSenseCodeQualifier) { + + // + // See if failure is due to device's current TPG state. + // + // If the failure is PORT_IN_STANDBY_STATE, we leave DSM_RETRY_DONT_DECREMENT unset if no active path exists, + // because otherwise MPIO will not be able to find a better path, and it will get into an infinite loop + // of trying and failing the command on a Standby path. See WCxeTfs:89150 + // + case SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION: + case SPC3_SCSI_SENSEQ_TARGET_PORT_IN_UNAVAILABLE_STATE: + + errorMask = DSM_RETRY_DONT_DECREMENT; + + case SPC3_SCSI_SENSEQ_TARGET_PORT_IN_STANDBY_STATE: + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): TPG-transition/TPG-SB/TPG-UA. ASCQ %x. Will send down async RTPG. Asking for retry on Srb %p.\n", + DsmId, + addSenseCodeQualifier, + Srb)); + + // + // Indicate that a retry is necessary but without decrementing the remaining + // retries count. However, we may need to send down an STPG/RTPG also. + // And we must set PTBU to a path that is in a different TPG. + // + sendTPG = TRUE; + tpgException = TRUE; + NT_ASSERT(!devInfoException); + retry = TRUE; + handled = TRUE; + + if ((addSenseCodeQualifier == SPC3_SCSI_SENSEQ_TARGET_PORT_IN_STANDBY_STATE) && + DsmIsReadWrite(opCode)) { + + PDSM_CONTEXT context = (PDSM_CONTEXT) deviceInfo->DsmContext; + KIRQL oldIrql = ExAcquireSpinLockExclusive(&(context->DsmContextLock)); + BOOLEAN activePathExists = ( NULL != DsmpGetAnyActivePath(deviceInfo->Group, FALSE, NULL, 0) ); + ExReleaseSpinLockExclusive(&(context->DsmContextLock), oldIrql); + + if (activePathExists) { + errorMask = DSM_RETRY_DONT_DECREMENT; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Not decrementing error counter, as an active path exists in group %p and opcode %x is r/w\n", + DsmId, + deviceInfo->Group, + opCode)); + } + } + + break; + + case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Manual intervention required. Asking for retry on Srb %p.\n", + DsmId, + Srb)); + + // + // This may be caused by NDU of controller firmware. It does not + // necessarily indicate that the device won't be ready via other path(s). + // Worth retrying instead of immediately failing back. + // + retry = TRUE; + handled = TRUE; + + break; + } + } + } + } + } + + } else if (Srb->SrbStatus == SRB_STATUS_BUS_RESET) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): BUS_RESET. Failing back Srb %p.\n", + DsmId, + Srb)); + + // + // Upper layers will retry in this case. If we retry here it will + // have a multiplicative effect which may result in a very long + // IO completion time if the device persistently times out. + // + retry = FALSE; + handled = TRUE; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Failing request. STATUS_IO_DEVICE_ERROR. SrbStatus (%x) ScsiStatus (%x).\n", + DsmId, + Srb->SrbStatus, + scsiStatus)); + } + + break; + } + + case STATUS_BUFFER_OVERFLOW: { + + if (DsmIsReadWrite(opCode)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): BUFFER_OVERFLOW: Retry.\n", + DsmId)); + + // + // Retry these, as this condition might indicate a torn write. + // + retry = TRUE; + handled = TRUE; + } + + break; + } + + case STATUS_DEVICE_BUSY: { + + // + // See if it's a check condition for TPG states in transition. + // + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && + scsiStatus == SCSISTAT_CHECK_CONDITION) { + + if (validSense) { + + if (senseKey == SCSI_SENSE_NOT_READY && + addSenseCode == SCSI_ADSENSE_LUN_NOT_READY && + addSenseCodeQualifier == SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): TPG transition. Will send down async RTPG. Asking for retry on Srb %p.\n", + DsmId, + Srb)); + + // + // Indicate that a retry is necessary but without decrementing the remaining + // retries count. However, we may need to send down an STPG/RTPG also. + // And we must set PTBU to a path that is in a different TPG. + // + sendTPG = TRUE; + tpgException = TRUE; + NT_ASSERT(!devInfoException); + retry = TRUE; + handled = TRUE; + errorMask = DSM_RETRY_DONT_DECREMENT; + } + + } + } + + break; + } + + case STATUS_DEVICE_NOT_READY: { + + if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID && + scsiStatus == SCSISTAT_CHECK_CONDITION) { + + if (validSense) { + if (senseKey == SCSI_SENSE_NOT_READY && + addSenseCode == SCSI_ADSENSE_LUN_NOT_READY) { + + switch (addSenseCodeQualifier) { + + case SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Manual intervention required. Asking for retry on Srb %p.\n", + DsmId, + Srb)); + + // + // This may be caused by NDU of controller firmware. It does not + // necessarily indicate that the device won't be ready via other path(s). + // Worth retrying instead of immediately failing back. + // + retry = TRUE; + handled = TRUE; + + break; + } + + case SCSI_SENSEQ_SPACE_ALLOC_IN_PROGRESS: { + // + // This indicates a logical block provisioning temporary resource exhaustion + // condition and therefore we must allow the class layer to handle it. + // + retry = FALSE; + handled = TRUE; + + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Unhandled AddQual %x.\n", + DsmId, + addSenseCodeQualifier)); + + break; + } + } + } + } + } + } + + + default: { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Unhandled status code %x.\n", + DsmId, + *Status)); + + break; + } + } + + if (!handled) { + + // + // The NTSTATUS didn't indicate a fail-over condition, but + // check various srb status for failover-class error. + // + switch (Srb->SrbStatus) { + case SRB_STATUS_SELECTION_TIMEOUT: + case SRB_STATUS_INVALID_LUN: + case SRB_STATUS_INVALID_TARGET_ID: + case SRB_STATUS_NO_DEVICE: + case SRB_STATUS_NO_HBA: + case SRB_STATUS_INVALID_PATH_ID: { + + // + // All of these are fatal. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): SrbStatus 0x%x. Will initiate fail over.\n", + DsmId, + Srb->SrbStatus)); + + failover = TRUE; + break; + } + + + default: { + + if ((scsiStatus == SCSISTAT_CHECK_CONDITION) && + (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) { + + if (validSense) { + + switch (senseKey) { + + case SCSI_SENSE_NO_SENSE: { + + if (addSenseCode == SCSI_ADSENSE_NO_SENSE && + addSenseCodeQualifier == SCSI_SENSEQ_CAUSE_NOT_REPORTABLE) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): CheckCondition with no sense info. Will initiate fail over.\n", + DsmId)); + + // + // This could be a transient error generated + // in response to potentially a hardware fault. + // Worth trying another path. + // + failover = TRUE; + handled = TRUE; + } + + break; + } + + case SCSI_SENSE_ILLEGAL_REQUEST: { + + if (addSenseCode == SCSI_ADSENSE_INVALID_LUN) { + + if (addSenseCodeQualifier == 0x00) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Invalid LUN. Will initiate fail over.\n", + DsmId)); + + // + // LUN may still exist on other path(s). + // Worth a failover. + // + failover = TRUE; + handled = TRUE; + } + } + + break; + } + + case SCSI_SENSE_HARDWARE_ERROR: { + + if (addSenseCode == SPC3_SCSI_ADSENSE_LOGICAL_UNIT_COMMAND_FAILED) { + + if (addSenseCodeQualifier == SPC3_SCSI_SENSEQ_SET_TARGET_PORT_GROUPS_FAILED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): STPG failed. Will initiate fail over.\n", + DsmId)); + + // + // If an STPG failed, treat as FATAL and get another + // path set to A/O via another STPG. + // + failover = TRUE; + handled = TRUE; + } + } else if ((addSenseCode == SCSI_ADSENSE_LOGICAL_UNIT_ERROR && addSenseCodeQualifier == SCSI_SENSEQ_TIMEOUT_ON_LOGICAL_UNIT) || + (addSenseCode == SCSI_ADSENSE_DATA_TRANSFER_ERROR && addSenseCodeQualifier == SCSI_SENSEQ_INITIATOR_RESPONSE_TIMEOUT)) { + + // + // Could potentially indicate a dropped FC packet. Retry (along another + // path, based on the LB policy). + // + retry = TRUE; + handled = TRUE; + } + + break; + } + + default: { + + break; + } + } + } + } + + if (!handled) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Unhandled SRB Status 0x%x. Sense data %x|%x|%x.\n", + DsmId, + Srb->SrbStatus, + validSense ? senseKey : 0xFF, + validSense ? addSenseCode : 0xFF, + validSense ? addSenseCodeQualifier : 0xFF)); + } + + break; + } + } + } + + if (failover) { + ULONG SpecialHandlingFlag = 0; + + // + // If ALUA is supported, then it is possible that we may need to send + // down an STPG so build an IRP and fill in the SRB for STPG and send it down. + // + if (!DsmpIsSymmetricAccess(deviceInfo)) { + + DsmpSetLBForPathFailingALUA(DsmContext, deviceInfo, TRUE, SpecialHandlingFlag); + + } else { + + // + // If device doesn't support ALUA, we just need to update + // states without sending down any commands (STPG) + // + DsmpSetLBForPathFailing(DsmContext, deviceInfo, TRUE, SpecialHandlingFlag); + } + + errorMask = DSM_FATAL_ERROR; + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmInterpretError(DevInfo %p): Device changed to state %d\n", + deviceInfo, + deviceInfo->State)); + +#if DBG + { + ULONG inx; + PDSM_GROUP_ENTRY group = deviceInfo->Group; + PDSM_DEVICE_INFO tempDevInfo; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Device %p in group %p being marked as failed. NTStatus 0x%x.\n", + DsmId, + deviceInfo, + group, + *Status)); + + for (inx = 0; inx < group->NumberDevices; inx++) { + + tempDevInfo = group->DeviceList[inx]; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Device %p at %d. State %d.\n", + DsmId, + tempDevInfo, + inx, + tempDevInfo->State)); + } + } +#endif // DBG + } + + if (retry) { + + if (sendTPG) { + + // + // If ALUA is supported, send down STPG/RTPG as appropriate. + // + if (!DsmpIsSymmetricAccess(deviceInfo)) { + + DsmpSetPathForIoRetryALUA(DsmContext, deviceInfo, tpgException, devInfoException); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_RW, + "DsmInterpretError(DevInfo %p): SRB request %p will be retried. PTBU set to %p.\n", + deviceInfo, + Srb, + deviceInfo->Group->PathToBeUsed)); + } + } + } + + + *Retry = retry; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmInterpretError (DevInfo %p): Exiting function returning errorMask %x.\n", + DsmId, + errorMask)); + + return errorMask; +} + +BOOLEAN +DsmIsAddressTypeSupported( + _In_ IN PVOID DsmContext, + _In_ IN ULONG AddressType + ) +/*++ + +Routine Description: + + This routine is called when MPIO wants to know if the DSM supports a + particular storage address type. + + This routine must be provided for DSMs of DsmType6 or higher. + +Arguments: + + DsmContext - Context value passed to DsmInitialize() + AddressType - The storage address type being queried. + +Return Value: + + TRUE - If the DSM supports the given storage address type. + FALSE - If the DSM does not support the given storage address type. + +--*/ +{ + UNREFERENCED_PARAMETER(DsmContext); + + if (AddressType == STORAGE_ADDRESS_TYPE_BTL8) + { + return TRUE; + } + + return FALSE; +} + +NTSTATUS +DsmDeviceNotUsed( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId + ) +/*++ + +Routine Description: + + This routine indicates that the device represented by DsmId will not be + initialized completely by MPIO. + The DSM_ID list passed to other functions will no longer contain DsmId, + so internal structures should be updated accordingly. + + This routine must be provided for DSMs of DsmType6 or higher. + +Arguments: + + DsmContext - Context value given to the multipath driver during registration. + DsmId - Value referring to the uninitialized device. + +Return Value: + + NTSTATUS of the operation. + +--*/ +{ + PDSM_DEVICE_INFO deviceInfo = (PDSM_DEVICE_INFO)DsmId; + + DSM_ASSERT(deviceInfo->Group != NULL); + DSM_ASSERT(deviceInfo->Group->GroupSig == DSM_GROUP_SIG); + + // + // Undo anything we did to build up the device in DsmInquire(). + // + DsmRemoveDevice((PDSM_CONTEXT)DsmContext, DsmId, deviceInfo->FailGroup); + + return STATUS_SUCCESS; +} + +NTSTATUS +DsmUnload( + _In_ IN PVOID DsmContext + ) +/*++ + +Routine Description: + + This routine is called when the main module requires the DSM to be unloaded + (ie. prior to the main module unload). + +Arguments: + + DsmContext - Context value passed to DsmInitialize() + +Return Value: + + STATUS_SUCCESS; + +--*/ + +{ + PVOID tempAddress = DsmContext; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmUnload (DsmCtxt %p): Entering function.\n", + DsmContext)); + + DsmpFreeDSMResources((PDSM_CONTEXT) DsmContext); + + if (gMPIOControlObjectRefd) { + + ObDereferenceObject(gMPIOControlObject); + gMPIOControlObjectRefd = FALSE; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmUnload (DsmCtxt %p): Exiting function.\n", + tempAddress)); + + // + // Stop the tracing subsystem. + // + WPP_CLEANUP(gDsmDriverObject); + + return STATUS_SUCCESS; +} + diff --git a/tests/projects/windows/driver/wdm/msdsm/msdsm.h b/tests/projects/windows/driver/wdm/msdsm/msdsm.h new file mode 100644 index 000000000..e1ddeb52d --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/msdsm.h @@ -0,0 +1,1403 @@ +/*++ + +Copyright (C) 2004-2010 Microsoft Corporation + +Module Name: + + msdsm.h + +Abstract: + + Header for the Microsoft Device Specific Module (DSM). + +Environment: + + kernel mode only + +Notes: + +--*/ + +#ifndef _MSDSM_H_ +#define _MSDSM_H_ + +// +// Maximum number of paths per device supported by the DSM. +// This is a limit currently set by MPIO itself and needs to be updated if MPIO +// supports more paths-per-device in the future. +// +#define DSM_MAX_PATHS 32 + +// +// MPIO control object's well known symbolic name +// +#define DSM_MPIO_CONTROL_OBJECT_SYMLINK L"\\DosDevices\\MPIOControl" + +// +// Location of System class node in the registry +// +#define DSM_SYSTEM_CLASS_GUID_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E97D-E325-11CE-BFC1-08002BE10318}" + +// +// Values used for matching and figuring out the DriverVersion +// +#define DSM_INF_PATH L"InfPath" +#define DSM_MSDSM_INF_PATH L"msdsm.inf" +#define DSM_DRIVER_VERSION L"DriverVersion" +#define DSM_DRIVER_VERSION_FIELD_DELIMITER L'.' +#define DSM_BUFFER_MAXCOUNT 64 + +// +// MSDSM's display name. +// +#define DSM_FRIENDLY_NAME L"Microsoft DSM" + +// +// Name of the value for the supported devices in the registry, found in the +// DSM's Services' Parameters key +// +#define DSM_SUPPORTED_DEVICELIST_VALUE_NAME L"DsmSupportedDeviceList" + +// +// Value used to determine if per-IO statistics gathering needs to be turned OFF +// +#define DSM_DISABLE_STATISTICS L"DsmDisableStatistics" + +// +// Names of the values in the registry for whether to use the same path for +// sequential IOs when employing Least Blocks load balance policy, as well +// as its size. +// +#define DSM_USE_CACHE_FOR_LEAST_BLOCKS L"DsmUseCacheForLeastBlocks" +#define DSM_CACHE_SIZE_FOR_LEAST_BLOCKS L"DsmCacheSizeForLeastBlocks" + +// +// Name of the value in the registry for the maximum request retry time during ALUA +// state transitions. This value is found in the DSM's Services' Parameters key, and +// applies only to Persistent Reservation commands. +// +#define DSM_MAX_STATE_TRANSITION_TIME_VALUE_NAME L"DsmMaximumStateTransitionTime" + + +// +// Default max amount of time (in seconds) that a PR failing with retry-able UA will be retried +// +#define DSM_MAX_PR_UNIT_ATTENTION_RETRY_TIME 3 + +// +// Macro to translate seconds to ticks. Each system tick is 10^(-7) seconds. +// +#define DSM_SECONDS_TO_TICKS(_Seconds) ((_Seconds) * 10000000) + +// +// Size of the buffer allocated to retrieve device serial number. +// This is as defined by SPC-3 spec. The identifier with the biggest size is +// SCSI name type (0x8). +// +#define DSM_SERIAL_NUMBER_BUFFER_SIZE 255 + +// +// Number of LB Policies that are supported by this driver. +// +#define DSM_NUMBER_OF_LB_POLICIES 6 + +// +// Size of the buffer passed to read in Persistent Reserve keys. +// +#define DSM_READ_PERSISTENT_KEYS_BUFFER_SIZE 4096 + +// +// The default threshold for sequential IO for the Least Blocks load balance +// policy is 1MB. +// +#define DSM_LEAST_BLOCKS_DEFAULT_THRESHOLD 0x00100000 + +// +// Initialization data structure that needs to be filled in for MPIO +// +DSM_INIT_DATA gDsmInitData; + +// +// Macro used to round of a number to the nearest 8 byte aligned one. +// +#ifdef AlignOn8Bytes +#undef AlignOn8Bytes +#endif +#define AlignOn8Bytes(x) (((x) + 7) & ~7) + +// +// Macro for determining minimum of two numbers +// +#ifdef MIN +#undef MIN +#endif +#define MIN(a, b) ((ULONGLONG)(a) < (ULONGLONG)(b) ? (a) : (b)) + +// +// Macro used to convert a 4 byte array to a ULONG (where byte 0 MSB, byte 3 LSB) +// +#define GetUlongFrom4ByteArray(UCharArray, ULongValue) \ + ((UNALIGNED UCHAR *)&(ULongValue))[3] = ((UNALIGNED UCHAR *)(UCharArray))[0]; \ + ((UNALIGNED UCHAR *)&(ULongValue))[2] = ((UNALIGNED UCHAR *)(UCharArray))[1]; \ + ((UNALIGNED UCHAR *)&(ULongValue))[1] = ((UNALIGNED UCHAR *)(UCharArray))[2]; \ + ((UNALIGNED UCHAR *)&(ULongValue))[0] = ((UNALIGNED UCHAR *)(UCharArray))[3]; + +// +// Macro used to convert a ULONG into a 4 byte array (as big-endian) +// +#define Get4ByteArrayFromUlong(ULongValue, UCharArray) \ + ((UNALIGNED UCHAR *)(UCharArray))[3] = ((UNALIGNED UCHAR *)&(ULongValue))[0]; \ + ((UNALIGNED UCHAR *)(UCharArray))[2] = ((UNALIGNED UCHAR *)&(ULongValue))[1]; \ + ((UNALIGNED UCHAR *)(UCharArray))[1] = ((UNALIGNED UCHAR *)&(ULongValue))[2]; \ + ((UNALIGNED UCHAR *)(UCharArray))[0] = ((UNALIGNED UCHAR *)&(ULongValue))[3]; + +// +// Macro to check if passed in opcode is a read, write +// +#define DsmIsReadRequest(_Opcode) (_Opcode == SCSIOP_READ || _Opcode == SCSIOP_READ16) +#define DsmIsWriteRequest(_Opcode) (_Opcode == SCSIOP_WRITE || _Opcode == SCSIOP_WRITE16) +#define DsmIsReadWrite(_Opcode) (_Opcode == SCSIOP_READ || _Opcode == SCSIOP_READ16 || \ + _Opcode == SCSIOP_WRITE || _Opcode == SCSIOP_WRITE16) + +#define DsmIsReadCapacity( _Opcode ) (_Opcode == SCSIOP_READ_CAPACITY || _Opcode == SCSIOP_READ_CAPACITY16) + + +// +// Macro to find the number of bytes consumed by the array +// +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + + +// +// Signature used to identify various structures. +// Used solely for debugging purposes. +// +#define DSM_DEVICE_SIG 0xAAAAAAAA +#define DSM_GROUP_SIG 0x55555555 +#define DSM_FOG_SIG 0x88888888 +#define DSM_TARGET_PORT_GROUP_SIG 0x33333333 +#define DSM_TARGET_PORT_SIG 0xCCCCCCCC +#define DSM_CONTROLLER_SIG 0xEEEEEEEE + +#define WNULL (L'\0') +#define WNULL_SIZE (sizeof(WNULL)) + +#if DBG + +// +// NT_ASSERT wrapper. +// +#define DSM_ASSERT(exp) if (DoAssert) { \ + NT_ASSERT(exp); \ + } + +#else // DBG + +#define DSM_ASSERT(exp) + +#endif // DBG + +#define DSM_PARAMETER_PATH_W L"MSDSM\\Parameters" + +// +// Pool Tags used in memory allocation +// +#define DSM_TAG_GENERIC '00ZZ' +#define DSM_TAG_PASS_THRU '10ZZ' +#define DSM_TAG_GROUP_ENTRY '20ZZ' +#define DSM_TAG_FO_GROUP '30ZZ' +#define DSM_TAG_DSM_CONTEXT '40ZZ' +#define DSM_TAG_DEV_INFO '50ZZ' +#define DSM_TAG_SERIAL_NUM '60ZZ' +#define DSM_TAG_CTRL_INFO '70ZZ' +#define DSM_TAG_SUPPORTED_DEV '80ZZ' +#define DSM_TAG_REG_PATH '90ZZ' +#define DSM_TAG_FOG_DEV_ENTRY 'A0ZZ' +#define DSM_TAG_DEV_ID 'B0ZZ' +#define DSM_TAG_DEV_NAME 'C0ZZ' +#define DSM_TAG_LB_POLICY 'D0ZZ' +#define DSM_TAG_PR_KEYS 'E0ZZ' +#define DSM_TAG_RESERVED_DEVICE 'F0ZZ' +#define DSM_TAG_BIN_TO_ASCII '01ZZ' +#define DSM_TAG_TARGET_PORT_LIST_ENTRY '11ZZ' +#define DSM_TAG_TARGET_PORT_GROUP_ENTRY '21ZZ' +#define DSM_TAG_RELATIVE_TARGET_PORT_ID '31ZZ' +#define DSM_TAG_TARGET_PORT_GROUPS '41ZZ' +#define DSM_TAG_CONTROLLER_LIST_ENTRY '51ZZ' +#define DSM_TAG_CONTROLLER_INFO '61ZZ' +#define DSM_TAG_IO_STATUS_BLOCK '71ZZ' +#define DSM_TAG_DEVICE_ID_LIST '81ZZ' +#define DSM_TAG_TP_DEVICE_LIST_ENTRY '91ZZ' +#define DSM_TAG_RETRY_RESERVE 'A1ZZ' +#define DSM_TAG_WORKITEM 'B1ZZ' +#define DSM_TAG_SCSI_ADDRESS 'C1ZZ' +#define DSM_TAG_FAIL_DEVINFO_LIST_ENTRY 'D1ZZ' +#define DSM_TAG_TPG_COMPLETION_CONTEXT 'E1ZZ' +#define DSM_TAG_SCSI_REQUEST_BLOCK 'F1ZZ' +#define DSM_TAG_SCSI_SENSE_INFO '02ZZ' +#define DSM_TAG_SPT_DATA_BUFFER '12ZZ' +#define DSM_TAG_REG_KEY_RELATED '22ZZ' +#define DSM_TAG_DEV_HARDWARE_ID '32ZZ' +#define DSM_TAG_REG_VALUE_RELATED '42ZZ' +#define DSM_TAG_ZOMBIEGROUP_ENTRY '52ZZ' +#define DSM_TAG_PERSISTENT_RESERVATION '62ZZ' + +// +// Parameters subkey name under HKLM\System\CCS\Services\MSDSM +// +#define DSM_SERVICE_PARAMETERS L"Parameters" + +// +// Load Balance settings are persisted in the registry under this key +// +#define DSM_LOAD_BALANCE_SETTINGS L"DsmLoadBalanceSettings" + +// +// Load Balance settings on a VID/PID basis are persistented in the registry +// under this key +// +#define DSM_TARGETS_LOAD_BALANCE_SETTING L"DsmTargetsLoadBalanceSetting" + +// +// Values persisted per device: +// 1. Load Balance Policy +// 2. Preferred Path +// 3. Whether LB policy has been explicitly set +// +#define DSM_LOAD_BALANCE_POLICY L"DsmLoadBalancePolicy" +#define DSM_PREFERRED_PATH L"DsmPreferredPath" +#define DSM_POLICY_EXPLICITLY_SET L"DsmLoadBalancePolicyExplicitlySet" + +// +// Prefix for subkey created for each path +// +#define DSM_PATH L"DSMPath" + +// +// Values persisted per path: +// 1. Whether primary +// 2. Whether optimized +// 3. Path weight. +// +// Primary Optimized State +//==================================== +// True True Active-Optimized +// True False Active-Unoptimized +// False True StandBy +// False False Unavailable +// +#define DSM_PRIMARY_PATH L"DsmPrimaryPath" +#define DSM_OPTIMIZED_PATH L"DsmOptimizedPath" +#define DSM_PATH_WEIGHT L"DsmPathWeight" + +// +// Indicates that device doesn't support ALUA. +// +#define DSM_DEVINFO_ALUA_NOT_SUPPORTED 0 + +// +// Implies that device supports implicit ALUA transistions. +// +#define DSM_DEVINFO_ALUA_IMPLICIT 1 + +// +// Implies that device supports explicit ALUA state transitions. +// +#define DSM_DEVINFO_ALUA_EXPLICIT 2 + +// +// Type of device identifier (VPD 0x83) +// +typedef enum _DSM_DEVID_TYPE { + DSM_DEVID_SERIAL_NUMBER = 1, + DSM_DEVID_RELATIVE_TARGET_PORT, + DSM_DEVID_TARGET_PORT_GROUP +} DSM_DEVID_TYPE, *PDSM_DEVID_TYPE; + +#define _DSM_TERNARY_BOOLEAN UCHAR +typedef _DSM_TERNARY_BOOLEAN DSM_TERNARY_BOOLEAN, *PDSM_TERNARY_BOOLEAN; +#define DSM_TERNARY_UNKNOWN 0 +#define DSM_TERNARY_TRUE 1 +#define DSM_TERNARY_FALSE 2 + +// +// Macro to determine if _Id2 is more preferred than _Id1 to build a device's +// serial number. +// +#define DsmpIsPreferredDeviceId(_Id1, _Id2) (((_Id2) == StorageIdTypeScsiNameString) || \ + ((_Id2) == StorageIdTypeFCPHName && (_Id1) != StorageIdTypeScsiNameString) || \ + ((_Id2) == StorageIdTypeEUI64 && (_Id1) != StorageIdTypeScsiNameString && (_Id1) != StorageIdTypeFCPHName) || \ + ((_Id2) == StorageIdTypeVendorId && (_Id1) != StorageIdTypeScsiNameString && (_Id1) != StorageIdTypeFCPHName && (_Id1) != StorageIdTypeEUI64) || \ + ((_Id2) == StorageIdTypeVendorSpecific && (_Id1) != StorageIdTypeScsiNameString && (_Id1) != StorageIdTypeFCPHName && (_Id1) != StorageIdTypeEUI64 && (_Id1) != StorageIdTypeVendorId)) + +// +// Device State +// +typedef enum _DSM_DEVICE_STATE { + + // + // If ALUA is not supported, this state indicates that the device is active + // and a request can be sent to the device. + // If ALUA is supported, then this state indicates optimizied device-path + // pair for the device. + // + DSM_DEV_ACTIVE_OPTIMIZED = 0, + + // + // If ALUA is not supported, this state is not used. + // If ALUA is supported, then this state indicates active but unoptimized + // device-path pairing for the device. Can be used in in case no + // active/optimized path is available to service the IO. + // + DSM_DEV_ACTIVE_UNOPTIMIZED, + + // + // If ALUA is not supported, this state indicates that the device is in + // standby state. A request can be sent to the device in this state. + // If ALUA is supported, then this state indicates standby device-path + // pairing and only certain requests can be handled in this state. + // + DSM_DEV_STANDBY, + + // + // If ALUA is not supported, this state is not used. + // If ALUA is supported, then this state indicates that the device-path pairing + // is not active and incapable of handling any requests. + // + DSM_DEV_UNAVAILABLE, + + // + // If ALUA is not supported, this state is not used. + // If ALUA is supported, then this state indicates that the device-path pairing + // (actually its TPG) is in a transitioning state. + // + DSM_DEV_TRANSITIONING = 15, + + // + // Initial state when devInfo is created. + // + DSM_DEV_NOT_USED_STATE = 16, + + // + // Indicates that the state was undetermined (this is applicable only for + // a deviceInfo's DesiredState or if the device instance's path was not + // determined). + // + DSM_DEV_UNDETERMINED, + + // + // Indicates that a request sent down previously failed with a fatal error + // + DSM_DEV_FAILED, + + // + // Indicates that InvalidatePath has been called + // + DSM_DEV_INVALIDATED, + + // + // This indicates the device is about to be removed. No new request + // should be sent to the device. + // + DSM_DEV_REMOVE_PENDING, + + // + // This indicates the device has been removed. + // + DSM_DEV_REMOVED + +} DSM_DEVICE_STATE, *PDSM_DEVICE_STATE; + +// +// Device states supported +// +#define DSM_STATE_ACTIVE_OPTIMIZED_SUPPORTED 0 +#define DSM_STATE_STANDBY_SUPPORTED 1 +#define DSM_STATE_ACTIVE_UNOPTIMIZED_SUPPORTED 2 +#define DSM_STATE_UNAVAILABLE_SUPPORTED 4 + + +// +// Macro to determine if devInfo is in a failure state. +// +#define DsmpIsDeviceFailedState(_State) ((_State) > DSM_DEV_NOT_USED_STATE) + +// +// Macro to determine if devInfo was initialized. +// +#define DsmpIsDeviceInitialized(_DeviceInfo) ((_DeviceInfo)->Initialized) + +// +// Macro to determine if device is "usable" (ie. IsPathActive was successfully called). +// +#define DsmpIsDeviceUsable(_DeviceInfo) ((_DeviceInfo)->Usable) + +// +// Macro to determine if devInfo was used to send down registration. +// It the devInfo's group is not reserved, then the devInfo doesn't need to have +// had a register go down it. +// It the group is reserved, then the devInfo MUST have had a register go down it +// for it to be used. +// +#define DsmpIsDeviceUsablePR(_DeviceInfo) (!(_DeviceInfo)->Group->PRKeyValid || (_DeviceInfo)->PRKeyRegistered) + + +// +// Macro to determine if _State2 is a more preferred state than _State1. +// +#define DsmpIsBetterDeviceState(_State1, _State2) (((_State1) == DSM_DEV_STANDBY && (_State2) == DSM_DEV_ACTIVE_UNOPTIMIZED) || \ + ((_State1) == DSM_DEV_UNAVAILABLE && \ + ((_State2) == DSM_DEV_ACTIVE_UNOPTIMIZED || (_State2) == DSM_DEV_STANDBY)) || \ + ((_State1) == DSM_DEV_TRANSITIONING && \ + ((_State2) == DSM_DEV_ACTIVE_UNOPTIMIZED || (_State2) == DSM_DEV_STANDBY) || (_State2) == DSM_DEV_UNAVAILABLE)) + +// +// Macro to determine if passed in _State is active. +// +#define DsmpIsDeviceStateActive(_State) ((_State) == DSM_DEV_ACTIVE_OPTIMIZED || (_State) == DSM_DEV_ACTIVE_UNOPTIMIZED) + +// +// Macro to determine if symmetric access to the storage +// +#define DsmpIsSymmetricAccess(_DeviceInfo) ((_DeviceInfo)->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED || \ + ((_DeviceInfo)->ALUASupport == DSM_DEVINFO_ALUA_IMPLICIT && \ + (_DeviceInfo)->Group->Symmetric)) + +// +// Multi-path Group State +// +typedef enum _DSM_GROUP_STATE { + + // + // This indicates that the device is in working state. + // + DSM_GP_NORMAL = 1, + + // + // This indicates that there is a pending reservation failover + // + DSM_GP_PENDING, + + // + // This indicates that the device has lost all its paths + // + DSM_GP_FAILED + +} DSM_GROUP_STATE, *PDSM_GROUP_STATE; + +// +// Fail-Over Group State +// +typedef enum _DSM_FAILOVER_GROUP_STATE { + + // + // This indicates that the path is in working state. + // + DSM_FG_NORMAL = 1, + + // + // This indicates the path which had failed earlier + // is back to working state now. + // + DSM_FG_FAILBACK, + + // + // This indicates the path is about to be removed + // + DSM_FG_PENDING_REMOVE, + + // + // This indicates the path has failed. + // + DSM_FG_FAILED + +} DSM_FAILOVER_GROUP_STATE, *PDSM_FAILOVER_GROUP_STATE; + +#define DsmpIsPathFailedState(_State) ((_State) >= DSM_FG_PENDING_REMOVE) + +// +// DSM Context is the global driver context that gets passed to each of the DSM +// entry points. +// +// The DSM Context will maintain a list of all DeviceInfos (device-path pairing). +// It will maintain a list of Group entries. Each entry in the Group list will +// represent a LUN's different instances down different paths (i.e. DeviceInfos). +// Each entry in the Group will maintain a list of target port groups. +// Each entry in the target port group list will maintain a list of target +// ports that make up the target port group. Every deviceInfo that isn't +// in a failure state will be in the same state as the Asymmetric Access +// State of the target port group. +// There will be a list of Fail Over Group entries, where each entry represents +// the list of devices that fail over as a group (i.e. devices on the same path). +// There will also be a list of controller entries, representing the controllers +// on all storages connected to the system. +// +typedef struct _DSM_CONTEXT { + + // + // Used to synchronize access to the SupportedDevices list. + // + KSPIN_LOCK SupportedDevicesListLock; + + // + // List of supported devices - added into the INF. + // + UNICODE_STRING SupportedDevices; + + // + // Used to synchronize access to the elements in this structure. + // + EX_SPIN_LOCK DsmContextLock; + + // + // Flag cached that indicates if statistics don't need to be gathered + // + BOOLEAN DisableStatsGathering; + + UCHAR Reserved[3]; + + // + // Number of devices currently found. + // + ULONG NumberDevices; + + // + // List of devices. + // + LIST_ENTRY DeviceList; + + // + // Number of multi-path groups. + // + ULONG NumberGroups; + + // + // List of multi-path groups. + // + LIST_ENTRY GroupList; + + // + // Number of fail-over groups. + // + ULONG NumberFOGroups; + + // + // List of fail-over groups. + // + LIST_ENTRY FailGroupList; + + // + // Number of controllers. + // + ULONG NumberControllers; + + // + // List of controllers + // + LIST_ENTRY ControllerList; + + // + // Number of stale fail-over groups + // + ULONG NumberStaleFOGroups; + + // + // List of stale fail-over groups maintained for paths for which all devices + // have gotten removed but for which there is still outstanding IO-statistics + // + LIST_ENTRY StaleFailGroupList; + + // + // Context value passed to the DSM from MPIO. + // + PVOID MPIOContext; + + + // + // Look-aside list of completion routine context structures. + // + NPAGED_LOOKASIDE_LIST CompletionContextList; + +} DSM_CONTEXT, *PDSM_CONTEXT; + +// +// Statistics structure. Used by the device and path routines. +// +typedef struct _DSM_STATS { + + ULONG NumberReads; + ULONG NumberWrites; + ULONGLONG BytesRead; + ULONGLONG BytesWritten; + +} DSM_STATS, *PDSM_STATS; + + +// +// Information about each device that is supported by the DSM. +// +typedef struct _DSM_DEVICE_INFO { + + // + // To link to the next device info structure in the list + // + LIST_ENTRY ListEntry; + + // + // The device SIG. Used for debug. + // + ULONG DeviceSig; + + // + // Back-pointer to the DSM_CONTEXT. + // + PVOID DsmContext; + + // + // The underlying port driver PDO. + // + PDEVICE_OBJECT PortPdo; + + // + // The port FDO to which PortPdo is attached. + // + PDEVICE_OBJECT PortFdo; + + // + // The DeviceObject to which I/Os generated by the DSM should + // be sent. This is given to us by MPIO. + // + PDEVICE_OBJECT TargetObject; + + // + // The multi-path group to which this device belongs. + // + struct _DSM_GROUP_ENTRY *Group; + + // + // The fail-over group to which this device belongs. + // + struct _DSM_FAILOVER_GROUP *FailGroup; + + // + // The controller through which this device showed up. + // + struct _DSM_CONTROLLER_LIST_ENTRY *Controller; + + // + // The Target Port Group that this device belongs to. + // + struct _DSM_TARGET_PORT_GROUP_ENTRY *TargetPortGroup; + + // + // The Target Port that this device was exposed via. + // + struct _DSM_TARGET_PORT_LIST_ENTRY *TargetPort; + + // + // The current state of this device: ACTIVE_O, ACTIVE_U, STANDBY, UNAVAILABLE, etc. + // + DSM_DEVICE_STATE State; + + // + // Previous state of this device. Updated whenever this deviceInfo makes a + // state transition. + // + DSM_DEVICE_STATE PreviousState; + + // + // The desired state of this device: based on PrimaryPath and OptimizedPath + // specified in the registry. + // + DSM_DEVICE_STATE DesiredState; + + // + // The ALUA state of the TPG immediately after a ReportTPG is issued. + // + DSM_DEVICE_STATE ALUAState; + + // + // Holds state information temporarily while applying LB policy. Used in case + // changes need to be reverted in case of failure to apply the policy. + // + DSM_DEVICE_STATE TempPreviousStateForLB; + + // + // This is to save off the last known non-failed state. + // In case of an error down this deviceInfo, it is marked to be in Failed state. + // However, if no remove comes down for this device and a PathVerify down this + // deviceInfo succeeds, we need to put the deviceInfo back into a usable state. + // + DSM_DEVICE_STATE LastKnownGoodState; + + // + // This counter indicates that this deviceInfo is being used and a remove + // must thus wait until the counter falls to 0. + // + LONG BlockRemove; + + + // + // This indicates whether this device has handled a register/register_ignore_existing request, + // irrespective of the actual status of the operation. + // + BOOLEAN RegisterServiced; + + // + // This flag is set when a register/register_ignore_existing succeeds down this device-path pair. + // + BOOLEAN PRKeyRegistered; + + // + // Indicates whether the serial number was embedded in the device + // descriptor, or it was allocated. + // + BOOLEAN SerialNumberAllocated; + + // + // Flag to indicate that SetDeviceInfo has been called (and succeeded) on this device + // + BOOLEAN Initialized; + + // + // Flag to indicate that IsPathActive has been called (and succeeded) on this device. + // + BOOLEAN Usable; + + // + // Flag to indicate if IALUAE was disabled (via mode select) + // + BOOLEAN ImplicitDisabled; + + // + // Flag to indicate that RTPG has already been sent down in Inquire, so + // PathVerify can ignore sending down one more if it is called during + // device initialization. + // + BOOLEAN IgnorePathVerify; + + // + // Bit map indicating whether (and what kind) of ALUA support. + // + UCHAR ALUASupport; + + // + // Weight assigned to this path by management application. This is used + // when doing Load Balancing based on weighted paths. + // + ULONG PathWeight; + + // + // Number of requests outstanding on this device. + // + LONG NumberOfRequestsInProgress; + + // + // I/O, Fail-Over statistics. + // + DSM_STATS DeviceStats; + + // + // The device's serial number. + // + PSTR SerialNumber; + + // + // The scsi address of the port pdo. + // + PSCSI_ADDRESS ScsiAddress; + + + // + // Kernel structure that describes this device. Passed in to Inquire. + // + // NOTE: Descriptor should be the LAST field in this structure + // + STORAGE_DEVICE_DESCRIPTOR Descriptor; + +} DSM_DEVICE_INFO, *PDSM_DEVICE_INFO; + +typedef enum _DSM_DEFAULT_LB_POLICY_TYPE { + DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY = 0, // DSM assigned based on LUN access capability + DSM_DEFAULT_LB_POLICY_DSM_WIDE, // Admin has set a DSM-wide default policy + DSM_DEFAULT_LB_POLICY_VID_PID, // Admin has set a default policy for LUN's VID/PID + DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT // Admin has explicitly set the policy on the LUN +} DSM_DEFAULT_LB_POLICY_TYPE, *PDSM_DEFAULT_LB_POLICY_TYPE; + +typedef ULONG DSM_LOAD_BALANCE_TYPE, *PDSM_LOAD_BALANCE_TYPE; + + +// +// Information about multi-path groups: The same device found via multiple paths +// are put under one group. Each group will have it's own Load Balance policy +// settings. In other words, Load Balance policy settings are on per-device basis. +// +typedef struct _DSM_GROUP_ENTRY { + + // + // To link to the next entry in the multi-path group. + // + LIST_ENTRY ListEntry; + + // + // Group signature. Used for debug. + // + ULONG GroupSig; + + // + // Ordinal of creation. Never decremented. + // + ULONG GroupNumber; + + // + // State of the group. + // + DSM_GROUP_STATE State; + + // + // Number of devices in the multi-path group. + // + ULONG NumberDevices; + + // + // Array of devices belonging to this group. + // + PDSM_DEVICE_INFO DeviceList[DSM_MAX_PATHS]; + + // + // Max time to retry failed PR requests + // + ULONG MaxPRRetryTimeDuringStateTransition; + + // + // Number of target port groups that this device is accessible via. + // + ULONG NumberTargetPortGroups; + + // + // Array of the target port groups that this LUN belongs in. + // + struct _DSM_TARGET_PORT_GROUP_ENTRY *TargetPortGroupList[DSM_MAX_PATHS]; + + // + // Key used in Persistent Reserve\Release. This key is provided to the DSM + // by Cluster service. If cluster service has provided the key PRKeyValid + // is set to TRUE. PRKeyValid is set to FALSE otherwise. + // PRServiceAction, PRType and PRScope are the service action, type and + // scope associated with the PR registration. + // + UCHAR PersistentReservationRegisteredKey[8]; + UCHAR PRServiceAction; + UCHAR PRType; + UCHAR PRScope; + UCHAR PRKeyValid; + + + // + // Flag used to denote that LU access is symmetric down all paths + // + BOOLEAN Symmetric; + + // + // Flag to indicate whether or not to use same path for sequential IO + // when employing Least Blocks load balance policy. + // + BOOLEAN UseCacheForLeastBlocks; + + // + // Flag used to indicate if a throttle request succeeded. + // + ULONG Throttled; + + // + // Counter to track the number of RTPG in flight. + // + ULONG InFlightRTPG; + + // + // A bitmask of which devices are currently reserved. + // + ULONG ReservationList; + + // + // Which type of Load Balancing is being performed. + // + DSM_LOAD_BALANCE_TYPE LoadBalanceType; + + // + // Indicates how the Load Balancing policy was selected. + // + DSM_DEFAULT_LB_POLICY_TYPE LBPolicySelection; + + // + // The path to use when possible - if in F.O. Only, if failover had taken + // place and this path comes back online, failback to this path will take + // place. + // + ULONGLONG PreferredPath; + + // + // The path to choose when Round Robin Load Balance policy is in use + // + PVOID PathToBeUsed; + + // + // Size of cache set by Admin. Used in case of handling sequential + // IO in Least Blocks policy. + // + ULONGLONG CacheSizeForLeastBlocks; + + // + // The HardwareId (VID/PID) of the LUN + // + PWSTR HardwareId; + + // + // The registry key under which Load Balance Policy settings + // are stored in the registry for this Device Group. + // + PWSTR RegistryKeyName; + + // + // Number of failing deviceInfos + // + ULONG NumberFailingDevInfos; + + // + // To link the list of failed A/O devInfos and the corresponding non-A/O + // devInfos that are temporarily being used to service IO until STPG can + // properly update the device states. This is applicable only for ALUA + // devices. + // + LIST_ENTRY FailingDevInfoList; + + // + // General Purpose Event. + // + KEVENT Event; + +} DSM_GROUP_ENTRY, *PDSM_GROUP_ENTRY; + +// +// The collection of devices on one path. These fail-over as a unit. +// A path is considered an I_T nexus, i.e. Initiator port to Target (controller) port. +// +typedef struct _DSM_FAILOVER_GROUP { + + // + // To link to the next entry in the failover group + // + LIST_ENTRY ListEntry; + + // + // Signature. Used for debug. + // + ULONG FailOverSig; + + // + // State of the Path. + // + DSM_FAILOVER_GROUP_STATE State; + + // + // The pathId corresponding to this FOG. It may or may not be + // the same as what MPIO gave us as the default value. + // + PVOID PathId; + + // + // The default pathId (port FDO). + // + PDEVICE_OBJECT MPIOPath; + + // + // Last LBA + // + ULONGLONG LastLba; + + // + // Cumulative outstanding IO (in terms of size) + // + ULONGLONG OutstandingBytesOfIO; + + // + // Count of inflight IOs. This will be used in LQD load balance policy. + // + volatile LONG NumberOfRequestsInFlight; + + // + // Number of devices in this FOG. + // + ULONG Count; + + // + // List of devices that will over together. + // + LIST_ENTRY FOG_DeviceList; + + // + // List of zombie groups (in case a device is removed before the failover + // processing begins). + // + LIST_ENTRY ZombieGroupList; + +} DSM_FAILOVER_GROUP, *PDSM_FAILOVER_GROUP; + + +// +// Information about a target port group entry for a given LUN. +// Note: This is not a global list of all TPGs that are built. It is local to a Group entry. +// +typedef struct _DSM_TARGET_PORT_GROUP_ENTRY { + + // + // Signature. Used for debug. + // + ULONG TargetPortGroupSig; + + // + // The asymmetric access state for this target port group: + // ACTIVE_O, ACTIVE_U, STANDBY or UNAVAILABLE + // + DSM_DEVICE_STATE AsymmetricAccessState; + + // + // Flag to indicate if this is the preferred target port group. + // + BOOLEAN Preferred; + + // + // Supported access states + // + BOOLEAN ActiveOptimizedSupported; + BOOLEAN ActiveUnoptimizedSupported; + BOOLEAN StandBySupported; + BOOLEAN UnavailableSupported; + + // + // Indicates if the device reports asymmetric state as being under transition. + // + BOOLEAN TransitioningSupported; + + // + // Flag to indicate if this has been returned in any subsequent RTPG after + // it is initially built. (If this flag is not set after parsing the RTPG + // information, it indicates that this TPG entry is stale and should be + // deleted). + // + BOOLEAN Traversed; + + UCHAR Reserved; + + // + // The target group identifier + // + USHORT Identifier; + + // + // Status code + // + UCHAR StatusCode; + + // + // Vendor unique + // + UCHAR VendorUnique; + + // + // Backpointer to owning group + // + PDSM_GROUP_ENTRY Group; + + // + // Number of target ports that make up this group + // + ULONG NumberTargetPorts; + + // + // Linked list of target ports that make up this target port group. + // + LIST_ENTRY TargetPortList; + +} DSM_TARGET_PORT_GROUP_ENTRY, *PDSM_TARGET_PORT_GROUP_ENTRY; + + +// +// Information about each target port list entry for a given target port group. +// Note: this is not a global list of all TPs. It is local to a given TPG entry. +// +typedef struct _DSM_TARGET_PORT_LIST_ENTRY { + + // + // Link + // + LIST_ENTRY ListEntry; + + // + // Signature. Used for debug. + // + ULONG TargetPortSig; + + // + // Relative target port identifier + // + ULONG Identifier; + + // + // Backpointer to owning target port group + // + PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup; + + // + // Number of device instances exposed via this target port + // + ULONG Count; + + // + // List of device instances exposed via this target port + // + LIST_ENTRY TP_DeviceList; + +} DSM_TARGET_PORT_LIST_ENTRY, *PDSM_TARGET_PORT_LIST_ENTRY; + +// +// Information about each controller entry +// +typedef struct _DSM_CONTROLLER_LIST_ENTRY { + + // + // To link to the next contoller entry. + // + LIST_ENTRY ListEntry; + + // + // It's signature. Used for debug. + // + ULONG ControllerSig; + + // + // Device object (this controller's PDO). + // + PDEVICE_OBJECT DeviceObject; + + // + // Port FDO through which this controller object was exposed. + // + PDEVICE_OBJECT PortObject; + + // + // Identifier. + // + _Field_size_(IdLength) PUCHAR Identifier; + + // + // Identifier length. + // + ULONG IdLength; + + // + // Identifier code set. + // + STORAGE_IDENTIFIER_CODE_SET IdCodeSet; + + // + // Controller's SCSI address. + // + PSCSI_ADDRESS ScsiAddress; + + // + // Number of references to this entry. + // + UCHAR RefCount; + + // + // Flag to indicate whether this is a fake entry built for storage that do + // NOT have controllers + // + BOOLEAN IsFakeController; + + UCHAR Reserved[2]; + +} DSM_CONTROLLER_LIST_ENTRY, *PDSM_CONTROLLER_LIST_ENTRY; + +// +// Generic linked list of devices +// +typedef struct _DSM_DEVICELIST_ENTRY { + + // + // To link to the next device info structure in the list + // + LIST_ENTRY ListEntry; + + // + // Representation of device-path pair + // + PDSM_DEVICE_INFO DeviceInfo; + +} DSM_DEVICELIST_ENTRY, *PDSM_DEVICELIST_ENTRY; + +// +// Zombie Group List Entry +// +typedef struct _DSM_ZOMBIEGROUP_ENTRY { + + // + // To link to the next zombie group structure in the list + // + LIST_ENTRY ListEntry; + + // + // Pointer to actual group entry + // + PDSM_GROUP_ENTRY Group; + + // + // Flag to indicate that the failover thread has processed this entry. + // + BOOLEAN Processed; + +} DSM_ZOMBIEGROUP_ENTRY, *PDSM_ZOMBIEGROUP_ENTRY; + +// +// Linked list of devices that will failover as a group +// +typedef DSM_DEVICELIST_ENTRY DSM_FOG_DEVICELIST_ENTRY, *PDSM_FOG_DEVICELIST_ENTRY; + +// +// Linked list of the same device being exposed off of a particular target port +// (possibly because the controller is connected to multiple HBAs). +// +typedef DSM_DEVICELIST_ENTRY DSM_TARGET_PORT_DEVICELIST_ENTRY, *PDSM_TARGET_PORT_DEVICELIST_ENTRY; + +// +// Information about each failing devInfo and its corresponding devInfo +// being used temporarily to service requests until STPG can update new +// device states. +// +typedef struct _DSM_FAIL_PATH_PROCESSING_LIST_ENTRY { + + // + // To link to the next device info structure in the list + // + LIST_ENTRY ListEntry; + + // + // Representation of the failing device-path pair + // + PDSM_DEVICE_INFO FailingDeviceInfo; + + // + // Representation of the new candidate device-path pair that will take over + // processing of requests + // + PDSM_DEVICE_INFO TempDeviceInfo; + +} DSM_FAIL_PATH_PROCESSING_LIST_ENTRY, *PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY; + +// +// Completion context structure. +// +typedef struct _DSM_COMPLETION_CONTEXT { + + // + // The device that handled the request. + // + PDSM_DEVICE_INFO DeviceInfo; + + // + // The global context. + // + PDSM_CONTEXT DsmContext; + + // + // These are used to store control code, pointer to KEVENT, etc. + // + PVOID RequestUnique1; + + ULONG_PTR RequestUnique2; + +#if DBG + // + // Request time-stamp. + // + LARGE_INTEGER TickCount; +#endif + +} DSM_COMPLETION_CONTEXT, *PDSM_COMPLETION_CONTEXT; + +// +// Completion context structure for report/set target port groups. +// +typedef struct _DSM_TPG_COMPLETION_CONTEXT { + + PDSM_COMPLETION_CONTEXT CompletionContext; + + PSCSI_REQUEST_BLOCK Srb; + + PVOID SenseInfoBuffer; + + ULONG NumberRetries; + + UCHAR SenseInfoBufferLength; + +} DSM_TPG_COMPLETION_CONTEXT, *PDSM_TPG_COMPLETION_CONTEXT; + +// +// Version number used to determine whice version of MPIO_DSM_Path to use. +// +#define DSM_WMI_VERSION_1 1 +#define DSM_WMI_VERSION_2 2 + +// +// Version of MPIO_DSM_Path that is currently supported by this DSM. +// +#define DSM_WMI_VERSION DSM_WMI_VERSION_2 + +// +// This struct is used to save Load Balance Policy Settings in the registry +// +typedef struct _DSM_LOAD_BALANCE_POLICY_SETTINGS { + + WCHAR RegistryKeyName[256]; + ULONG LoadBalancePolicy; + ULONG PathCount; + MPIO_DSM_Path_V2 DsmPath[1]; + +} DSM_LOAD_BALANCE_POLICY_SETTINGS, *PDSM_LOAD_BALANCE_POLICY_SETTINGS; + +// +// This structure is used to pass in information used by the workitem +// to failover reservations down another path. +// +typedef struct _DSM_RETRY_RESERVE { + + PDSM_COMPLETION_CONTEXT CompletionContext; + + PIRP Irp; + + PKEVENT Event; + +} DSM_RETRY_RESERVE, *PDSM_RETRY_RESERVE; + +// +// This structure defines the workitem that will be used to handle reservation +// failover. +// +typedef struct _DSM_WORKITEM { + + // + // Work item that should be freed by the worker routine + // + PIO_WORKITEM WorkItem; + + // + // Context to be passed to worker routine + // + PVOID Context; + +} DSM_WORKITEM, *PDSM_WORKITEM; + +#endif // _MSDSM_H + + diff --git a/tests/projects/windows/driver/wdm/msdsm/msdsm.mof b/tests/projects/windows/driver/wdm/msdsm/msdsm.mof new file mode 100644 index 000000000..53ee61392 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/msdsm.mof @@ -0,0 +1,82 @@ +// +// Copyright (C) 2004 Microsoft Corporation +// +// +// Microsoft DSM's internal classes +// + +// +// Perf class. +// +[WMI, + guid("{a34d03ec-6b0b-46a1-9178-82525f41133f}")] +class MSDSM_DEVICEPATH_PERF +{ + [WmiDataId(1), + Description("Path Identifier.") : amended + ] uint64 PathId; + + [WmiDataId(2), + Description("Number of Read Requests.") : amended + ] uint32 NumberReads; + + [WmiDataId(3), + Description("Number of Write Requests.") : amended + ] uint32 NumberWrites; + + [WmiDataId(4), + Description("Total Bytes Read.") : amended + ] uint64 BytesRead; + + [WmiDataId(5), + Description("Total Bytes Written.") : amended + ] uint64 BytesWritten; +}; + +[WMI, + Dynamic, + Provider("WmiProv"), + Description("Retrieve MSDSM Performance Information.") : amended, + Locale("MS\\0x409"), + guid("{875b8871-4889-4114-93f6-cd064c001cea}")] +class MSDSM_DEVICE_PERF +{ + [key, read] + string InstanceName; + [read] boolean Active; + + [WmiDataId(1), + read, + Description("Number of paths.") : amended + ] uint32 NumberPaths; + + [WmiDataId(2), + read, + Description("Array of Performance Information per path for the device.") : amended, + WmiSizeIs("NumberPaths") + ] MSDSM_DEVICEPATH_PERF PerfInfo[]; +}; + +// +// Methods +// Clear perf counters. +// +[Dynamic, + Provider("WMIProv"), + WMI, + Description("MSDSM WMI Methods") : amended, + guid("{04517f7e-92bb-4ebe-aed0-54339fa5f544}"), + locale("MS\\0x409") +] +class MSDSM_WMI_METHODS +{ + + [key, read] + string InstanceName; + [read] boolean Active; + + [WmiMethodId(1), + Implemented, + Description("Clear path performance counters for the device.") : amended + ] void MSDsmClearCounters(); +}; diff --git a/tests/projects/windows/driver/wdm/msdsm/msdsm.rc b/tests/projects/windows/driver/wdm/msdsm/msdsm.rc new file mode 100644 index 000000000..743640342 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/msdsm.rc @@ -0,0 +1,24 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// +// Copyright (C) Microsoft Corporation, 2004 +// +// File: msdsm.rc +// +//-------------------------------------------------------------------------- + +#include + +#include + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Microsoft Device Specific Module" +#define VER_INTERNALNAME_STR "msdsm.sys" +#define VER_ORIGINALFILENAME_STR "msdsm.sys" + +#include "common.ver" + +MofResourceName MOFDATA msdsm.bmf +DsmMofResourceName MOFDATA msdsmdsm.bmf diff --git a/tests/projects/windows/driver/wdm/msdsm/msdsmdsm.mof b/tests/projects/windows/driver/wdm/msdsm/msdsmdsm.mof new file mode 100644 index 000000000..f85eea270 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/msdsmdsm.mof @@ -0,0 +1,141 @@ +// +// Copyright (C) 2004 Microsoft Corporation +// +// Microsoft DSM's DSM-specific classes +// + +// +// Class used for retrieving and setting MSDSM-wide default load balance policy. +// +[WMI, + Dynamic, + Provider("WmiProv"), + Description("MSDSM-wide default load balance policies.") : amended, + Locale("MS\\0x409"), + guid("{c81b5681-f3ca-4c98-9325-707d0d62ffc4}")] +class MSDSM_DEFAULT_LOAD_BALANCE_POLICY +{ + [key, read] + string InstanceName; + [read] boolean Active; + + [WmiDataId(1), + read, write, + Description("Load Balance Policy to be applied to devices controlled by MSDSM.") : amended + ] uint32 LoadBalancePolicy; + + [WmiDataId(2), + read, + Description("Reserved.") : amended + ] uint32 Reserved; + + // + // Preferred path. + // + [WmiDataId(3), + read, write, + Description("Preferred Path.") : amended + ] uint64 PreferredPath; +}; + +// +// Embedded class that describes a target and the default load balance policy +// of its LUNs. +// +[WMI, + guid("{ddb00a72-0fab-418b-a89e-97370ae293a4}")] +class MSDSM_TARGET_DEFAULT_POLICY_INFO +{ + // + // VID-PID string as an 8 + 16 character concatenated string. + // Spaces should be used to make the VID 8 chars and the PID 16 chars. + // + [WmiDataId(1), + MaxLen(31), + Description("Concatenated VendorID (8 characters) and ProductID (16 characters).") : amended + ] string HardwareId; + + // + // The default load balance policy to be applied to LUNs from the target + // whose hardware id matches the VID/PID above. + // NOTE: Setting this to 0 will act as removal of default setting for this + // target. + // + [WmiDataId(2)] uint32 LoadBalancePolicy; + + // + // Used for alignment reasons. + // + [WmiDataId(3)] uint32 Reserved; + + // + // Preferred path. + // + [WmiDataId(4)] uint64 PreferredPath; +}; + +// +// Class used for retrieving and setting target-level default load balance policy. +// +[WMI, + Dynamic, + Provider("WmiProv"), + Description("Target-level default load balance policies.") : amended, + Locale("MS\\0x409"), + guid("{5ccbcd91-1b56-4327-a2f3-0960335f8846}")] +class MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY +{ + [key, read] + string InstanceName; + [read] boolean Active; + + [WmiDataId(1), + read, write, + Description("Number of targets specified.") : amended + ] uint32 NumberDevices; + + [WmiDataId(2), + read, + Description("Reserved.") : amended + ] uint32 Reserved; + + [WmiDataId(3), + read, write, + MaxLen(31), + Description("Array of target hardware identifiers with policy and preferred path information.") : amended, + WmiSizeIs("NumberDevices") + ] MSDSM_TARGET_DEFAULT_POLICY_INFO TargetDefaultPolicyInfo[]; +}; + +// +// Supported devices list class. +// +[WMI, + Dynamic, + Provider("WmiProv"), + Description("Retrieve MSDSM's supported devices list.") : amended, + Locale("MS\\0x409"), + guid("{c362d67c-371e-44d8-8bba-044619e4f245}")] +class MSDSM_SUPPORTED_DEVICES_LIST +{ + [key, read] + string InstanceName; + [read] boolean Active; + + [WmiDataId(1), + read, + Description("Number of supported devices.") : amended + ] uint32 NumberDevices; + + [WmiDataId(2), + read, + Description("Reserved.") : amended + ] uint32 Reserved; + + [WmiDataId(3), + read, + MaxLen(31), + Description("Array of device hardware identifiers.") : amended, + WmiSizeIs("NumberDevices") + ] string DeviceId[]; +}; diff --git a/tests/projects/windows/driver/wdm/msdsm/precomp.h b/tests/projects/windows/driver/wdm/msdsm/precomp.h new file mode 100644 index 000000000..bca8595db --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/precomp.h @@ -0,0 +1,34 @@ + +/*++ + +Copyright (c) 2004 Microsoft Corporation + +Module Name: + + precomp.h + +Abstract: + + Precompiled header file for Microsoft Device Specific Module (DSM). + +Revision History: + +--*/ + +#pragma once + +#define DEBUG_MAIN_SOURCE 1 + +#include +#include + +#include "dsm.h" +#include "mpiodisk.h" +#include "msdsm.h" +#include "prototypes.h" +#include "trace.h" +#include "srbhelper.h" + +#include +#include + diff --git a/tests/projects/windows/driver/wdm/msdsm/precompsrc.c b/tests/projects/windows/driver/wdm/msdsm/precompsrc.c new file mode 100644 index 000000000..5944cf515 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/precompsrc.c @@ -0,0 +1 @@ +#include "precomp.h" \ No newline at end of file diff --git a/tests/projects/windows/driver/wdm/msdsm/prototypes.h b/tests/projects/windows/driver/wdm/msdsm/prototypes.h new file mode 100644 index 000000000..ebcf42029 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/prototypes.h @@ -0,0 +1,1436 @@ + +/*++ + +Copyright (C) 2004 Microsoft Corporation + +Module Name: + + prototypes.h + +Abstract: + + Contains function prototypes for all the functions defined + by Microsoft Device Specific Module (DSM). + +Environment: + + kernel mode only + +Notes: + +--*/ + +#pragma warning (disable:4214) // bit field usage +#pragma warning (disable:4200) // zero-sized array + +#ifndef _PROTOTYPES_H_ +#define _PROTOTYPES_H_ + +#define DSM_VENDOR_ID_LEN 8 +#define DSM_PRODUCT_ID_LEN 16 +#define DSM_VENDPROD_ID_LEN 24 + +// +// In accordance with SPC-3 specs +// +#define SPC3_TARGET_PORT_GROUPS_HEADER_SIZE 4 + +typedef struct _SPC3_CDB_REPORT_TARGET_PORT_GROUPS { + UCHAR OperationCode; + UCHAR ServiceAction : 5; + UCHAR Reserved1 : 3; + UCHAR Reserved2[4]; + UCHAR AllocationLength[4]; + UCHAR Reserved3; + UCHAR Control; +} SPC3_CDB_REPORT_TARGET_PORT_GROUPS, *PSPC3_CDB_REPORT_TARGET_PORT_GROUPS; + +typedef struct _SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR { + UCHAR AsymmetricAccessState : 4; + UCHAR Reserved : 3; + UCHAR Preferred : 1; + UCHAR ActiveOptimizedSupported : 1; + UCHAR ActiveUnoptimizedSupported : 1; + UCHAR StandbySupported : 1; + UCHAR UnavailableSupported : 1; + UCHAR Reserved2 : 3; + UCHAR TransitioningSupported : 1; + USHORT TPG_Identifier; + UCHAR Reserved3; + UCHAR StatusCode; + UCHAR VendorUnique; + UCHAR NumberTargetPorts; + ULONG TargetPortIds[0]; +} SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR, *PSPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR; + +typedef struct _SPC3_CDB_SET_TARGET_PORT_GROUPS { + UCHAR OperationCode; + UCHAR ServiceAction : 5; + UCHAR Reserved1 : 3; + UCHAR Reserved2[4]; + UCHAR ParameterListLength[4]; + UCHAR Reserved3; + UCHAR Control; +} SPC3_CDB_SET_TARGET_PORT_GROUPS, *PSPC3_CDB_SET_TARGET_PORT_GROUPS; + +typedef struct _SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR { + UCHAR AsymmetricAccessState : 4; + UCHAR Reserved1 : 4; + UCHAR Reserved2; + USHORT TPG_Identifier; +} SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR, *PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR; + +typedef struct _SPC3_CONTROL_EXTENSION_MODE_PAGE { + UCHAR PageCode : 6; + UCHAR SubpageFormat : 1; + UCHAR ParametersSavable : 1; + UCHAR SubpageCode; + UCHAR PageLength[2]; + UCHAR ImplicitALUAEnable : 1; + UCHAR ScsiPrecendence : 1; + UCHAR TimestampChangeable : 1; + UCHAR Reserved1 : 5; + UCHAR InitialPriority : 4; + UCHAR Reserved2 : 4; + UCHAR Reserved3[26]; +} SPC3_CONTROL_EXTENSION_MODE_PAGE, *PSPC3_CONTROL_EXTENSION_MODE_PAGE; + +#define SPC3_SCSIOP_REPORT_TARGET_PORT_GROUPS 0xA3 +#define SPC3_SCSIOP_SET_TARGET_PORT_GROUPS 0xA4 +#define SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS 0xA +#define SPC3_RESERVATION_ACTION_REPORT_CAPABILITIES 0x2 + +#define SPC3_SCSI_ADSENSE_COMMANDS_CLEARED_BY_ANOTHER_INITIATOR 0x2F +#define SPC3_SCSI_ADSENSE_LOGICAL_UNIT_COMMAND_FAILED 0x67 + +#define SPC3_SCSI_SENSEQ_MODE_PARAMETERS_CHANGED 0x1 +#define SPC3_SCSI_SENSEQ_RESERVATIONS_PREEMPTED 0x3 +#define SPC3_SCSI_SENSEQ_RESERVATIONS_RELEASED 0x4 +#define SPC3_SCSI_SENSEQ_REGISTRATIONS_PREEMPTED 0x5 +#define SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_CHANGED 0x6 +#define SPC3_SCSI_SENSEQ_IMPLICIT_ASYMMETRIC_ACCESS_STATE_TRANSITION_FAILED 0x7 +#define SPC3_SCSI_SENSEQ_CAPACITY_DATA_HAS_CHANGED 0x9 +#define SPC3_SCSI_SENSEQ_ASYMMETRIC_ACCESS_STATE_TRANSITION 0xA +#define SPC3_SCSI_SENSEQ_TARGET_PORT_IN_STANDBY_STATE 0xB +#define SPC3_SCSI_SENSEQ_TARGET_PORT_IN_UNAVAILABLE_STATE 0xC + +#define SPC3_SCSI_SENSEQ_SET_TARGET_PORT_GROUPS_FAILED 0xA + +#define SPC3_SET_TARGET_PORT_GROUPS_TIMEOUT 10 +#define SPC3_REPORT_TARGET_PORT_GROUPS_TIMEOUT 10 + + +// +// Function prototypes for functions intrface.c +// + +DRIVER_INITIALIZE DriverEntry; +DRIVER_UNLOAD DsmDriverUnload; + +NTSTATUS +DsmInquire ( + _In_ IN PVOID DsmContext, + _In_ IN PDEVICE_OBJECT TargetDevice, + _In_ IN PDEVICE_OBJECT PortObject, + _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, + _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList, + _Out_ OUT PVOID *DsmIdentifier + ); + +BOOLEAN +DsmCompareDevices( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId1, + _In_ IN PVOID DsmId2 + ); + +NTSTATUS +DsmGetControllerInfo( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN ULONG Flags, + _Inout_ IN OUT PCONTROLLER_INFO *ControllerInfo + ); + +NTSTATUS +DsmSetDeviceInfo( + _In_ IN PVOID DsmContext, + _In_ IN PDEVICE_OBJECT TargetObject, + _In_ IN PVOID DsmId, + _Inout_ IN OUT PVOID *PathId + ); + +BOOLEAN +DsmIsPathActive( + _In_ IN PVOID DsmContext, + _In_ IN PVOID PathId, + _In_ IN PVOID DsmId + ); + +NTSTATUS +DsmPathVerify( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PVOID PathId + ); + +NTSTATUS +DsmInvalidatePath( + _In_ IN PVOID DsmContext, + _In_ IN ULONG ErrorMask, + _In_ IN PVOID PathId, + _Inout_ IN OUT PVOID *NewPathId + ); + +NTSTATUS +DsmMoveDevice( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PVOID MPIOPath, + _In_ IN PVOID SuggestedPath, + _In_ IN ULONG Flags + ); + +NTSTATUS +DsmRemovePending( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId + ); + +NTSTATUS +DsmRemoveDevice( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PVOID PathId + ); + +NTSTATUS +DsmRemovePath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PVOID PathId + ); + +NTSTATUS +DsmSrbDeviceControl( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ); + +PVOID +DsmLBGetPath( + _In_ IN PVOID DsmContext, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PDSM_IDS DsmList, + _In_ IN PVOID CurrentPath, + _Out_ OUT NTSTATUS *Status + ); + +ULONG +DsmInterpretError( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _Inout_ IN OUT NTSTATUS *Status, + _Out_ OUT PBOOLEAN Retry, + _Out_ OUT PLONG RetryInterval, + ... + ); + +NTSTATUS +DsmUnload( + _In_ IN PVOID DsmContext + ); + +VOID +DsmSetCompletion( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _Inout_ IN OUT PDSM_COMPLETION_INFO DsmCompletion + ); + +_Success_(return == DSM_PATH_SET) +ULONG +DsmCategorizeRequest( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PVOID CurrentPath, + _Outptr_result_maybenull_ OUT PVOID *PathId, + _Out_ OUT NTSTATUS *Status + ); + +NTSTATUS +DsmBroadcastRequest( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ); + +BOOLEAN +DsmIsAddressTypeSupported( + _In_ IN PVOID DsmContext, + _In_ IN ULONG AddressType + ); + +NTSTATUS +DsmDeviceNotUsed( + _In_ IN PVOID DsmContext, + _In_ IN PVOID DsmId + ); + + +// +// Function prototypes for functions in dsmmain.c +// + +VOID +DsmpFreeDSMResources( + _In_ IN PDSM_CONTEXT DsmContext + ); + +PDSM_GROUP_ENTRY +DsmpFindDevice( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN BOOLEAN AcquireDSMLockExclusive + ); + +PDSM_GROUP_ENTRY +DsmpBuildGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + +NTSTATUS +DsmpParseTargetPortGroupsInformation( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, + _In_ IN ULONG TargetPortGroupsInfoLength + ); + +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpFindTargetPortGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, + _In_ IN ULONG TPGs_BufferLength + ); + +_Success_(return!=0) +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpUpdateTargetPortGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, + _In_ IN ULONG TPGs_BufferLength, + _Out_ OUT PULONG DescriptorSize + ); + +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpBuildTargetPortGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_reads_bytes_(TPGs_BufferLength) IN PUCHAR TargetPortGroupsDescriptor, + _In_ IN ULONG TPGs_BufferLength, + _Out_ OUT PULONG DescriptorSize + ); + +PDSM_TARGET_PORT_LIST_ENTRY +DsmpFindTargetPortListEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN ULONG RelativeTargetPortId + ); + +PDSM_TARGET_PORT_LIST_ENTRY +DsmpBuildTargetPortListEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN ULONG RelativeTargetPortId + ); + +PDSM_TARGET_PORT_GROUP_ENTRY +DsmpFindTargetPortGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PUSHORT TargetPortGroupId + ); + +PDSM_TARGET_PORT_LIST_ENTRY +DsmpFindTargetPort( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN PULONG TargetPortGroupId + ); + +NTSTATUS +DsmpAddDeviceEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + +PDSM_CONTROLLER_LIST_ENTRY +DsmpFindControllerEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDEVICE_OBJECT PortObject, + _In_ IN PSCSI_ADDRESS ScsiAddress, + _In_reads_(ControllerSerialNumberLength) IN PSTR ControllerSerialNumber, + _In_ IN SIZE_T ControllerSerialNumberLength, + _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, + _In_ IN BOOLEAN AcquireLock + ); + +_Ret_maybenull_ +_Must_inspect_result_ +_When_(return != NULL, __drv_allocatesMem(Mem)) +PDSM_CONTROLLER_LIST_ENTRY +DsmpBuildControllerEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_opt_ IN PDEVICE_OBJECT DeviceObject, + _In_ IN PDEVICE_OBJECT PortObject, + _In_ IN PSCSI_ADDRESS ScsiAddress, + _In_ IN PSTR ControllerSerialNumber, + _In_ IN STORAGE_IDENTIFIER_CODE_SET CodeSet, + _In_ IN BOOLEAN AcquireLock + ); + +VOID +DsmpFreeControllerEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ __drv_freesMem(Mem) IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry + ); + +BOOLEAN +DsmpIsDeviceBelongsToController( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PDSM_CONTROLLER_LIST_ENTRY ControllerEntry + ); + +PDSM_DEVICE_INFO +DsmpFindDevInfoFromGroupAndFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_FAILOVER_GROUP FOGroup + ); + +PDSM_FAILOVER_GROUP +DsmpFindFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PVOID PathId + ); + +PDSM_FAILOVER_GROUP +DsmpBuildFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PVOID *PathId + ); + +NTSTATUS +DsmpUpdateFOGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_FAILOVER_GROUP FailGroup, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + +VOID +DsmpRemoveDeviceFailGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_FAILOVER_GROUP FailGroup, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN BOOLEAN AcquireDSMLockExclusive + ); + +ULONG +DsmpRemoveDeviceEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + +VOID +DsmpRemoveDeviceFromTargetPortList( + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + +PDSM_FAILOVER_GROUP +DsmpSetNewPath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDevice + ); + +PDSM_FAILOVER_GROUP +DsmpSetNewPathUsingGroup( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY Group + ); + +VOID +DsmpRemoveZombieGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY ZombieGroup + ); + +NTSTATUS +DsmpUpdateTargetPortGroupDevicesStates( + _In_ IN PDSM_TARGET_PORT_GROUP_ENTRY TargetPortGroup, + _In_ IN DSM_DEVICE_STATE NewState + ); + +VOID +DsmpIncrementCounters( + _In_ PDSM_FAILOVER_GROUP FailGroup, + _In_ PSCSI_REQUEST_BLOCK Srb + ); + +BOOLEAN +DsmpDecrementCounters( + _In_ PDSM_FAILOVER_GROUP FailGroup, + _In_ PSCSI_REQUEST_BLOCK Srb + ); + +PDSM_FAILOVER_GROUP +DsmpGetPath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmList, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN ULONG SpecialHandlingFlag + ); + +PVOID +DsmpGetPathIdFromPassThroughPath( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmList, + _In_ IN PIRP Irp, + _Inout_ IN OUT NTSTATUS *Status + ); + +VOID +DsmpRemoveGroupEntry( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_GROUP_ENTRY GroupEntry, + _In_ IN BOOLEAN AcquireDSMLockExclusive + ); + +BOOLEAN +DsmpMpioPassThroughPathCommand( + _In_ IN PIRP Irp + ); + +BOOLEAN +DsmpReservationCommand( + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb + ); + +VOID +DsmpRequestComplete( + _In_ IN PVOID DsmId, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PVOID DsmContext + ); + +NTSTATUS +DsmpRegisterPersistentReservationKeys( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN BOOLEAN Register + ); + + +BOOLEAN +DsmpShouldRetryPassThroughRequest( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ); + +BOOLEAN +DsmpShouldRetryPersistentReserveCommand( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ); + +BOOLEAN +DsmpShouldRetryTPGRequest( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ); + +BOOLEAN +DsmpIsDeviceRemoved( + _In_ IN PVOID SenseData, + _In_ IN UCHAR SenseDataSize + ); + +PDSM_DEVICE_INFO +DsmpGetActivePathToBeUsed( + _In_ PDSM_GROUP_ENTRY Group, + _In_ BOOLEAN Symmetric, + _In_ IN ULONG SpecialHandlingFlag + ); + +PDSM_DEVICE_INFO +DsmpGetAnyActivePath( + _In_ PDSM_GROUP_ENTRY Group, + _In_ BOOLEAN Exception, + _In_opt_ PDSM_DEVICE_INFO DeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ); + +PDSM_DEVICE_INFO +DsmpFindStandbyPathToActivate( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN ULONG SpecialHandlingFlag + ); + +PDSM_DEVICE_INFO +DsmpFindStandbyPathToActivateALUA( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PBOOLEAN SendTPG, + _In_ IN ULONG SpecialHandlingFlag + ); + +PDSM_DEVICE_INFO +DsmpFindStandbyPathInAlternateTpgALUA( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForDsmPolicyAdjustment( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ); + +NTSTATUS +DsmpSetLBForVidPidPolicyAdjustment( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PWSTR TargetHardwareId, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ); + +NTSTATUS +DsmpSetNewDefaultLBPolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_opt_ IN PDSM_DEVICE_INFO NewDeviceInfo, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForPathArrival( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForPathArrivalALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO NewDeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForPathRemoval( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, + _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForPathRemovalALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO RemovedDeviceInfo, + _In_opt_ IN OPTIONAL PDSM_GROUP_ENTRY Group, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForPathFailing( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, + _In_ IN BOOLEAN MarkDevInfoFailed, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetLBForPathFailingALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, + _In_ IN BOOLEAN MarkDevInfoFailed, + _In_ IN ULONG SpecialHandlingFlag + ); + +NTSTATUS +DsmpSetPathForIoRetryALUA( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO FailingDeviceInfo, + _In_ IN BOOLEAN TPGException, + _In_ IN BOOLEAN DeviceInfoException + ); + +PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY +DsmpFindFailPathDevInfoEntry( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO FailingDevInfo + ); + +PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY +DsmpBuildFailPathDevInfoEntry( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_DEVICE_INFO FailingDevInfo, + _In_ IN PDSM_DEVICE_INFO AlternateDevInfo + ); + +IO_COMPLETION_ROUTINE DsmpPhase1ProcessPathFailingALUA; + +NTSTATUS +DsmpRemoveFailPathDevInfoEntry( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN PDSM_FAIL_PATH_PROCESSING_LIST_ENTRY FailPathDevInfoEntry + ); + +IO_COMPLETION_ROUTINE DsmpPhase2ProcessPathFailingALUA; + +NTSTATUS +DsmpPersistentReserveOut( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ); + +__inline +BOOLEAN +DsmpIsPersistentReservationKeyZeroKey( + _In_ ULONG KeyLength, + _In_reads_bytes_(KeyLength) PUCHAR Key + ) +{ + BOOLEAN zeroKey = FALSE; + + NT_ASSERT(KeyLength == 8); + + if ((KeyLength) == 8 && + (Key[0] == 0 && Key[1] == 0 && Key[2] == 0 && Key[3] == 0 && + Key[4] == 0 && Key[5] == 0 && Key[6] == 0 && Key[7] == 0)) { + + zeroKey = TRUE; + } + + return zeroKey; +} + + +NTSTATUS +DsmpPersistentReserveIn( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN PSCSI_REQUEST_BLOCK Srb, + _In_ IN PKEVENT Event + ); + +IO_COMPLETION_ROUTINE DsmpPersistentReserveCompletion; + + +// +// Function prototypes for functions in utils.c +// + +_Success_(return != NULL) +__drv_allocatesMem(Mem) +_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) +_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) +_When_(((PoolType&0x2))!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))==0, + _Post_maybenull_ _Must_inspect_result_) +_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))!=0, + _Post_notnull_) +_When_((PoolType&NonPagedPoolMustSucceed)!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +_Post_writable_byte_size_(NumberOfBytes) +PVOID +DsmpAllocatePool( + _In_ _Strict_type_match_ IN POOL_TYPE PoolType, + _In_ IN SIZE_T NumberOfBytes, + _In_ IN ULONG Tag + ); + +_Success_(return != NULL) +_Post_maybenull_ +_Must_inspect_result_ +__drv_allocatesMem(Mem) +_Post_writable_byte_size_(*BytesAllocated) +_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) +_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) +_When_((PoolType&NonPagedPoolMustSucceed)!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +PVOID +DsmpAllocateAlignedPool( + _In_ IN POOL_TYPE PoolType, + _In_ IN SIZE_T NumberOfBytes, + _In_ IN ULONG AlignmentMask, + _In_ IN ULONG Tag, + _Out_ OUT SIZE_T *BytesAllocated + ); + +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +DsmpFreePool( + _In_opt_ __drv_freesMem(Mem) IN PVOID Block + ); + +NTSTATUS +DsmpGetStatsGatheringChoice( + _In_ IN PDSM_CONTEXT Context, + _Out_ OUT PULONG StatsGatherChoice + ); + +NTSTATUS +DsmpSetStatsGatheringChoice( + _In_ IN PDSM_CONTEXT Context, + _In_ IN ULONG StatsGatherChoice + ); + + +NTSTATUS +DsmpGetDeviceList( + _In_ IN PDSM_CONTEXT Context + ); + +_Success_(return==0) +NTSTATUS +DsmpGetStandardInquiryData( + _In_ IN PDEVICE_OBJECT DeviceObject, + _Out_ OUT PINQUIRYDATA InquiryData + ); + +BOOLEAN +DsmpCheckScsiCompliance( + _In_ IN PDEVICE_OBJECT DeviceObject, + _In_ IN PINQUIRYDATA InquiryData, + _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, + _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList + ); + +BOOLEAN +DsmpDeviceSupported( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PCSTR VendorId, + _In_ IN PCSTR ProductId + ); + +BOOLEAN +DsmpFindSupportedDevice( + _In_ IN PUNICODE_STRING DeviceName, + _In_ IN PUNICODE_STRING SupportedDevices + ); + +_Success_(return!=0) +PVOID +DsmpParseDeviceID ( + _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceID, + _In_ IN DSM_DEVID_TYPE DeviceIdType, + _In_opt_ IN PULONG IdNumber, + _Out_opt_ PSTORAGE_IDENTIFIER_CODE_SET CodeSet, + _In_ IN BOOLEAN Legacy + ); + +PUCHAR +DsmpBinaryToAscii( + _In_reads_(Length) IN PUCHAR HexBuffer, + _In_ IN ULONG Length, + _Inout_ IN OUT PULONG UpdateLength, + _In_ IN BOOLEAN Legacy + ); + +PSTR +DsmpGetSerialNumber( + _In_ IN PDEVICE_OBJECT DeviceObject + ); + + +NTSTATUS +DsmpDisableImplicitStateTransition( + _In_ IN PDEVICE_OBJECT DeviceObject, + _Out_ OUT PBOOLEAN DisableImplicit + ); + +PWSTR +DsmpBuildHardwareId( + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + +PWSTR +DsmpBuildDeviceNameLegacyPage0x80( + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ); + + +PWSTR +DsmpBuildDeviceName( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_reads_(SerialNumberLength) IN PSTR SerialNumber, + _In_ IN SIZE_T SerialNumberLength + ); + +NTSTATUS +DsmpApplyDeviceNameCorrection( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_reads_(DeviceNameLegacyLen) PWSTR DeviceNameLegacy, + _In_ IN SIZE_T DeviceNameLegacyLen, + _In_reads_(DeviceNameLen) PWSTR DeviceName, + _In_ IN SIZE_T DeviceNameLen + ); + +NTSTATUS +DsmpQueryDeviceLBPolicyFromRegistry( + _In_ PDSM_DEVICE_INFO DeviceInfo, + _In_ PWSTR RegistryKeyName, + _Inout_ PDSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Inout_ PULONGLONG PreferredPath, + _Inout_ PUCHAR ExplicitlySet + ); + +NTSTATUS +DsmpQueryTargetLBPolicyFromRegistry( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Out_ OUT PULONGLONG PreferredPath + ); + +NTSTATUS +DsmpQueryDsmLBPolicyFromRegistry( + _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Out_ OUT PULONGLONG PreferredPath + ); + +NTSTATUS +DsmpSetDsmLBPolicyInRegistry( + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ); + +NTSTATUS +DsmpSetVidPidLBPolicyInRegistry( + _In_ IN PWSTR TargetHardwareId, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ); + +NTSTATUS +DsmpOpenLoadBalanceSettingsKey( + _In_ IN ACCESS_MASK AccessMask, + _Out_ OUT PHANDLE LoadBalanceSettingsKey + ); + +NTSTATUS +DsmpOpenTargetsLoadBalanceSettingKey( + _In_ IN ACCESS_MASK AccessMask, + _Out_ OUT PHANDLE TargetsLoadBalanceSettingKey + ); + +NTSTATUS +DsmpOpenDsmServicesParametersKey( + _In_ IN ACCESS_MASK AccessMask, + _Out_ OUT PHANDLE ParametersSettingsKey + ); + +IO_COMPLETION_ROUTINE DsmpReportTargetPortGroupsSyncCompletion; + +_Success_(return==0) +NTSTATUS +DsmpReportTargetPortGroups( + _In_ PDEVICE_OBJECT DeviceObject, + _Outptr_result_buffer_maybenull_(*TargetPortGroupsInfoLength) PUCHAR *TargetPortGroupsInfo, + _Out_ PULONG TargetPortGroupsInfoLength + ); + +NTSTATUS +DsmpReportTargetPortGroupsAsync( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, + _Inout_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, + _In_ IN ULONG TargetPortGroupsInfoLength, + _Inout_ __drv_aliasesMem IN OUT PUCHAR TargetPortGroupsInfo + ); + +NTSTATUS +DsmpQueryLBPolicyForDevice( + _In_ IN PWSTR RegistryKeyName, + _In_ IN ULONGLONG PathId, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Out_ OUT PULONG PrimaryPath, + _Out_ OUT PULONG OptimizedPath, + _Out_ OUT PULONG PathWeight + ); + +VOID +DsmpGetDSMPathKeyName( + _In_ ULONGLONG DSMPathId, + _Out_writes_(DsmPathKeyNameSize) PWCHAR DsmPathKeyName, + _In_ ULONG DsmPathKeyNameSize + ); + +UCHAR +DsmpGetAsciiForBinary( + _In_ UCHAR BinaryChar + ); + +NTSTATUS +DsmpGetDeviceIdList ( + _In_ IN PDEVICE_OBJECT DeviceObject, + _Out_ OUT PSTORAGE_DESCRIPTOR_HEADER *Descriptor + ); + +NTSTATUS +DsmpSetTargetPortGroups( + _In_ IN PDEVICE_OBJECT DeviceObject, + _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, + _In_ IN ULONG TargetPortGroupsInfoLength + ); + +NTSTATUS +DsmpSetTargetPortGroupsAsync( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, + _In_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, + _In_ IN ULONG TargetPortGroupsInfoLength, + _In_ __drv_aliasesMem IN PUCHAR TargetPortGroupsInfo + ); + +PDSM_LOAD_BALANCE_POLICY_SETTINGS +DsmpCopyLoadBalancePolicies( + _In_ IN PDSM_GROUP_ENTRY GroupEntry, + _In_ IN ULONG DsmWmiVersion, + _In_ IN PVOID SupportedLBPolicies + ); + +NTSTATUS +DsmpPersistLBSettings( + _In_ IN PDSM_LOAD_BALANCE_POLICY_SETTINGS LoadBalanceSettings + ); + +NTSTATUS +DsmpSetDeviceALUAState( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN DSM_DEVICE_STATE DevState + ); + +NTSTATUS +DsmpGetDeviceALUAState( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_opt_ IN PDSM_DEVICE_STATE DevState + ); + +NTSTATUS +DsmpAdjustDeviceStatesALUA( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_opt_ IN PDSM_DEVICE_INFO PreferredActiveDeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ); + +PDSM_WORKITEM +DsmpAllocateWorkItem( + _In_ IN PDEVICE_OBJECT DeviceObject, + _In_ IN PVOID Context + ); + +VOID +DsmpFreeWorkItem( + _In_ IN PDSM_WORKITEM DsmWorkItem + ); + +VOID +DsmpFreeZombieGroupList( + _In_ IN PDSM_FAILOVER_GROUP FailGroup + ); + +NTSTATUS +DsmpRegCopyTree( + _In_ IN HANDLE SourceKey, + _In_ IN HANDLE DestKey + ); + +NTSTATUS +DsmpRegDeleteTree( + _In_ IN HANDLE KeyRoot + ); + +#if defined (_WIN64) +VOID +DsmpPassThroughPathTranslate32To64( + _In_ IN PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32, + _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64 + ); + +VOID +DsmpPassThroughPathTranslate64To32( + _In_ IN PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64, + _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32 + ); +#endif + +NTSTATUS +DsmpGetMaxPRRetryTime( + _In_ IN PDSM_CONTEXT Context, + _Out_ OUT PULONG RetryTime + ); + +NTSTATUS +DsmpQueryCacheInformationFromRegistry( + _In_ IN PDSM_CONTEXT DsmContext, + _Out_ OUT PBOOLEAN UseCacheForLeastBlocks, + _Out_ OUT PULONGLONG CacheSizeForLeastBlocks + ); + +BOOLEAN +DsmpConvertSharedSpinLockToExclusive( + _Inout_ _Requires_lock_held_(*_Curr_) PEX_SPIN_LOCK SpinLock + ); + + +// +// Function prototypes for functions in wmi.c +// + +VOID +DsmpDsmWmiInitialize( + _In_ IN PDSM_WMILIB_CONTEXT WmiGlobalInfo, + _In_ IN PUNICODE_STRING RegistryPath + ); + +NTSTATUS +DsmGlobalQueryData( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG InstanceCount, + _Inout_ IN OUT PULONG InstanceLengthArray, + _In_ IN ULONG BufferAvail, + _Out_writes_to_(BufferAvail, *DataLength) OUT PUCHAR Buffer, + _Out_ OUT PULONG DataLength, + ... + ); + +NTSTATUS +DsmGlobalSetData( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG BufferAvail, + _In_reads_bytes_(BufferAvail) IN PUCHAR Buffer, + ... + ); + +VOID +DsmpWmiInitialize( + _In_ IN PDSM_WMILIB_CONTEXT WmiInfo, + _In_ IN PUNICODE_STRING RegistryPath + ); + +NTSTATUS +DsmQueryData( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG InstanceCount, + _Inout_ IN OUT PULONG InstanceLengthArray, + _In_ IN ULONG BufferAvail, + _When_(GuidIndex == 0 || GuidIndex == 7, _Pre_notnull_ _Const_) + _When_(!(GuidIndex == 0 || GuidIndex == 7), _Out_writes_to_(BufferAvail, *DataLength)) + OUT PUCHAR Buffer, + _Out_ OUT PULONG DataLength, + ... + ); + +NTSTATUS +DsmpQueryLoadBalancePolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG DsmWmiVersion, + _In_ IN ULONG InBufferSize, + _In_ IN PULONG OutBufferSize, + _Out_writes_bytes_(*OutBufferSize) OUT PVOID Buffer + ); + +NTSTATUS +DsmpQuerySupportedLBPolicies( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG BufferAvail, + _In_ IN ULONG DsmWmiVersion, + _Out_ OUT PULONG OutBufferSize, + _Out_writes_to_(BufferAvail, *OutBufferSize) OUT PUCHAR Buffer + ); + +NTSTATUS +DsmExecuteMethod( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG MethodId, + _In_ IN ULONG InBufferSize, + _In_ IN PULONG OutBufferSize, + _Inout_ IN OUT PUCHAR Buffer, + ... + ); + +NTSTATUS +DsmpClearLoadBalancePolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds + ); + +NTSTATUS +DsmpSetLoadBalancePolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG DsmWmiVersion, + _In_ IN ULONG InBufferSize, + _In_ IN PULONG OutBufferSize, + _In_ IN PVOID Buffer + ); + +NTSTATUS +DsmpValidateSetLBPolicyInput( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG DsmWmiVersion, + _In_ IN PVOID SetLoadBalancePolicyIN, + _In_ IN ULONG InBufferSize + ); + +VOID +DsmpSaveDeviceState( + _In_ IN PVOID SupportedLBPolicies, + _In_ IN ULONG DsmWmiVersion + ); + +VOID +DsmpRestorePreviousDeviceState( + _In_ IN PVOID SupportedLBPolicies, + _In_ IN ULONG DsmWmiVersion + ); + +VOID +DsmpUpdateDesiredStateAndWeight( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN ULONG DsmWmiVersion, + _In_ IN PVOID SupportedLBPolicies + ); + +NTSTATUS +DsmpQueryDevicePerf( + _In_ PDSM_CONTEXT DsmContext, + _In_ PDSM_IDS DsmIds, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ); + +NTSTATUS +DsmpClearPerfCounters( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds + ); + +NTSTATUS +DsmpQuerySupportedDevicesList( + _In_ PDSM_CONTEXT DsmContext, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ); + +NTSTATUS +DsmpQueryTargetsDefaultPolicy( + _In_ PDSM_CONTEXT DsmContext, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ); + +NTSTATUS +DsmpQueryDsmDefaultPolicy( + _In_ PDSM_CONTEXT DsmContext, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ); + + +// +// Function prototypes for functions in debug.c +// + +VOID +DsmpDebugPrint( + _In_ ULONG DebugPrintLevel, + _In_ PCCHAR DebugMessage, + ... + ); + +// +// SRB Helpers not found in srbhelper.h +// +_Success_(return != 0) +__drv_allocatesMem(mem) +_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) +_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) +_When_(((PoolType&0x2))!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))==0, + _Post_maybenull_ _Must_inspect_result_) +_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))!=0, + _Post_notnull_ ) +__inline PSTORAGE_REQUEST_BLOCK_HEADER +SrbAllocateCopy( + _Inout_ PVOID Srb, + _In_ _Strict_type_match_ POOL_TYPE PoolType, + _In_ ULONG Tag + ) +/* + +Description: + This function returns an allocated copy of the given SRB. The memory is + allocated using DsmpAllocatePool(). + + ***It is up to the caller to free the memory returned by this function.*** + +Arguments: + Srb - A pointer to either a STORAGE_REQUEST_BLOCK or a SCSI_REQUEST_BLOCK. + PoolType - The pool type to use. See documentation for ExAllocatePoolWithTag(). + Tag - The allocation tag to use. See documentation for ExAllocatePoolWithTag(). + +Returns: + NULL, if the copy could not be allocated; or + A pointer to either a STORAGE_REQUEST_BLOCK or a SCSI_REQUEST_BLOCK that is + direct copy of the given SRB. + +*/ +{ + PSTORAGE_REQUEST_BLOCK srb = (PSTORAGE_REQUEST_BLOCK)Srb; + PSTORAGE_REQUEST_BLOCK_HEADER srbCopy = NULL; + ULONG allocationSize = 0; + + if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) + { + allocationSize = srb->SrbLength; + NT_ASSERT(allocationSize >= (sizeof(STORAGE_REQUEST_BLOCK) + sizeof(STOR_ADDR_BTL8))); + } + else + { + allocationSize = SCSI_REQUEST_BLOCK_SIZE; + NT_ASSERT(allocationSize >= sizeof(SCSI_REQUEST_BLOCK)); + } + + #pragma warning(suppress: 28160 28118) // False-positive; PoolType is simply passed through + srbCopy = (PSTORAGE_REQUEST_BLOCK_HEADER)DsmpAllocatePool(PoolType, allocationSize, Tag); + if (srbCopy != NULL) + { + RtlCopyMemory(srbCopy, Srb, allocationSize); + } + + return srbCopy; +} + +__inline +BOOLEAN DsmpIsMPIOPassThroughEx( + ULONG ControlCode + ) +// +// Returns TRUE if the given passthrough IOCTL's control code indicates it is +// an "extended" passthrough. Returns FALSE otherwise. +// +{ + if (ControlCode == IOCTL_MPIO_PASS_THROUGH_PATH_EX || + ControlCode == IOCTL_MPIO_PASS_THROUGH_PATH_DIRECT_EX) { + return TRUE; + } else { + return FALSE; + } +} + +__inline +UCHAR DsmpNtStatusToSrbStatus( + _In_ NTSTATUS Status + ) +/*++ + +Routine Description: + + Translate an NT status value into a SCSI Srb status code. + +Arguments: + + Status - Supplies the NT status code to translate. + +Return Value: + + SRB status code. + +--*/ +{ + switch (Status) { + + case STATUS_DEVICE_BUSY: + return SRB_STATUS_BUSY; + + case STATUS_INVALID_DEVICE_REQUEST: + return SRB_STATUS_BAD_FUNCTION; + + case STATUS_INSUFFICIENT_RESOURCES: + return SRB_STATUS_INTERNAL_ERROR; + + case STATUS_INVALID_PARAMETER: + return SRB_STATUS_INVALID_REQUEST; + + default: + if (NT_SUCCESS (Status)) { + return SRB_STATUS_SUCCESS; + } else { + return SRB_STATUS_ERROR; + } + } +} + + +#endif // _PROTOTYPES_H_ + diff --git a/tests/projects/windows/driver/wdm/msdsm/trace.h b/tests/projects/windows/driver/wdm/msdsm/trace.h new file mode 100644 index 000000000..b9449cc8f --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/trace.h @@ -0,0 +1,35 @@ + +/*++ + +Copyright (C) 2004 Microsoft Corporation + +Module Name: + + trace.h + +Abstract: + + Header file included by the Microsoft Device Specific Module (DSM). + + This file contains Windows tracing related defines. + +Environment: + + kernel mode only + +Notes: + +--*/ + +// +// Set component ID for DbgPrintEx calls +// +#define DEBUG_COMP_ID DPFLTR_MSDSM_ID + +// +// Include header file and setup GUID for tracing +// +#include +#define WPP_GUID_MSDSM (DEDADFF5, F99F, 4600, B8C9, 2D4D9B806B5B) +#define WPP_CONTROL_GUIDS WPP_CONTROL_GUIDS_NORMAL_FLAGS(WPP_GUID_MSDSM) + diff --git a/tests/projects/windows/driver/wdm/msdsm/utils.c b/tests/projects/windows/driver/wdm/msdsm/utils.c new file mode 100644 index 000000000..91d8f44ce --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/utils.c @@ -0,0 +1,7946 @@ + +/*++ + +Copyright (C) 2004-2010 Microsoft Corporation + +Module Name: + + utils.c + +Abstract: + + This driver is the Microsoft Device Specific Module (DSM). + It exports behaviours that mpio.sys will use to determine how to + multipath SPC-3 compliant devices. + + This file contains utility routines. + +Environment: + + kernel mode only + +Notes: + +--*/ + +#include "precomp.h" + +#ifdef DEBUG_USE_WPP +#include "utils.tmh" +#endif + +#pragma warning (disable:4305) + +extern BOOLEAN DoAssert; + +#ifdef ALLOC_PRAGMA + #pragma alloc_text(PAGE, DsmpBuildDeviceNameLegacyPage0x80) + #pragma alloc_text(PAGE, DsmpBuildDeviceName) + #pragma alloc_text(PAGE, DsmpApplyDeviceNameCorrection) + #pragma alloc_text(PAGE, DsmpOpenLoadBalanceSettingsKey) + #pragma alloc_text(PAGE, DsmpQueryLBPolicyForDevice) + #pragma alloc_text(PAGE, DsmpOpenTargetsLoadBalanceSettingKey) + #pragma alloc_text(PAGE, DsmpOpenDsmServicesParametersKey) +#endif + +_Success_(return != NULL) +__drv_allocatesMem(Mem) +_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) +_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) +_When_(((PoolType&0x2))!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))==0, + _Post_maybenull_ _Must_inspect_result_) +_When_(((PoolType&(0x2|POOL_RAISE_IF_ALLOCATION_FAILURE)))!=0, + _Post_notnull_ ) +_When_((PoolType&NonPagedPoolMustSucceed)!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +_Post_writable_byte_size_(NumberOfBytes) +PVOID +DsmpAllocatePool( + _In_ _Strict_type_match_ IN POOL_TYPE PoolType, + _In_ IN SIZE_T NumberOfBytes, + _In_ IN ULONG Tag + ) +/*+++ + +Routine Description : + + Allocates memory from the specified pool using the given tag. + If the allocation is successful, the entire buffer will be zeroed. + +Arguements: + + PoolType - Pool to allocate from (NonPaged, Paged, etc) + NumberOfBytes - Size of the buffer to allocate + Tag - Tag (DSM_TAG_XXX) to be used for this allocation. + These tags are defined in msdsm.h + +Return Value: + + Pointer to the buffer if allocation is successful + NULL otherwise + +--*/ +{ + PVOID Block = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpAllocatePool (Tag %u): Entering function.\n", + Tag)); + + #pragma warning(suppress: 28118) // False-positive; PoolType is simply passed through + Block = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); + if (Block) { + RtlZeroMemory(Block, NumberOfBytes); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpAllocatePool (Tag %u): Exiting function with allocated block %p.\n", + Tag, + Block)); + + return Block; +} + + +_Success_(return != NULL) +_Post_maybenull_ +_Must_inspect_result_ +__drv_allocatesMem(Mem) +_Post_writable_byte_size_(*BytesAllocated) +_When_(((PoolType&0x1))!=0, _IRQL_requires_max_(APC_LEVEL)) +_When_(((PoolType&0x1))==0, _IRQL_requires_max_(DISPATCH_LEVEL)) +_When_((PoolType&NonPagedPoolMustSucceed)!=0, + __drv_reportError("Must succeed pool allocations are forbidden. " + "Allocation failures cause a system crash")) +PVOID +#pragma warning(suppress:28195) // Allocation is not guaranteed, caller needs to check return value +DsmpAllocateAlignedPool( + _In_ IN POOL_TYPE PoolType, + _In_ IN SIZE_T NumberOfBytes, + _In_ IN ULONG AlignmentMask, + _In_ IN ULONG Tag, + _Out_ OUT SIZE_T *BytesAllocated + ) +/*+++ + +Routine Description : + + Allocates memory from the specified pool using the given tag and alignment requirement. + If the allocation is successful, the entire buffer will be zeroed. + +Arguements: + + PoolType - Pool to allocate from (NonPaged, Paged, etc) + NumberOfBytes - Size of the buffer to allocate + AlignmentMask - Alignment requirement specified by the device + Tag - Tag (DSM_TAG_XXX) to be used for this allocation. + These tags are defined in msdsm.h + BytesAllocated - Returns the number of bytes allocated, if the routine was successful + +Return Value: + + Pointer to the buffer if allocation is successful + NULL otherwise + +--*/ +{ + PVOID Block = NULL; + UINT_PTR align64 = (UINT_PTR)AlignmentMask; + ULONG totalSize = (ULONG)NumberOfBytes; + NTSTATUS status = STATUS_SUCCESS; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpAllocateAlignedPool (Tag %u): Entering function.\n", + Tag)); + + if (BytesAllocated == NULL) { + + status = STATUS_INVALID_PARAMETER; + goto __Exit; + } + + *BytesAllocated = 0; + + if (AlignmentMask) { + + status = RtlULongAdd((ULONG)NumberOfBytes, AlignmentMask, &totalSize); + } + + if (NT_SUCCESS(status)) { + + #pragma warning(suppress: 6014 28118) // Block isn't leaked, this function is marked as an allocator; PoolType is simply passed through + Block = ExAllocatePoolWithTag(PoolType, totalSize, Tag); + + if (Block != NULL) { + + if (AlignmentMask) { + + Block = (PVOID)(((UINT_PTR)Block + align64) & ~align64); + } + } else { + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + +__Exit: + + if (NT_SUCCESS(status)) { + + RtlZeroMemory(Block, totalSize); + *BytesAllocated = totalSize; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpAllocateAlignedPool (Tag %u): Exiting function with allocated block %p.\n", + Tag, + Block)); + + return Block; +} + + +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +DsmpFreePool( + _In_opt_ __drv_freesMem(Mem) IN PVOID Block + ) +/*+++ + +Routine Description : + + Frees the block passed in. + +Arguements: + + Block - pointer to the memory to free. + +Return Value: + + Nothing + +--*/ +{ + PVOID tempAddress = Block; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFreePool (Block %p): Entering function.\n", + Block)); + + if (Block) { + + ExFreePool(Block); + Block = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFreePool (Block %p): Exiting function.\n", + tempAddress)); + + return; +} + + +NTSTATUS +DsmpGetStatsGatheringChoice( + _In_ IN PDSM_CONTEXT Context, + _Out_ OUT PULONG StatsGatherChoice + ) +/*++ + +Routine Description: + + This routine is used to determine if the Admin wants statitics to be collected + on every IO. It queries the the services key for the value under + "msdsm\Parameters\DsmDisableStatistics" + +Arguments: + + Context - The DSM Context value. + StatsGatherChoice - Returns the choice of whether or not to gather statistics + +Return Value: + + Status of the RtlQueryRegistryValues call. + +--*/ +{ + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + WCHAR registryKeyName[56] = {0}; + NTSTATUS status = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetStatsGatherChoice (DsmCtxt %p): Entering function.\n", + Context)); + + if (!StatsGatherChoice) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "DsmpGetStatsGatherChoice (DsmCtxt %p): Invalid parameter - StatsGatherChoice is NULL.\n", + Context)); + + goto __Exit_DsmpGetStatsGatherChoice; + } + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + // + // Build the key value name that we want as the base of the query. + // + RtlStringCbPrintfW(registryKeyName, + sizeof(registryKeyName), + DSM_PARAMETER_PATH_W); + + // + // The query table has two entries. One for the supporteddeviceList and + // the second which is the 'NULL' terminator. + // + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_DISABLE_STATISTICS; + queryTable[0].EntryContext = StatsGatherChoice; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + registryKeyName, + queryTable, + registryKeyName, + NULL); + +__Exit_DsmpGetStatsGatherChoice: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetStatsGatherChoice (DsmCtxt %p): Exiting function with status %x.\n", + Context, + status)); + + return status; +} + + +NTSTATUS +DsmpSetStatsGatheringChoice( + _In_ IN PDSM_CONTEXT Context, + _In_ IN ULONG StatsGatherChoice + ) +/*++ + +Routine Description: + + This routine is used to set the value that indicates whether statistics will + be gathered on every IO. It updates the services key for the value under + "msdsm\Parameters\DsmDisableStatistics" + +Arguments: + + Context - The DSM Context value. + StatsGatherChoice - Value indicating whether to gather statistics (TRUE) or not (FALSE) + +Return Value: + + Status of the RtlWriteRegistryValue call. + +--*/ +{ + WCHAR registryKeyName[56] = {0}; + NTSTATUS status = STATUS_SUCCESS; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetStatsGatherChoice (DsmCtxt %p): Entering function.\n", + Context)); + + // + // Build the key value name that we want as the base of the query. + // + RtlStringCbPrintfW(registryKeyName, + sizeof(registryKeyName), + DSM_PARAMETER_PATH_W); + + + status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, + registryKeyName, + DSM_DISABLE_STATISTICS, + REG_DWORD, + &StatsGatherChoice, + sizeof(ULONG)); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetStatsGatherChoice (DsmCtxt %p): Exiting function with status %x.\n", + Context, + status)); + + return status; +} + + + +NTSTATUS +DsmpGetDeviceList( + _In_ IN PDSM_CONTEXT Context + ) +/*++ + +Routine Description: + + This routine is used to build the supported device list by querying the services + key for the values under "msdsm\Parameters\DsmSupportedDeviceList" + +Arguments: + + Context - The DSM Context value. It contains storage for the multi_sz string that may + be built. + +Return Value: + + Status of the RtlQueryRegistryValues call. + +--*/ +{ + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + WCHAR registryKeyName[56] = {0}; + UNICODE_STRING inquiryStrings; + WCHAR defaultIDs[] = { L"\0" }; + NTSTATUS status; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetDeviceList (DsmCtxt %p): Entering function.\n", + Context)); + + RtlZeroMemory(queryTable, sizeof(queryTable)); + RtlInitUnicodeString(&inquiryStrings, NULL); + + // + // Build the key value name that we want as the base of the query. + // + RtlStringCbPrintfW(registryKeyName, + sizeof(registryKeyName), + DSM_PARAMETER_PATH_W); + + // + // The query table has two entries. One for the supporteddeviceList and + // the second which is the 'NULL' terminator. + // + // Indicate that there is NO call-back routine, and to give back the MULTI_SZ as + // one blob, as opposed to individual unicode strings. + // + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_NOEXPAND | RTL_QUERY_REGISTRY_TYPECHECK; + + // + // The value to query. + // + queryTable[0].Name = DSM_SUPPORTED_DEVICELIST_VALUE_NAME; + + // + // Where to put the strings. Note that we need to use an empty unicode_string + // for the query or else RtlQueryRegistryValues will only fill in enough + // entries as specified by the size of the unicode string's buffer, which + // is why we can't use Context->SupportedDevices directly in the call. + // + queryTable[0].EntryContext = &inquiryStrings; + queryTable[0].DefaultType = (REG_MULTI_SZ << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_MULTI_SZ; + queryTable[0].DefaultData = defaultIDs; + queryTable[0].DefaultLength = sizeof(defaultIDs); + + status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + registryKeyName, + queryTable, + registryKeyName, + NULL); + + // + // If we successfully queried for the supported device list, we need to delete + // our cached list and update it with this new one. + // + if (NT_SUCCESS(status)) { + + KIRQL oldIrql; + PWCHAR tempBuffer = NULL; + + tempBuffer = DsmpAllocatePool(NonPagedPoolNx, inquiryStrings.MaximumLength, DSM_TAG_REG_VALUE_RELATED); + + // + // This is a "best effort" operation. If we are unable to allocate a + // buffer for the strings, we just continue using our old cached list. + // We do NOT fall back to using inquiryStrings's buffer as we want to + // be able to work with the supported devices list at raised IRQL. + // + if (tempBuffer) { + + RtlCopyMemory(tempBuffer, inquiryStrings.Buffer, inquiryStrings.Length); + + KeAcquireSpinLock(&Context->SupportedDevicesListLock, &oldIrql); + DsmpFreePool(Context->SupportedDevices.Buffer); + Context->SupportedDevices.Buffer = tempBuffer; + Context->SupportedDevices.Length = inquiryStrings.Length; + Context->SupportedDevices.MaximumLength = inquiryStrings.MaximumLength; + KeReleaseSpinLock(&Context->SupportedDevicesListLock, oldIrql); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetDeviceList (DsmCtxt %p): Failed to allocate supported device list's buffer.\n", + Context)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + + ExFreePool(inquiryStrings.Buffer); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetDeviceList (DsmCtxt %p): Exiting function with status %x.\n", + Context, + status)); + + return status; +} + + +_Success_(return==0) +NTSTATUS +DsmpGetStandardInquiryData( + _In_ IN PDEVICE_OBJECT DeviceObject, + _Out_ OUT PINQUIRYDATA InquiryData + ) +/*++ + +Routine Description: + + Helper routine to send an inquiry with EVPD cleared to get the standard inquiry data. + +Arguments: + + DeviceObject - The port PDO to which the command should be sent. + InquiryData - Pointer to inquiry data that will be returned to caller. + +Return Value: + + STATUS_SUCCESS or failure NTSTATUS code. + +--*/ +{ + PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; + PCDB cdb; + IO_STATUS_BLOCK ioStatus; + ULONG length; + NTSTATUS status = STATUS_SUCCESS; + PINQUIRYDATA inquiryData; + PSENSE_DATA senseData; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetStandardInquiryData (DevObj %p): Entering function.\n", + DeviceObject)); + + if (InquiryData == NULL) { + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpGetStandardInquiryData; + } + + // + // Build a standard inquiry command. + // + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + passThrough = DsmpAllocatePool(NonPagedPoolNx, + length, + DSM_TAG_PASS_THRU); + if (!passThrough) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetStandardInquiryData (DevObj %p): Failed to allocate mem for passthrough.\n", + DeviceObject)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpGetStandardInquiryData; + } + +__Retry_Request: + + // + // Build the cdb for SCSI-3 standard inquiry. + // + cdb = (PCDB)passThrough->ScsiPassThrough.Cdb; + cdb->CDB6INQUIRY3.OperationCode = SCSIOP_INQUIRY; + cdb->CDB6INQUIRY3.EnableVitalProductData = 0; + cdb->CDB6INQUIRY3.AllocationLength = sizeof(INQUIRYDATA); + + passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); + passThrough->ScsiPassThrough.CdbLength = 6; + passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; + passThrough->ScsiPassThrough.DataIn = 1; + passThrough->ScsiPassThrough.DataTransferLength = sizeof(INQUIRYDATA); + passThrough->ScsiPassThrough.TimeOutValue = 20; + passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); + passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); + + DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, + DeviceObject, + passThrough, + passThrough, + length, + length, + FALSE, + &ioStatus); + + status = ioStatus.Status; + senseData = (PSENSE_DATA)(passThrough->SenseInfoBuffer); + + if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(status))) { + + // + // Get the returned data. + // + inquiryData = (PINQUIRYDATA)(passThrough->DataBuffer); + + RtlCopyMemory(InquiryData, inquiryData, sizeof(INQUIRYDATA)); + + } else if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_CHECK_CONDITION) && + (NT_SUCCESS(ioStatus.Status)) && + (DsmpShouldRetryPassThroughRequest(senseData, passThrough->ScsiPassThrough.SenseInfoLength))) { + + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + // + // Retry the request + // + RtlZeroMemory(passThrough, length); + goto __Retry_Request; + + } else { + + // Failed to get inquiry data + // Here it is possible that status is success, but scsi status is not. + // If so, set status to unsuccessful. + if (NT_SUCCESS(status)){ + status = STATUS_UNSUCCESSFUL; + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetStandardInquiryData (DevObj %p): NTStatus 0x%x, ScsiStatus 0x%x.\n", + DeviceObject, + status, + passThrough->ScsiPassThrough.ScsiStatus)); + } + +__Exit_DsmpGetStandardInquiryData: + + // + // Free the passthrough + data buffer. + // + if (passThrough) { + DsmpFreePool(passThrough); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetStandardInquiryData (DevObj %p): Exiting function with status %x.\n", + DeviceObject, + status)); + + return status; +} + + +BOOLEAN +DsmpCheckScsiCompliance( + _In_ IN PDEVICE_OBJECT TargetObject, + _In_ IN PINQUIRYDATA InquiryData, + _In_ IN PSTORAGE_DEVICE_DESCRIPTOR Descriptor, + _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceIdList + ) +/*++ + +Routine Description: + + Helper routine to determine if the device is SPC-3 compliant. + +Arguments: + + DeviceObject - The port PDO that we're determining compliance for. + InquiryData - Pointer to its inquiry data. + Descriptor - Pointer to its VPD page 0x80 data + DeviceIdList - Pointer to its VPD page 0x83 data + +Return Value: + + TRUE if compliant, else FALSE. + +--*/ +{ + BOOLEAN supported = FALSE /* TRUE */; + UCHAR deviceType; + UCHAR qualifier; + + UNREFERENCED_PARAMETER(DeviceIdList); + UNREFERENCED_PARAMETER(Descriptor); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpCheckScsiCompliance (DevObj %p): Entering function.\n", + TargetObject)); + + deviceType = InquiryData->DeviceType & 0x1F; + qualifier = (InquiryData->DeviceTypeQualifier >> 0x5) & 0x7; + + if ((deviceType | qualifier) == 0x7F) { + + supported = FALSE; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpCheckScsiCompliance (DevObj %p): Exiting function with Supported = %u.\n", + TargetObject, + supported)); + + return supported; +} + + +BOOLEAN +DsmpDeviceSupported( + _In_ IN PDSM_CONTEXT Context, + _In_ IN PCSTR VendorId, + _In_ IN PCSTR ProductId + ) +/*++ + +Routine Description: + + This routine determines whether the device is supported by traversing the SupportedDevice + list and comparing to the VendorId/ProductId values passed in. + +Arguments: + + Context - Context value given to the multipath driver during registration. + VendorId - Pointer to the inquiry data VendorId. + ProductId - Pointer to the inquiry data ProductId. + +Return Value: + + TRUE - If VendorId/ProductId is found. + +--*/ +{ + UNICODE_STRING deviceName; + UNICODE_STRING productName; + ANSI_STRING ansiVendor; + ANSI_STRING ansiProduct; + NTSTATUS status; + BOOLEAN supported = FALSE; + KIRQL oldIrql; + UNICODE_STRING tempStrings; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpDeviceSupported (DsmCtxt %p): Entering function.\n", + Context)); + + KeAcquireSpinLock(&Context->SupportedDevicesListLock, &oldIrql); + + RtlInitUnicodeString(&tempStrings, NULL); + tempStrings.Buffer = DsmpAllocatePool(NonPagedPoolNx, Context->SupportedDevices.MaximumLength, DSM_TAG_REG_VALUE_RELATED); + + if (tempStrings.Buffer) { + + RtlCopyMemory(tempStrings.Buffer, Context->SupportedDevices.Buffer, Context->SupportedDevices.Length); + tempStrings.Length = Context->SupportedDevices.Length; + tempStrings.MaximumLength = Context->SupportedDevices.MaximumLength; + + } else { + + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpDeviceSupported (DsmCtxt %p): Failed to allocate temporary list (error %x).\n", + Context, + status)); + + KeReleaseSpinLock(&Context->SupportedDevicesListLock, oldIrql); + + goto __Exit_DsmpDeviceSupported; + } + + KeReleaseSpinLock(&Context->SupportedDevicesListLock, oldIrql); + + // + // The SupportedDevice list was built in DriverEntry from the services key. + // + if (tempStrings.MaximumLength == 0) { + + // + // List is empty. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDeviceSupported (DsmCtxt %p): No supported Device in the list.\n", + Context)); + + goto __Exit_DsmpDeviceSupported; + } + + RtlInitUnicodeString(&productName, NULL); + + // + // Convert the inquiry fields into ansi strings. + // + RtlInitAnsiString(&ansiVendor, VendorId); + RtlInitAnsiString(&ansiProduct, ProductId); + + // + // Allocate the deviceName buffer. Needs to be 8+16 plus NULL. + // (productId length + vendorId length + NULL). + // + deviceName.MaximumLength = 25 * sizeof(WCHAR); + deviceName.Buffer = DsmpAllocatePool(PagedPool, deviceName.MaximumLength, DSM_TAG_SUPPORTED_DEV); + + if (deviceName.Buffer) { + + // + // Convert the vendorId to unicode. + // + status = RtlAnsiStringToUnicodeString(&deviceName, &ansiVendor, FALSE); + if (NT_SUCCESS(status)) { + + // + // Convert the productId to unicode. + // + status = RtlAnsiStringToUnicodeString(&productName, &ansiProduct, TRUE); + + if (NT_SUCCESS(status)) { + + // + // 'cat' them. + // + status = RtlAppendUnicodeStringToString(&deviceName, &productName); + + if (NT_SUCCESS(status)) { + + // + // Run the list of supported devices that was captured from the registry + // and see if this one is in the list. + // + supported = DsmpFindSupportedDevice(&deviceName, + &tempStrings); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDeviceSupported (DsmCtxt %p): Failed to append product name. Status %x.\n", + Context, + status)); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDeviceSupported (DsmCtxt %p): Failed to convert ansi vendor string to unicode. Status %x\n", + Context, + status)); + } + + DsmpFreePool(deviceName.Buffer); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDeviceSupported (DsmCtxt %p): Failed to allocate device name buffer.\n", + Context)); + } + +__Exit_DsmpDeviceSupported: + + if (tempStrings.Buffer) { + DsmpFreePool(tempStrings.Buffer); + } + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpDeviceSupported (DsmCtxt %p): Exiting function with supported = %u.\n", + Context, + supported)); + + return supported; +} + + +BOOLEAN +DsmpFindSupportedDevice( + _In_ IN PUNICODE_STRING DeviceName, + _In_ IN PUNICODE_STRING SupportedDevices + ) +/*++ + +Routine Description: + + This routine compares the two unicode strings for a match. + +Arguments: + + DeviceName - String built from the current device's inquiry data. + SupportedDevices - MULTI_SZ of devices that are supported. + +Return Value: + + TRUE - If VendorId/ProductId is found. + +--*/ +{ + PWSTR devices = SupportedDevices->Buffer; + ULONG bufferLengthLeft = SupportedDevices->MaximumLength / sizeof(WCHAR); + UNICODE_STRING unicodeString; + USHORT originalLength = DeviceName->Length; + LONG compare; + BOOLEAN supported = FALSE; + WCHAR tempString[32]; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFindSupportedDevice (DevName %ws): Entering function.\n", + DeviceName->Buffer)); + + // + // 'devices' is the current buffer in the MULTI_SZ built from + // the registry. + // + while (devices[0]) { + + RtlZeroMemory(tempString, sizeof(tempString)); + + if (!NT_SUCCESS(RtlStringCchCopyNW(tempString, sizeof(tempString) / sizeof(tempString[0]), devices, bufferLengthLeft))) { + + tempString[(sizeof(tempString) / sizeof(tempString)) - 1] = L'\0'; + } + + // + // Make the current entry into a unicode string. + // + RtlInitUnicodeString(&unicodeString, tempString); + + // + // Compare this one with the current device. + // However, for storages that make up the product id on-the-fly, MPIO + // allows for matching based just on substring (product-id-prefix so to + // speak). + // + if (unicodeString.Length < DeviceName->Length) { + DeviceName->Length = unicodeString.Length; + } + + compare = RtlCompareUnicodeStrings(unicodeString.Buffer, + unicodeString.Length / sizeof(WCHAR), + DeviceName->Buffer, + DeviceName->Length / sizeof(WCHAR), + TRUE); + + DeviceName->Length = originalLength; + + if (compare == 0) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpFindSupportedDevice (DevName %ws): Device support found in the registry.\n", + DeviceName->Buffer)); + + supported = TRUE; + break; + } + + // + // Advance to next entry in the MULTI_SZ. + // + devices += (unicodeString.MaximumLength / sizeof(WCHAR)); + + bufferLengthLeft -= (unicodeString.MaximumLength / sizeof(WCHAR)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpFindSupportedDevice (DevName %ws): Exiting function with Supported = %u.\n", + DeviceName->Buffer, + supported)); + + return supported; +} + +_Success_(return!=0) +PVOID +DsmpParseDeviceID( + _In_ IN PSTORAGE_DEVICE_ID_DESCRIPTOR DeviceID, + _In_ IN DSM_DEVID_TYPE DeviceIdType, + _In_opt_ IN PULONG IdNumber, + _Out_opt_ OUT PSTORAGE_IDENTIFIER_CODE_SET CodeSet, + _In_ IN BOOLEAN Legacy + ) +/*++ + +Routine Description: + + This routine builds a serial number string based on the information + in the VPD page 0x83 data if serial number is requested, else it + returns the appropriate identifier requested. + + Caller must free the buffer. + +Arguments: + + DeviceIdList - VPD Page 0x83 information. + DeviceIdType - Type of identifier that the DeviceID is being parsed for + IdNumber - If there are multiple identifiers of type DeviceIdType, this parameter + determines which among them to actually return. + IMPORTANT: This number is one-based (not zero-based). + CodeSet - Of relevance only if the DeviceIdType is DSM_DEVID_SERIAL_NUMBER. This + returns the code set that was used when building the serial number. + Legacy - Of relevance only if the DeviceIdType is DSM_DEVID_SERIAL_NUMBER. If the + code set of the identifier is StorageIdCodeSetBinary, this determines + whether to use the legacy method of binary to ascii conversion. + +Return Value: + + Requested Device identifier. + +--*/ +{ + PSTORAGE_IDENTIFIER identifier; + STORAGE_IDENTIFIER_CODE_SET codeSet = StorageIdCodeSetReserved; // Preload with a bogus value. + STORAGE_IDENTIFIER_TYPE type = 0xF; + STORAGE_ASSOCIATION_TYPE association = 0xF; + ULONG numberIds; + ULONG i; + ULONG identifierSize = 0; + PUCHAR bytes = NULL; + PVOID buffer = NULL; + BOOLEAN done = FALSE; + ULONG idNumber = MAXULONG; + ULONG matches = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpParseDeviceID (DevIdDesc %p): Entering function - IdType %x.\n", + DeviceID, + DeviceIdType)); + + if (IdNumber) { + idNumber = *IdNumber; + } + + // + // Get the number of encapsulated identifiers. + // + numberIds = DeviceID->NumberOfIdentifiers; + + if (idNumber != MAXULONG && idNumber > numberIds) { + goto __Exit_DsmpParseDeviceID; + } + + // + // Get a pointer to the first one. + // + identifier = (PSTORAGE_IDENTIFIER)(DeviceID->Identifiers); + + for (i = 0; i < numberIds && !done; i++) { + + switch (DeviceIdType) { + + case DSM_DEVID_SERIAL_NUMBER: { + + // + // The way this works is that we will go through all the identifiers + // Order of preference will be LUN-associated over Target-associated. + // Further, upon same association, preference will be based on type as + // follows: 0x8, 0x3, 0x2, 0x1, 0x0. + // So an existing identifier will be discarded if a better one is found. + // If two identifiers have the same type, we will prefer the one will + // the larger length. + // + + // + // 1. Ensure that the association is for either the LUN or target. (If neither, ignore id). + // 2. If association is with target, don't it consider if current candidate has assocation with LUN. + // 3. If considering this identifier, order of preference is 8 > 3 > 2 > 1 > 0. + // 4. If this id type is same as current candidate, consider it only if it is of greater length. + // + if (((identifier->Association == StorageIdAssocDevice) || + (identifier->Association == 0x2 && association != StorageIdAssocDevice)) && + ((type == identifier->Type && identifierSize < identifier->IdentifierSize) || + (type != identifier->Type && DsmpIsPreferredDeviceId(type, identifier->Type)))) { + + // + // Get a pointer to the id itself. + // + bytes = identifier->Identifier; + + // + // The id's size. + // + identifierSize = identifier->IdentifierSize; + + // + // Get the type, code set, and association. + // + type = identifier->Type; + codeSet = identifier->CodeSet; + association = identifier->Association; + + matches++; + } + + break; + } + + case DSM_DEVID_RELATIVE_TARGET_PORT: { + + // + // Ensure that the association is for the target port. + // + if (identifier->Association != StorageIdAssocPort) { + + if ((i + 1) < numberIds) { + identifier = (PSTORAGE_IDENTIFIER)((PUCHAR)identifier + identifier->NextOffset); + } + + continue; + } + + if (identifier->Type == StorageIdTypePortRelative) { + + // + // Get a pointer to the id itself. + // + bytes = identifier->Identifier; + + // + // The id's size. + // + identifierSize = identifier->IdentifierSize; + + type = identifier->Type; + codeSet = identifier->CodeSet; + association = identifier->Association; + + matches++; + } + + break; + } + + case DSM_DEVID_TARGET_PORT_GROUP: { + + // + // Ensure that the association is for the target port. + // + if (identifier->Association != StorageIdAssocPort) { + + if ((i + 1) < numberIds) { + identifier = (PSTORAGE_IDENTIFIER)((PUCHAR)identifier + identifier->NextOffset); + } + + continue; + } + + if (identifier->Type == 0x5) { + + // + // Get a pointer to the id itself. + // + bytes = identifier->Identifier; + + // + // Move this by two bytes because first two bytes are reservered + // + bytes += sizeof(USHORT); + + // + // The id's size. Reduce the size by 2 bytes (to account + // for the reservered bytes) + // + identifierSize = identifier->IdentifierSize - sizeof(USHORT); + + type = identifier->Type; + codeSet = identifier->CodeSet; + association = identifier->Association; + + matches++; + } + + break; + } + + default: break; + } + + + if (idNumber != MAXULONG && idNumber == matches) { + done = TRUE; + } + + // + // Advance to the next identifier in the buffer. + // + if ((i + 1) < numberIds) { + identifier = (PSTORAGE_IDENTIFIER)((PUCHAR)identifier + identifier->NextOffset); + } + } + + if (idNumber != MAXULONG && idNumber > matches) { + goto __Exit_DsmpParseDeviceID; + } + + if (DeviceIdType == DSM_DEVID_SERIAL_NUMBER) { + + if (type != StorageIdTypeScsiNameString && + type != StorageIdTypeFCPHName && + type != StorageIdTypeEUI64 && + type != StorageIdTypeVendorId && + type != StorageIdTypeVendorSpecific) { + + DSM_ASSERT(FALSE); + bytes = NULL; + identifierSize = 0; + type = association = 0xF; + codeSet = StorageIdCodeSetReserved; + } + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpParseDeviceID (DevIdDesc %p): IdentifierSize = %u, Type = %u, Association = %u, CodeSet = %u.\n", + DeviceID, + identifierSize, + type, + association, + codeSet)); + + if (!bytes) { + goto __Exit_DsmpParseDeviceID; + } + + if (codeSet == StorageIdCodeSetBinary) { + + // + // Need to convert to ascii. + // + buffer = DsmpBinaryToAscii(bytes, + identifierSize, + &identifierSize, + Legacy); + + } else { + + if (identifierSize) { + // + // Allocate a buffer that is the size of the data, plus one for NULL. + // + buffer = DsmpAllocatePool(NonPagedPoolNx, identifierSize + 1, DSM_TAG_DEV_ID); + DSM_ASSERT(buffer); + + if (buffer) { + + // + // Copy over the id. + // + RtlCopyMemory(buffer, bytes, identifierSize); + } + } + } + + if (CodeSet) { + *CodeSet = codeSet; + } + + } else { + + if (identifierSize) { + + DSM_ASSERT((DeviceIdType == DSM_DEVID_RELATIVE_TARGET_PORT && identifierSize == sizeof(ULONG)) || + (DeviceIdType == DSM_DEVID_TARGET_PORT_GROUP && identifierSize == sizeof(USHORT))); + + _Analysis_assume_((DeviceIdType == DSM_DEVID_RELATIVE_TARGET_PORT && identifierSize == sizeof(ULONG)) || + (DeviceIdType == DSM_DEVID_TARGET_PORT_GROUP && identifierSize == sizeof(USHORT))); + + buffer = DsmpAllocatePool(NonPagedPoolNx, identifierSize, DSM_TAG_DEV_ID); + + if (buffer) { + + if (DeviceIdType == DSM_DEVID_RELATIVE_TARGET_PORT) { + + GetUlongFrom4ByteArray(bytes, *((PULONG)buffer)); + + } else if (DeviceIdType == DSM_DEVID_TARGET_PORT_GROUP) { + + *((PUSHORT)buffer) = (bytes[0] << 8) | (bytes[1]); + } + } + } + } + +__Exit_DsmpParseDeviceID: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpParseDeviceID (DevIdDesc %p): Exiting function with buffer %p.\n", + DeviceID, + buffer)); + + return buffer; +} + + +PUCHAR +DsmpBinaryToAscii( + _In_reads_(Length) IN PUCHAR HexBuffer, + _In_ IN ULONG Length, + _Inout_ IN OUT PULONG UpdateLength, + _In_ IN BOOLEAN Legacy + ) +/*++ + +Routine Description: + + This routine will convert HexBuffer into an ascii NULL-terminated string. + + Note: This routine will allocate memory for storing the ascii string. It is + the responsibility of the caller to free this buffer. + +Arguments: + + HexBuffer - Pointer to the binary data. + Length - Length, in bytes, of HexBuffer. + UpdateLength - Storage to place the actual length of the returned string. + Legacy - Use the legacy method for the conversion. + +Return Value: + + Serial Number string, or NULL if an error occurred. + +--*/ +{ + static UCHAR IntegerTable[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + ULONG i; + ULONG j; + ULONG actualLength; + PUCHAR buffer = NULL; + UCHAR highWord; + UCHAR lowWord; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBinaryToAscii (HexBuff %p): Entering function.\n", + HexBuffer)); + + if (Length == 0) { + *UpdateLength = 0; + goto __Exit_DsmpBinaryToAscii; + } + + if (Legacy) { + // + // Do a pre-test on the buffer to determine the length actually needed. + // + for (i = 0, actualLength = 0; i < Length; i++) { + + if (HexBuffer[i] < 0x10) { + actualLength++; + } else { + actualLength += 2; + } + } + + // + // Add room for a terminating NULL. + // + actualLength++; + } else { + // + // We need one character for each nibble, plus one for the terminating NULL. + // + actualLength = (Length * 2) + 1; + } + + // + // Allocate the buffer. + // + buffer = DsmpAllocatePool(NonPagedPoolNx, + actualLength, + DSM_TAG_BIN_TO_ASCII); + if (!buffer) { + *UpdateLength = 0; + goto __Exit_DsmpBinaryToAscii; + } + + for (i = 0, j = 0; i < Length && j < actualLength; i++) { + + if (Legacy && (HexBuffer[i] < 0x10)) { + + // + // If legacy is mentioned and it's 0x0F or less, + // just convert the entire byte. + // + buffer[j++] = IntegerTable[HexBuffer[i]]; + } else { + + // + // Split out each nibble from the binary byte. + // + highWord = HexBuffer[i] >> 4; + lowWord = HexBuffer[i] & 0x0F; + + // + // Using the lookup table, convert and stuff into + // the ascii buffer. + // + buffer[j++] = IntegerTable[highWord]; + buffer[j++] = IntegerTable[lowWord]; + } + } + + // + // Update the caller's length field. + // + *UpdateLength = actualLength; + +__Exit_DsmpBinaryToAscii: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBinaryToAscii (HexBuff %p): Exiting function with buffer %s.\n", + HexBuffer, + (const char*) buffer)); + + return buffer; +} + + +PSTR +DsmpGetSerialNumber( + _In_ IN PDEVICE_OBJECT DeviceObject + ) +/*++ + +Routine Description: + + Helper routine to send an inquiry with EVPD set to get the serial number page. + Used if the serial number is not embedded in the device descriptor (this device probably + doesn't support VPD page 0x00). + + Note: This routine will allocate memory for storing the serial number. It is + the responsibility of the caller to free this buffer. + +Arguments: + + DeviceObject - The port PDO to which the command should be sent. + +Return Value: + + The serial number (null-terminated string) or NULL if the call fails. + +--*/ +{ + PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; + PVPD_SERIAL_NUMBER_PAGE serialPage; + PCDB cdb; + PSTR serialNumber = NULL; + IO_STATUS_BLOCK ioStatus; + ULONG length; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetSerialNumber (DevObj %p): Entering function.\n", + DeviceObject)); + + // + // Build an inquiry command with EVPD and pagecode of 0x80 (serial number). + // + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + passThrough = DsmpAllocatePool(NonPagedPoolNx, + length, + DSM_TAG_PASS_THRU); + if (!passThrough) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetSerialNumber (DevObj %p): Failed to allocate mem for passthrough.\n", + DeviceObject)); + + goto __Exit_DsmpGetSerialNumber; + } + + // + // Build the cdb. + // + cdb = (PCDB)passThrough->ScsiPassThrough.Cdb; + cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY; + cdb->CDB6INQUIRY.Reserved1 = 1; + cdb->CDB6INQUIRY.PageCode = VPD_SERIAL_NUMBER; + cdb->CDB6INQUIRY.AllocationLength = DSM_SERIAL_NUMBER_BUFFER_SIZE; + + passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); + passThrough->ScsiPassThrough.CdbLength = 6; + passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; + passThrough->ScsiPassThrough.DataIn = 1; + passThrough->ScsiPassThrough.DataTransferLength = DSM_SERIAL_NUMBER_BUFFER_SIZE; + passThrough->ScsiPassThrough.TimeOutValue = 20; + passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); + passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); + + DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, + DeviceObject, + passThrough, + passThrough, + length, + length, + FALSE, + &ioStatus); + if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && + (NT_SUCCESS(ioStatus.Status))) { + + ULONG inx; + + // + // Get the returned data. + // + serialPage = (PVPD_SERIAL_NUMBER_PAGE)(passThrough->DataBuffer); + + // + // Allocate a buffer to hold just the serial number plus a null terminator + // + serialNumber = DsmpAllocatePool(NonPagedPoolNx, + serialPage->PageLength + 1, + DSM_TAG_SERIAL_NUM); + if (serialNumber) { + + // + // Copy it over. + // + RtlCopyMemory(serialNumber, serialPage->SerialNumber, serialPage->PageLength); + + // + // Some devices return binary data for the serial number. + // Convert to a more ascii-ish format so that other routines don't have a problem. + // + for (inx = 0; inx < serialPage->PageLength; inx++) { + if (serialNumber[inx] == '\0') { + serialNumber[inx] = ' '; + } + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetSerialNumber (DevObj %p): Failed to allocate mem for serialnumber.\n", + DeviceObject)); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetSerialNumber (DevObj %p): NTStatus 0%x, ScsiStatus 0x%x.\n", + DeviceObject, + ioStatus.Status, + passThrough->ScsiPassThrough.ScsiStatus)); + } + +__Exit_DsmpGetSerialNumber: + + // + // Free the passthrough + data buffer. + // + if (passThrough) { + + DsmpFreePool(passThrough); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetSerialNumber (DevObj %p): Exiting function with serial number %s.\n", + DeviceObject, + (const char*)serialNumber)); + + // + // Return the sn. + // + return serialNumber; +} + + +NTSTATUS +DsmpDisableImplicitStateTransition( + _In_ IN PDEVICE_OBJECT TargetDevice, + _Out_ OUT PBOOLEAN DisableImplicit + ) +/*++ + +Routine Description: + + Send down request to disable implicit ALUA state transition. + The function first sends down a mode sense to get the control extension mode + sense data. It then clears the IALUAE bit and sends down a mode select. + +Arguements: + + TargetDevice - Device object that will be target of this command. + DisableImplicit - Flag returned to the caller to indicate whether or not + implicit transitions are disabled. + +Return Value : + + STATUS_SUCCESS if the command succeeds. + Appropriate NTSTATUS code on failure + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PSCSI_PASS_THROUGH_WITH_BUFFERS passThrough = NULL; + PCDB cdb; + IO_STATUS_BLOCK ioStatus; + ULONG length; + PSPC3_CONTROL_EXTENSION_MODE_PAGE controlExtensionPage = NULL; + PSENSE_DATA senseData = NULL; + BOOLEAN implicitDisabled = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): Entering function.\n", + TargetDevice)); + + // + // First build the mode sense command to get the control extension parameters. + // + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + passThrough = DsmpAllocatePool(NonPagedPoolNx, + length, + DSM_TAG_PASS_THRU); + if (!passThrough) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): Failed to allocate mem for passthrough.\n", + TargetDevice)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpDisableImplicitStateTransition; + } + +__Retry_ModeSense: + + passThrough->ScsiPassThrough.Length = sizeof(SCSI_PASS_THROUGH); + passThrough->ScsiPassThrough.CdbLength = 6; + passThrough->ScsiPassThrough.SenseInfoLength = SPTWB_SENSE_LENGTH; + passThrough->ScsiPassThrough.DataIn = 1; + passThrough->ScsiPassThrough.DataTransferLength = sizeof(SPC3_CONTROL_EXTENSION_MODE_PAGE); + passThrough->ScsiPassThrough.TimeOutValue = 20; + passThrough->ScsiPassThrough.SenseInfoOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseInfoBuffer); + passThrough->ScsiPassThrough.DataBufferOffset = FIELD_OFFSET(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuffer); + + // + // Build the cdb for mode sense. + // + cdb = (PCDB)passThrough->ScsiPassThrough.Cdb; + cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; + cdb->MODE_SENSE.Dbd = 1; + cdb->MODE_SENSE.PageCode = 0xA; + cdb->MODE_SENSE.SubPageCode = 0x01; + cdb->MODE_SENSE.AllocationLength = sizeof(SPC3_CONTROL_EXTENSION_MODE_PAGE); + + DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, + TargetDevice, + passThrough, + passThrough, + length, + length, + FALSE, + &ioStatus); + + status = ioStatus.Status; + senseData = (PSENSE_DATA)(passThrough->SenseInfoBuffer); + + if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(status))) { + + controlExtensionPage = (PSPC3_CONTROL_EXTENSION_MODE_PAGE)(passThrough->DataBuffer); + + if (controlExtensionPage->ImplicitALUAEnable) { + + controlExtensionPage->ImplicitALUAEnable = 0; + +__Retry_ModeSelect: + + RtlZeroMemory(passThrough->SenseInfoBuffer, passThrough->ScsiPassThrough.SenseInfoLength); + + passThrough->ScsiPassThrough.DataIn = 0; + + // + // Build the cdb for mode select. + // + RtlZeroMemory(cdb, 6); + cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; + cdb->MODE_SELECT.SPBit = 0; + cdb->MODE_SELECT.PFBit = 1; + cdb->MODE_SELECT.ParameterListLength = sizeof(SPC3_CONTROL_EXTENSION_MODE_PAGE); + + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH, + TargetDevice, + passThrough, + passThrough, + length, + length, + FALSE, + &ioStatus); + + status = ioStatus.Status; + senseData = (PSENSE_DATA)(passThrough->SenseInfoBuffer); + + if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_GOOD) && (NT_SUCCESS(status))) { + + implicitDisabled = TRUE; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): Implicit transitions turned off successfully.\n", + TargetDevice)); + + } else if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_CHECK_CONDITION) && + (NT_SUCCESS(status)) && + (DsmpShouldRetryPassThroughRequest(senseData, passThrough->ScsiPassThrough.SenseInfoLength))) { + + // + // Retry the request + // + goto __Retry_ModeSelect; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): ModeSelect failed - NTStatus 0x%x, ScsiStatus 0x%x.\n", + TargetDevice, + status, + passThrough->ScsiPassThrough.ScsiStatus)); + } + } else { + + implicitDisabled = TRUE; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): Implicit transitions already turned OFF.\n", + TargetDevice)); + } + } else if ((passThrough->ScsiPassThrough.ScsiStatus == SCSISTAT_CHECK_CONDITION) && + (NT_SUCCESS(status)) && + (DsmpShouldRetryPassThroughRequest(senseData, passThrough->ScsiPassThrough.SenseInfoLength))) { + + length = sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS); + + // + // Retry the request + // + RtlZeroMemory(passThrough, length); + goto __Retry_ModeSense; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): ModeSense failed - NTStatus 0x%x, ScsiStatus 0x%x.\n", + TargetDevice, + status, + passThrough->ScsiPassThrough.ScsiStatus)); + } + +__Exit_DsmpDisableImplicitStateTransition: + + // + // Free the passthrough + data buffer. + // + if (passThrough) { + DsmpFreePool(passThrough); + } + + // + // Return whether IALUAE is set to 0. + // + if (DisableImplicit) { + + *DisableImplicit = implicitDisabled; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpDisableImplicitStateTransition (DevObj %p): Exiting function with status %x.\n", + TargetDevice, + status)); + + return status; +} + + +PWSTR +DsmpBuildHardwareId( + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + Construct a string concatinating VendorId with ProductId. + +Arguements: + + DeviceInfo - Device Extension + +Return Value : + + NULL terminated hardware id if it was built successfully. + NULL in case of failure. + +--*/ +{ + PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; + PWSTR hardwareId = NULL; + SIZE_T vendorIDLength = 0; + SIZE_T productIDLength = 0; + PCSZ vendorIdOffset; + PCSZ productIdOffset; + SIZE_T sizeNeeded; + NTSTATUS status = STATUS_SUCCESS; + ANSI_STRING ansiString; + UNICODE_STRING unicodeString; + ULONG offset; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): Entering function.\n", + DeviceInfo)); + + deviceDescriptor = &(DeviceInfo->Descriptor); + + // + // Save the vendorid and productid offset in Device Descriptor + // + offset = deviceDescriptor->ProductIdOffset; + if ((offset != 0) && (offset != MAXULONG)) { + + productIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + offset = deviceDescriptor->VendorIdOffset; + if ((offset != 0) && (offset != MAXULONG)) { + + vendorIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + if (!vendorIDLength || !productIDLength) { + + status = STATUS_UNSUCCESSFUL; + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): Invalid vendor and/or product id.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildHardwareId; + } + + sizeNeeded = vendorIDLength + productIDLength; + hardwareId = DsmpAllocatePool(NonPagedPoolNx, sizeNeeded, DSM_TAG_DEV_HARDWARE_ID); + if (!hardwareId) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): Failed to allocate memory for device name.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpBuildHardwareId; + } + + // + // Build the NULL terminated hardwareId whose format is : + // + // VendorIdProductId + // + vendorIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + deviceDescriptor->VendorIdOffset); + RtlInitAnsiString(&ansiString, vendorIdOffset); + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT)vendorIDLength; + unicodeString.Buffer = hardwareId; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): Failed to convert vendor id to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildHardwareId; + } + + productIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + deviceDescriptor->ProductIdOffset); + RtlInitAnsiString(&ansiString, productIdOffset); + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT)productIDLength; + unicodeString.Buffer = hardwareId + strlen(((PCHAR)deviceDescriptor) + offset); + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): Failed to convert product id to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildHardwareId; + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): HardwareId is %ws.\n", + DeviceInfo, + hardwareId)); + +__Exit_DsmpBuildHardwareId: + + if (hardwareId && !NT_SUCCESS(status)) { + DsmpFreePool(hardwareId); + hardwareId = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildHardwareId (DevInfo %p): Exiting function with deviceName %ws.\n", + DeviceInfo, + hardwareId)); + + return hardwareId; +} + + +PWSTR +DsmpBuildDeviceNameLegacyPage0x80( + _In_ IN PDSM_DEVICE_INFO DeviceInfo + ) +/*++ + +Routine Description: + + Construct a string from VendorId, ProductId, and SerialNumber (page 0x80 + info) of the device. + +Arguements: + + DeviceInfo - Device Extension + +Return Value : + + STATUS_SUCCESS if the device name was built successfully. + + Appropriate NTSTATUS code on failure + +--*/ +{ + PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; + PWCHAR deviceName = NULL; + PWCHAR tmpPtr; + PWCHAR vendorID = NULL; + PWCHAR productID = NULL; + PWCHAR serialID = NULL; + ANSI_STRING ansiString; + UNICODE_STRING unicodeString; + UNICODE_STRING unicodeDeviceName; + SIZE_T vendorIDLength = 0; + SIZE_T productIDLength = 0; + SIZE_T serialIDLength = 0; + ULONG offset; + SIZE_T sizeNeeded; + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Entering function.\n", + DeviceInfo)); + + deviceDescriptor = &(DeviceInfo->Descriptor); + + // + // Save the vendorid, productid, and serialnumber offset + // in Device Descriptor + // + offset = deviceDescriptor->VendorIdOffset; + if ((offset != 0) && (offset != MAXULONG)) { + + vendorIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + offset = deviceDescriptor->ProductIdOffset; + if ((offset != 0) && (offset != MAXULONG)) { + + productIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + offset = deviceDescriptor->SerialNumberOffset; + if ((offset != 0) && (offset != MAXULONG)) { + + serialIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + // + // Allocate buffers to use to convert the IDs from ANSI to Unicode and + // eventually build the device name. + // + if (vendorIDLength > 0) { + vendorID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, vendorIDLength, DSM_TAG_DEV_NAME); + if (!vendorID) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for vendor ID.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (productIDLength > 0) { + productID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, productIDLength, DSM_TAG_DEV_NAME); + if (!productID) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for product ID.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (serialIDLength > 0) { + serialID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, serialIDLength, DSM_TAG_DEV_NAME); + if (!serialID) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for serial ID.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + sizeNeeded = vendorIDLength + productIDLength + serialIDLength; + if (sizeNeeded > 0) { + + // + // Account for the terminating NULL if serial id is empty. + // + + sizeNeeded += (serialIDLength ? 0 : WNULL_SIZE); + + deviceName = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, sizeNeeded, DSM_TAG_DEV_NAME); + if (!deviceName) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to allocate memory for device name.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } else { + + status = STATUS_UNSUCCESSFUL; + } + + if (!NT_SUCCESS(status)) { + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + + // + // Build the NULL terminated device name whose format is : + // + // VendorId_ProductId_SerialNumber + // + + unicodeDeviceName.Length = 0; + unicodeDeviceName.MaximumLength = (USHORT)sizeNeeded; + unicodeDeviceName.Buffer = deviceName; + + if (vendorIDLength) { + + PCSZ vendorIdOffset; + + vendorIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + + deviceDescriptor->VendorIdOffset); + + RtlInitAnsiString(&ansiString, vendorIdOffset); + + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT) vendorIDLength; + unicodeString.Buffer = vendorID; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to convert vendor id to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + + // + // If there are spaces in the id, set NULL at the first space. + // + tmpPtr = wcschr(vendorID, L' '); + if (tmpPtr != NULL) { + *tmpPtr = WNULL; + } + + status = RtlUnicodeStringCatString(&unicodeDeviceName, vendorID); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to concatenate vendor ID to device name.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + + RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); + } + + if (productIDLength) { + + PCSZ productIdOffset; + + productIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + + deviceDescriptor->ProductIdOffset); + + RtlInitAnsiString(&ansiString, productIdOffset); + + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT) productIDLength; + unicodeString.Buffer = productID; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to convert product id to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + + // + // If there are spaces in the id, set NULL at the first space. + // + tmpPtr = wcschr(productID, L' '); + if (tmpPtr != NULL) { + *tmpPtr = WNULL; + } + + status = RtlUnicodeStringCatString(&unicodeDeviceName, productID); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to concatenate product ID to device name.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + + RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); + } + + // + // Serial number + // + if (serialIDLength) { + + PCSZ serialNumberOffset; + + serialNumberOffset = (PCSZ)((PUCHAR)deviceDescriptor + + deviceDescriptor->SerialNumberOffset); + + RtlInitAnsiString(&ansiString, serialNumberOffset); + + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT) serialIDLength; + unicodeString.Buffer = serialID; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to convert serial number to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + + // + // If there are spaces in the id, set NULL at the first space. + // + tmpPtr = wcschr(serialID, L' '); + if (tmpPtr != NULL) { + *tmpPtr = WNULL; + } + + status = RtlUnicodeStringCatString(&unicodeDeviceName, serialID); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Failed to concatenate serial number to device name.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceNameLegacyPage0x80; + } + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Device Name is %ws.\n", + DeviceInfo, + deviceName)); + +__Exit_DsmpBuildDeviceNameLegacyPage0x80: + + if (vendorID) { + DsmpFreePool(vendorID); + } + + if (productID) { + DsmpFreePool(productID); + } + + if (serialID) { + DsmpFreePool(serialID); + } + + if (deviceName && !NT_SUCCESS(status)) { + DsmpFreePool(deviceName); + deviceName = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildDeviceNameLegacyPage0x80 (DevInfo %p): Exiting function with deviceName %ws.\n", + DeviceInfo, + deviceName)); + + return deviceName; +} + + + +PWSTR +DsmpBuildDeviceName( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_reads_(SerialNumberLength) IN PSTR SerialNumber, + _In_ IN SIZE_T SerialNumberLength + ) +/*++ + +Routine Description: + + Construct a string from VendorId, ProductId, and SerialNumber (page 0x83 + identifiers) of the device. + +Arguements: + + DeviceInfo - Device Extension + SerialNumber - Device serial number built from appropriate page 0x83 identifier + SerialNumberLength - Length (in chars) of the passed in serial number buffer + +Return Value : + + Device name if it was built successfully. + NULL in case of failure. + +--*/ +{ + PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor; + PWCHAR deviceName = NULL; + PWCHAR tmpPtr; + PWCHAR vendorID = NULL; + PWCHAR productID = NULL; + PWCHAR serialID = NULL; + ANSI_STRING ansiString; + UNICODE_STRING unicodeString; + UNICODE_STRING unicodeDeviceName; + SIZE_T vendorIDLength = 0; + SIZE_T productIDLength = 0; + SIZE_T serialIDLength = 0; + ULONG offset; + SIZE_T sizeNeeded; + NTSTATUS status = STATUS_SUCCESS; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Entering function.\n", + DeviceInfo)); + + deviceDescriptor = &(DeviceInfo->Descriptor); + + // + // Save the vendorid, productid, and serialnumber offset + // in Device Descriptor + // + offset = deviceDescriptor->VendorIdOffset; + if ((offset != 0) && (offset != MAXULONG)) { + + vendorIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + offset = deviceDescriptor->ProductIdOffset; + if ((offset != 0) && (offset != -1)) { + + productIDLength = (strlen(((PCHAR)deviceDescriptor) + offset) * sizeof(WCHAR)) + WNULL_SIZE; + } + + if (SerialNumber) { + + serialIDLength = (SerialNumberLength * sizeof(WCHAR)) + WNULL_SIZE; + } + + // + // Allocate buffers to use to convert the IDs from ANSI to Unicode and + // eventually build the device name. + // + if (vendorIDLength > 0) { + vendorID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, vendorIDLength, DSM_TAG_DEV_NAME); + if (!vendorID) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for vendor ID.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (productIDLength > 0) { + productID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, productIDLength, DSM_TAG_DEV_NAME); + if (!productID) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for product ID.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (serialIDLength > 0) { + serialID = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, serialIDLength, DSM_TAG_DEV_NAME); + if (!serialID) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for serial ID.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + sizeNeeded = vendorIDLength + productIDLength + serialIDLength; + if (sizeNeeded > 0) { + + // + // Account for the terminating NULL if serial id is empty. + // + + sizeNeeded += (serialIDLength ? 0 : WNULL_SIZE); + + deviceName = (PWCHAR)DsmpAllocatePool(NonPagedPoolNx, sizeNeeded, DSM_TAG_DEV_NAME); + if (!deviceName) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to allocate memory for device name.\n", + DeviceInfo)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } else { + + status = STATUS_UNSUCCESSFUL; + } + + if (!NT_SUCCESS(status)) { + goto __Exit_DsmpBuildDeviceName; + } + + // + // Build the NULL terminated device name whose format is : + // + // VendorId_ProductId_SerialNumber + // + + unicodeDeviceName.Length = 0; + unicodeDeviceName.MaximumLength = (USHORT)sizeNeeded; + unicodeDeviceName.Buffer = deviceName; + + if (vendorIDLength) { + + PCSZ vendorIdOffset; + + vendorIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + + deviceDescriptor->VendorIdOffset); + + RtlInitAnsiString(&ansiString, vendorIdOffset); + + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT) vendorIDLength; + unicodeString.Buffer = vendorID; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to convert vendor id to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceName; + } + + // + // If there are spaces in the id, set NULL at the first space. + // + tmpPtr = wcschr(vendorID, L' '); + if (tmpPtr != NULL) { + *tmpPtr = WNULL; + } + + status = RtlUnicodeStringCatString(&unicodeDeviceName, vendorID); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to concatenate vendor ID to device name.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceName; + } + + RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); + } + + if (productIDLength) { + + PCSZ productIdOffset; + + productIdOffset = (PCSZ)((PUCHAR)deviceDescriptor + + deviceDescriptor->ProductIdOffset); + + RtlInitAnsiString(&ansiString, productIdOffset); + + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT) productIDLength; + unicodeString.Buffer = productID; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to convert product id to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceName; + } + + // + // If there are spaces in the id, set NULL at the first space. + // + tmpPtr = wcschr(productID, L' '); + if (tmpPtr != NULL) { + *tmpPtr = WNULL; + } + + status = RtlUnicodeStringCatString(&unicodeDeviceName, productID); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to concatenate product ID to device name.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceName; + } + + RtlUnicodeStringCatString(&unicodeDeviceName, L"_"); + } + + // + // Serial number + // + if (serialIDLength) { + + PSTR serialNumberOffset; + + serialNumberOffset = SerialNumber; + + RtlInitAnsiString(&ansiString, serialNumberOffset); + + unicodeString.Length = 0; + unicodeString.MaximumLength = (USHORT) serialIDLength; + unicodeString.Buffer = serialID; + + status = RtlAnsiStringToUnicodeString(&unicodeString, + &ansiString, + FALSE); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to convert serial number to unicode string.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceName; + } + + // + // If there are spaces in the id, set NULL at the first space. + // + tmpPtr = wcschr(serialID, L' '); + if (tmpPtr != NULL) { + *tmpPtr = WNULL; + } + + status = RtlUnicodeStringCatString(&unicodeDeviceName, serialID); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Failed to concatenate serial number to device name.\n", + DeviceInfo)); + + goto __Exit_DsmpBuildDeviceName; + } + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Device Name is %ws.\n", + DeviceInfo, + deviceName)); + +__Exit_DsmpBuildDeviceName: + + if (vendorID) { + DsmpFreePool(vendorID); + } + + if (productID) { + DsmpFreePool(productID); + } + + if (serialID) { + DsmpFreePool(serialID); + } + + if (deviceName && !NT_SUCCESS(status)) { + DsmpFreePool(deviceName); + deviceName = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpBuildDeviceName (DevInfo %p): Exiting function with deviceName %ws.\n", + DeviceInfo, + deviceName)); + + return deviceName; +} + + +NTSTATUS +DsmpApplyDeviceNameCorrection( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_reads_(DeviceNameLegacyLen) PWSTR DeviceNameLegacy, + _In_ IN SIZE_T DeviceNameLegacyLen, + _In_reads_(DeviceNameLen) PWSTR DeviceName, + _In_ IN SIZE_T DeviceNameLen + ) +/*++ + +Routine Description: + + If the registry has a key name built with a legacy device name, this + function updates the key name with the current device name. + +Arguements: + + DeviceInfo - Device instance + DeviceNameLegacy - Device name built using legacy methods. + DeviceNameLegacyLen - Number of chars (including NULL) of the DeviceNameLegacy buffer. + DeviceName - Device name built using current methods. + DeviceNameLen - Number of chars (including NULL) of the DeviceName buffer. + +Return Value : + + STATUS_SUCCESS if the device's key was updated successfully. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE lbSettingsKey = NULL; + HANDLE deviceKeyLegacy = NULL; + HANDLE deviceKey = NULL; + OBJECT_ATTRIBUTES objectAttributes; + NTSTATUS status; + UNICODE_STRING deviceNameLegacy; + UNICODE_STRING deviceName; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(DeviceNameLen); + UNREFERENCED_PARAMETER(DeviceNameLegacyLen); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Entering function.\n", + DeviceInfo)); + + // + // First open LoadBalanceSettings key under the service key. + // + status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to open LB Settings key. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpApplyDeviceNameCorrection; + } + + RtlInitUnicodeString(&deviceNameLegacy, DeviceNameLegacy); + + InitializeObjectAttributes(&objectAttributes, + &deviceNameLegacy, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + lbSettingsKey, + (PSECURITY_DESCRIPTOR) NULL); + + // + // Open the old device key under DsmLoadBalanceSettings key. + // The name of this key is the one built using legacy methods - either a + // serial number from VPD page 0x80 or an aliased serial number from VPD + // page 0x83. + // + status = ZwOpenKey(&deviceKeyLegacy, + KEY_ALL_ACCESS, + &objectAttributes); + + if (NT_SUCCESS(status)) { + + ULONG disposition; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Key with old device name exists.\n", + DeviceInfo)); + + RtlInitUnicodeString(&deviceName, DeviceName); + + InitializeObjectAttributes(&objectAttributes, + &deviceName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + lbSettingsKey, + (PSECURITY_DESCRIPTOR) NULL); + + // + // Since the old name key exists, create one with the new name. + // + status = ZwCreateKey(&deviceKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + &disposition); + + if (NT_SUCCESS(status)) { + + // + // The new key shouldn't exist if the old one does. + // If it does, it indicates a error occured the previous time + // this was tried, so just copy over the old subtree anyways now. + // + DSM_ASSERT(disposition == REG_CREATED_NEW_KEY); + + // + // Copy over the entire subtree of the old key over to the new key. + // + status = DsmpRegCopyTree(deviceKeyLegacy, deviceKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to copy over the old device key's subtree. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpApplyDeviceNameCorrection; + } + + // + // Delete the old key name. + // + status = DsmpRegDeleteTree(deviceKeyLegacy); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to delete the old device key's subtree. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpApplyDeviceNameCorrection; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to create the new device key. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpApplyDeviceNameCorrection; + } + + } else if (status == STATUS_INVALID_HANDLE || + status == STATUS_OBJECT_NAME_NOT_FOUND) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Key with old device name does not exist.\n", + DeviceInfo)); + + status = STATUS_SUCCESS; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Failed to query key with old device name. Status %x\n", + DeviceInfo, + status)); + } + +__Exit_DsmpApplyDeviceNameCorrection: + + if (deviceKey) { + ZwClose(deviceKey); + } + + if (deviceKeyLegacy) { + ZwClose(deviceKeyLegacy); + } + + if (lbSettingsKey) { + ZwClose(lbSettingsKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpApplyDeviceNameCorrection (DevInfo %p): Exiting function with status %x\n", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryDeviceLBPolicyFromRegistry( + _In_ PDSM_DEVICE_INFO DeviceInfo, + _In_ PWSTR RegistryKeyName, + _Inout_ PDSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Inout_ PULONGLONG PreferredPath, + _Inout_ PUCHAR ExplicitlySet + ) +/*++ + +Routine Description: + + Query the saved load balance policy and preferred path for this device from + the registry. + Also returns whether this setting was explicitly set via WMI call to SetLBPolicy, + (as opposed to the settings being made based on defaults determined through the + storage's ALUA capabilities). + +Arguements: + + DeviceInfo - The instance of the LUN through a paricular path + RegistryKeyName - DeviceName representing this LUN + LoadBalanceType - Type of LB policy. + PreferredPath - The preferred path for the device. + ExplicitlySet - Flag reflecting if LB policy was explicitly set. + +Return Value : + + STATUS_SUCCESS if we were able to successfully query the registry for the info. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE lbSettingsKey = NULL; + HANDLE deviceKey = NULL; + UNICODE_STRING subKeyName; + OBJECT_ATTRIBUTES objectAttributes; + NTSTATUS status; + UNICODE_STRING keyValueName; + ULONG length; + struct _explicitSet { + KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; + UCHAR Data; + } explicitSet; + struct _preferredPath { + KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; + ULONGLONG Data; + } preferredPath; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Entering function.\n", + DeviceInfo)); + + // + // Query the Load Balance settings for the given device from the registry. + // First open LoadBalanceSettings key under the service key. + // + status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to open LB Settings key. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpQueryDeviceLBPolicyFromRegistry; + } + + RtlInitUnicodeString(&subKeyName, RegistryKeyName); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + lbSettingsKey, + (PSECURITY_DESCRIPTOR) NULL); + + // + // Create or Open the device key under DsmLoadBalanceSettings key. + // The name of this key is the one built in DsmpBuildDeviceName + // + status = ZwCreateKey(&deviceKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (NT_SUCCESS(status)) { + + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | + RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; + queryTable[0].EntryContext = LoadBalanceType; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + deviceKey, + queryTable, + deviceKey, + NULL); + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): LB Policy is %d.\n", + DeviceInfo, + *LoadBalanceType)); + + } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + // + // The device key must have been newly created. + // Set the default load balance policy for this device + // + + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_LOAD_BALANCE_POLICY, + REG_DWORD, + LoadBalanceType, + sizeof(ULONG)); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to write LB policy. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpQueryDeviceLBPolicyFromRegistry; + } + } + + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&keyValueName, DSM_POLICY_EXPLICITLY_SET); + status = ZwQueryValueKey(deviceKey, + &keyValueName, + KeyValuePartialInformation, + &explicitSet, + sizeof(explicitSet), + &length); + + if (NT_SUCCESS(status)) { + + NT_ASSERT(explicitSet.KeyValueInfo.DataLength == sizeof(UCHAR)); + + *ExplicitlySet = *((UCHAR UNALIGNED *)&(explicitSet.KeyValueInfo.Data)); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): ExplicitlySet is %!bool!.\n", + DeviceInfo, + *ExplicitlySet)); + + } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + *ExplicitlySet = FALSE; + + // + // The device key must have been newly created. + // Set ExplicitlySet to 0 to indicate that the default was used. + // + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_POLICY_EXPLICITLY_SET, + REG_BINARY, + ExplicitlySet, + sizeof(UCHAR)); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to write ExplicitlySet. Status %x.\n", + DeviceInfo, + status)); + } + } + + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); + status = ZwQueryValueKey(deviceKey, + &keyValueName, + KeyValuePartialInformation, + &preferredPath, + sizeof(preferredPath), + &length); + + if (NT_SUCCESS(status)) { + + NT_ASSERT(preferredPath.KeyValueInfo.DataLength == sizeof(ULONGLONG)); + + *PreferredPath = *((ULONGLONG UNALIGNED *)&(preferredPath.KeyValueInfo.Data)); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): PreferredPath is %I64x.\n", + DeviceInfo, + *PreferredPath)); + + } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + *PreferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + + // + // The device key must have been newly created. + // Set a bogus preferred path as default. + // + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_PREFERRED_PATH, + REG_BINARY, + PreferredPath, + sizeof(ULONGLONG)); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to write PreferredPath. Status %x.\n", + DeviceInfo, + status)); + } + } + } + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Failed to create LB policy registry key. Status %x.\n", + DeviceInfo, + status)); + + deviceKey = NULL; + } + +__Exit_DsmpQueryDeviceLBPolicyFromRegistry: + + if (deviceKey) { + ZwClose(deviceKey); + } + + if (lbSettingsKey) { + ZwClose(lbSettingsKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryDeviceLBPolicyFromRegistry (DevInfo %p): Exiting function with status %x.\n", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryTargetLBPolicyFromRegistry( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Out_ OUT PULONGLONG PreferredPath + ) +/*++ + +Routine Description: + + Query the load balance policy for the VID/PID of the passed in device from + the registry if it has been set. + +Arguements: + + DeviceInfo - Device's whose VID/PID we need to compare against. + LoadBalanceType - Type of LB policy. + PreferredPath - The preferred path for the device. + +Return Value : + + STATUS_SUCCESS if we were able to successfully query the registry for the info. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE targetsLBSettingKey = NULL; + HANDLE targetKey = NULL; + UNICODE_STRING subKeyName; + OBJECT_ATTRIBUTES objectAttributes; + NTSTATUS status = STATUS_INVALID_PARAMETER; + UNICODE_STRING keyValueName; + ULONG length; + struct _preferredPath { + KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; + ULONGLONG Data; + } preferredPath; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Entering function.\n", + DeviceInfo)); + + if (!LoadBalanceType || !PreferredPath) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Invalid parameter.\n", + DeviceInfo)); + + goto __Exit_DsmpQueryTargetLBPolicyFromRegistry; + } + + if (!DeviceInfo->Group->HardwareId) { + + status = STATUS_UNSUCCESSFUL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Couldn't build hardware id for passed in device.\n", + DeviceInfo)); + + goto __Exit_DsmpQueryTargetLBPolicyFromRegistry; + } + + // + // Query the Load Balance settings for the given target from the registry. + // First open TargetsLoadBalanceSetting key under the service key. + // + status = DsmpOpenTargetsLoadBalanceSettingKey(KEY_ALL_ACCESS, &targetsLBSettingKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to open Targets LB Setting key. Status %x.\n", + DeviceInfo, + status)); + + goto __Exit_DsmpQueryTargetLBPolicyFromRegistry; + } + + RtlInitUnicodeString(&subKeyName, DeviceInfo->Group->HardwareId); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + targetsLBSettingKey, + (PSECURITY_DESCRIPTOR) NULL); + + // + // Open the VID/PID key under DsmTargetsLoadBalanceSetting key. + // + status = ZwOpenKey(&targetKey, KEY_ALL_ACCESS, &objectAttributes); + + if (NT_SUCCESS(status)) { + + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | + RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; + queryTable[0].EntryContext = LoadBalanceType; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + targetKey, + queryTable, + targetKey, + NULL); + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): LB Policy is %d.\n", + DeviceInfo, + *LoadBalanceType)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to query LB Policy - error %x.\n", + DeviceInfo, + status)); + } + + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); + status = ZwQueryValueKey(targetKey, + &keyValueName, + KeyValuePartialInformation, + &preferredPath, + sizeof(preferredPath), + &length); + + if (NT_SUCCESS(status)) { + + NT_ASSERT(preferredPath.KeyValueInfo.DataLength == sizeof(ULONGLONG)); + + *PreferredPath = *((ULONGLONG UNALIGNED *)&(preferredPath.KeyValueInfo.Data)); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): PreferredPath is %I64x.\n", + DeviceInfo, + *PreferredPath)); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to query PreferredPath. Status %x.\n", + DeviceInfo, + status)); + } + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Failed to open LB policy registry key. Status %x.\n", + DeviceInfo, + status)); + + targetKey = NULL; + } + +__Exit_DsmpQueryTargetLBPolicyFromRegistry: + + if (targetKey) { + ZwClose(targetKey); + } + + if (targetsLBSettingKey) { + ZwClose(targetsLBSettingKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryTargetLBPolicyFromRegistry (DevInfo %p): Exiting function with status %x.\n", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryDsmLBPolicyFromRegistry( + _Out_ OUT PDSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Out_ OUT PULONGLONG PreferredPath + ) +/*++ + +Routine Description: + + Query the overall load balance policy for MSDSM controlled devices from + the registry if it has been set. + +Arguements: + + LoadBalanceType - Type of LB policy. + PreferredPath - The preferred path for the device. + +Return Value : + + STATUS_SUCCESS if we were able to successfully query the registry for the info. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE parametersKey = NULL; + NTSTATUS status = STATUS_INVALID_PARAMETER; + UNICODE_STRING keyValueName; + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + ULONG length; + struct _preferredPath { + KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; + ULONGLONG Data; + } preferredPath; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: Entering function.\n")); + + if (!LoadBalanceType || !PreferredPath) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: Invalid parameter.\n")); + + goto __Exit_DsmpQueryDsmLBPolicyFromRegistry; + } + + // + // Query the overall default Load Balance settings for MSDSM from the registry. + // First open the Parameters key under the service key. + // + status = DsmpOpenDsmServicesParametersKey(KEY_ALL_ACCESS, ¶metersKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: Failed to open Parameters key. Status %x.\n", + status)); + + goto __Exit_DsmpQueryDsmLBPolicyFromRegistry; + } + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | + RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; + queryTable[0].EntryContext = LoadBalanceType; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + parametersKey, + queryTable, + parametersKey, + NULL); + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: LB Policy is %d.\n", + *LoadBalanceType)); + + } else { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: Failed to query LB policy. Status %x.\n", + status)); + + goto __Exit_DsmpQueryDsmLBPolicyFromRegistry; + } + + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); + status = ZwQueryValueKey(parametersKey, + &keyValueName, + KeyValuePartialInformation, + &preferredPath, + sizeof(preferredPath), + &length); + + if (NT_SUCCESS(status)) { + + NT_ASSERT(preferredPath.KeyValueInfo.DataLength == sizeof(ULONGLONG)); + + *PreferredPath = *((ULONGLONG UNALIGNED *)&(preferredPath.KeyValueInfo.Data)); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: PreferredPath is %I64x.\n", + *PreferredPath)); + + } else { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: Failed to query PreferredPath. Status %x.\n", + status)); + } + } + +__Exit_DsmpQueryDsmLBPolicyFromRegistry: + + if (parametersKey) { + ZwClose(parametersKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryDsmLBPolicyFromRegistry: Exiting function with status %x.\n", + status)); + + return status; +} + + +NTSTATUS +DsmpSetDsmLBPolicyInRegistry( + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ) +/*++ + +Routine Description: + + Set the overall load balance policy for MSDSM controlled devices in + the registry. + Note: If the policy specified is 0, remove the currently set values + for policy and preferred path. + +Arguements: + + LoadBalanceType - Type of LB policy. + PreferredPath - The preferred path for devices controlled by DSM. + +Return Value : + + STATUS_SUCCESS if we were able to successfully set the info in the registry. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE parametersKey = NULL; + NTSTATUS status; + UNICODE_STRING lbPolicyValueName; + UNICODE_STRING preferredPathValueName; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetDsmLBPolicyInRegistry: Entering function.\n")); + + // + // First open the Parameters key under the service key. + // + status = DsmpOpenDsmServicesParametersKey(KEY_ALL_ACCESS, ¶metersKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetDsmLBPolicyInRegistry: Failed to open Parameters key. Status %x.\n", + status)); + + goto __Exit_DsmpSetDsmLBPolicyInRegistry; + } + + RtlInitUnicodeString(&lbPolicyValueName, DSM_LOAD_BALANCE_POLICY); + RtlInitUnicodeString(&preferredPathValueName, DSM_PREFERRED_PATH); + + // + // If the LB policy is specified as 0, we need to delete the values. + // + if (LoadBalanceType < DSM_LB_FAILOVER) { + + status = ZwDeleteValueKey(parametersKey, &preferredPathValueName); + + if (NT_SUCCESS(status) || status == STATUS_OBJECT_NAME_NOT_FOUND) { + + status = ZwDeleteValueKey(parametersKey, &lbPolicyValueName); + } + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetDsmLBPolicyInRegistry: Failed to delete either preferredPath or lbPolicy. Status %x.\n", + status)); + } + } else { + + status = ZwSetValueKey(parametersKey, + &lbPolicyValueName, + 0, + REG_DWORD, + &LoadBalanceType, + sizeof(ULONG)); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetDsmLBPolicyInRegistry: Failed to set LB policy in registry. Status %x.\n", + status)); + + goto __Exit_DsmpSetDsmLBPolicyInRegistry; + } + + status = ZwSetValueKey(parametersKey, + &preferredPathValueName, + 0, + REG_BINARY, + &PreferredPath, + sizeof(ULONGLONG)); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetDsmLBPolicyInRegistry: Failed to set preferred path in registry. Status %x.\n", + status)); + } + } + +__Exit_DsmpSetDsmLBPolicyInRegistry: + + if (parametersKey) { + ZwClose(parametersKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetDsmLBPolicyInRegistry: Exiting function with status %x.\n", + status)); + + return status; +} + + +NTSTATUS +DsmpSetVidPidLBPolicyInRegistry( + _In_ IN PWSTR TargetHardwareId, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _In_ IN ULONGLONG PreferredPath + ) +/*++ + +Routine Description: + + Set the default load balance policy for MSDSM controlled devices for + a particular target VID/PID in the registry. + Note: If the policy specified is 0, remove the subkey that matches + the passed in TargetHardwareId. + +Arguements: + + TargetHardwareId - The VID/PID for which a default LB policy is being set. + LoadBalanceType - Type of LB policy. + PreferredPath - The preferred path for devices controlled by DSM. + +Return Value : + + STATUS_SUCCESS if we were able to successfully set the info in the registry. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE targetsLBSettingKey = NULL; + HANDLE targetSubKey = NULL; + NTSTATUS status; + UNICODE_STRING vidPidKeyName; + UNICODE_STRING lbPolicyValueName; + UNICODE_STRING preferredPathValueName; + OBJECT_ATTRIBUTES objectAttributes; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Entering function.\n", + TargetHardwareId)); + + // + // First open the DsmTargetsLoadBalanceSetting key under the service's parameters key. + // + status = DsmpOpenTargetsLoadBalanceSettingKey(KEY_ALL_ACCESS, &targetsLBSettingKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to open Targets Policy settings key. Status %x.\n", + TargetHardwareId, + status)); + + goto __Exit_DsmpSetVidPidLBPolicyInRegistry; + } + + RtlInitUnicodeString(&vidPidKeyName, TargetHardwareId); + InitializeObjectAttributes(&objectAttributes, + &vidPidKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + targetsLBSettingKey, + (PSECURITY_DESCRIPTOR) NULL); + + // + // If the LB policy is specified as 0, we need to delete the values. + // + if (LoadBalanceType < DSM_LB_FAILOVER) { + + // + // Open the VID/PID key under DsmTargetsLoadBalanceSetting key. + // + status = ZwOpenKey(&targetSubKey, KEY_ALL_ACCESS, &objectAttributes); + + if (NT_SUCCESS(status)) { + + status = ZwDeleteKey(targetSubKey); + } + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to either open or delete. Status %x.\n", + TargetHardwareId, + status)); + } + } else { + + RtlInitUnicodeString(&lbPolicyValueName, DSM_LOAD_BALANCE_POLICY); + RtlInitUnicodeString(&preferredPathValueName, DSM_PREFERRED_PATH); + + status = ZwCreateKey(&targetSubKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to open/create key in registry. Status %x.\n", + TargetHardwareId, + status)); + + goto __Exit_DsmpSetVidPidLBPolicyInRegistry; + } + + status = ZwSetValueKey(targetSubKey, + &lbPolicyValueName, + 0, + REG_DWORD, + &LoadBalanceType, + sizeof(ULONG)); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to set LB policy in registry. Status %x.\n", + TargetHardwareId, + status)); + + goto __Exit_DsmpSetVidPidLBPolicyInRegistry; + } + + status = ZwSetValueKey(targetSubKey, + &preferredPathValueName, + 0, + REG_BINARY, + &PreferredPath, + sizeof(ULONGLONG)); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Failed to set preferred path in registry. Status %x.\n", + TargetHardwareId, + status)); + } + } + +__Exit_DsmpSetVidPidLBPolicyInRegistry: + + if (targetSubKey) { + ZwClose(targetSubKey); + } + + if (targetsLBSettingKey) { + ZwClose(targetsLBSettingKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpSetVidPidLBPolicyInRegistry (%ws): Exiting function with status %x.\n", + TargetHardwareId, + status)); + + return status; +} + + +NTSTATUS +DsmpOpenLoadBalanceSettingsKey( + _In_ IN ACCESS_MASK AccessMask, + _Out_ OUT PHANDLE LoadBalanceSettingsKey + ) +/*++ + +Routine Description: + + Open the device key in the registry. + + NOTE: It is the responsibility of the caller to close the returned handle. + +Arguements: + + AccessMask - Requested access with which to open key + LoadBalanceSettingsKey - handle of the key that is returned to the caller + +Return Value : + + STATUS_SUCCESS if we were able to successfully open the registry key. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE serviceKey = NULL; + HANDLE parametersKey = NULL; + PUNICODE_STRING registryPath = &(gDsmInitData.DsmWmiInfo.RegistryPath); + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING parametersKeyName; + UNICODE_STRING subKeyName; + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Entering function.\n", + registryPath)); + + *LoadBalanceSettingsKey = NULL; + + // + // First check if registry path is available for msdsm. + // + if (!registryPath->Buffer) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Registry Path not set.\n", + registryPath)); + + goto __Exit_DsmpOpenLoadBalanceSettingsKey; + } + + // + // Open the service key first + // + InitializeObjectAttributes(&objectAttributes, + registryPath, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + NULL, + NULL); + + status = ZwOpenKey(&serviceKey, + AccessMask, + &objectAttributes); + if (NT_SUCCESS(status)) { + + // + // Open Parameters key under the Service key + // + RtlInitUnicodeString(¶metersKeyName, DSM_SERVICE_PARAMETERS); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + ¶metersKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + serviceKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(¶metersKey, + AccessMask, + &objectAttributes); + + if (NT_SUCCESS(status)) { + + // + // Open LoadBalanceSettings key under the Parameters key + // + RtlInitUnicodeString(&subKeyName, DSM_LOAD_BALANCE_SETTINGS); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + parametersKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwCreateKey(LoadBalanceSettingsKey, + AccessMask, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Failed to open/create LBSettings key. Status %x.\n", + registryPath, + status)); + + *LoadBalanceSettingsKey = NULL; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Failed to open parameters key. Status %x.\n", + registryPath, + status)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Failed to open service key %ws. Status %x.\n", + registryPath, + registryPath->Buffer, + status)); + } + +__Exit_DsmpOpenLoadBalanceSettingsKey: + + if (parametersKey) { + ZwClose(parametersKey); + } + + if (serviceKey) { + ZwClose(serviceKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpOpenLoadBalanceSettingsKey (RegPath %p): Exiting function with status %x.\n", + registryPath, + status)); + + return status; +} + + +NTSTATUS +DsmpOpenTargetsLoadBalanceSettingKey( + _In_ IN ACCESS_MASK AccessMask, + _Out_ OUT PHANDLE TargetsLoadBalanceSettingKey + ) +/*++ + +Routine Description: + + Open the target key in the registry. + + NOTE: It is the responsibility of the caller to close the returned handle. + +Arguements: + + AccessMask - Requested access with which to open key + LoadBalanceSettingsKey - handle of the key that is returned to the caller + +Return Value : + + STATUS_SUCCESS if we were able to successfully open the registry key. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE serviceKey = NULL; + HANDLE parametersKey = NULL; + PUNICODE_STRING registryPath = &(gDsmInitData.DsmWmiInfo.RegistryPath); + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING parametersKeyName; + UNICODE_STRING subKeyName; + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Entering function.\n", + registryPath)); + + if (!TargetsLoadBalanceSettingKey) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Invalid parameter.\n", + registryPath)); + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpOpenTargetsLoadBalanceSettingKey; + } + + *TargetsLoadBalanceSettingKey = NULL; + + // + // First check if registry path is available for msdsm. + // + if (!registryPath->Buffer) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Registry Path not set.\n", + registryPath)); + + goto __Exit_DsmpOpenTargetsLoadBalanceSettingKey; + } + + // + // Open the service key first + // + InitializeObjectAttributes(&objectAttributes, + registryPath, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + NULL, + NULL); + + status = ZwOpenKey(&serviceKey, + AccessMask, + &objectAttributes); + if (NT_SUCCESS(status)) { + + // + // Open Parameters key under the Service key + // + RtlInitUnicodeString(¶metersKeyName, DSM_SERVICE_PARAMETERS); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + ¶metersKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + serviceKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(¶metersKey, + AccessMask, + &objectAttributes); + + if (NT_SUCCESS(status)) { + + // + // Open LoadBalanceSettings key under the Parameters key + // + RtlInitUnicodeString(&subKeyName, DSM_TARGETS_LOAD_BALANCE_SETTING); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + parametersKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwCreateKey(TargetsLoadBalanceSettingKey, + AccessMask, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Failed to open/create TargetsLBSetting key. Status %x.\n", + registryPath, + status)); + + *TargetsLoadBalanceSettingKey = NULL; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Failed to open parameters key. Status %x.\n", + registryPath, + status)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Failed to open service key %ws. Status %x.\n", + registryPath, + registryPath->Buffer, + status)); + } + +__Exit_DsmpOpenTargetsLoadBalanceSettingKey: + + if (parametersKey) { + ZwClose(parametersKey); + } + + if (serviceKey) { + ZwClose(serviceKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpOpenTargetsLoadBalanceSettingKey (RegPath %p): Exiting function with status %x.\n", + registryPath, + status)); + + return status; +} + + +NTSTATUS +DsmpOpenDsmServicesParametersKey( + _In_ IN ACCESS_MASK AccessMask, + _Out_ OUT PHANDLE ParametersKey + ) +/*++ + +Routine Description: + + Open the DSM's Parameters key in the registry. + + NOTE: It is the responsibility of the caller to close the returned handle. + +Arguements: + + AccessMask - Requested access with which to open key + ParametersKey - handle of the key that is returned to the caller + +Return Value : + + STATUS_SUCCESS if we were able to successfully open the registry key. + + Appropriate NTSTATUS code on failure + +--*/ +{ + HANDLE serviceKey = NULL; + PUNICODE_STRING registryPath = &(gDsmInitData.DsmWmiInfo.RegistryPath); + OBJECT_ATTRIBUTES objectAttributes; + UNICODE_STRING parametersKeyName; + NTSTATUS status = STATUS_UNSUCCESSFUL; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpOpenDsmServicesParametersKey (RegPath %p): Entering function.\n", + registryPath)); + + if (!ParametersKey) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenDsmServicesParametersKey (RegPath %p): Invalid parameter.\n", + registryPath)); + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpOpenDsmServicesParametersKey; + } + + *ParametersKey = NULL; + + // + // First check if registry path is available for msdsm. + // + if (!registryPath->Buffer) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenDsmServicesParametersKey (RegPath %p): Registry Path not set.\n", + registryPath)); + + goto __Exit_DsmpOpenDsmServicesParametersKey; + } + + // + // Open the service key first + // + InitializeObjectAttributes(&objectAttributes, + registryPath, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + NULL, + NULL); + + status = ZwOpenKey(&serviceKey, + AccessMask, + &objectAttributes); + if (NT_SUCCESS(status)) { + + // + // Open Parameters key under the Service key + // + RtlInitUnicodeString(¶metersKeyName, DSM_SERVICE_PARAMETERS); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + ¶metersKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + serviceKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(ParametersKey, + AccessMask, + &objectAttributes); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenDsmServicesParametersKey (RegPath %p): Failed to open parameters key. Status %x.\n", + registryPath, + status)); + + *ParametersKey = NULL; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpOpenDsmServicesParametersKey (RegPath %p): Failed to open service key %ws. Status %x.\n", + registryPath, + registryPath->Buffer, + status)); + } + +__Exit_DsmpOpenDsmServicesParametersKey: + + if (serviceKey) { + ZwClose(serviceKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpOpenDsmServicesParametersKey (RegPath %p): Exiting function with status %x.\n", + registryPath, + status)); + + return status; +} + +NTSTATUS +DsmpReportTargetPortGroupsSyncCompletion( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +{ + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Context); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroupsSyncCompletion: IRP %p, Context %p\n", + Irp, Context)); + + KeSetEvent(Irp->UserEvent, 0, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +_Success_(return==0) +NTSTATUS +DsmpReportTargetPortGroups( + _In_ PDEVICE_OBJECT DeviceObject, + _Outptr_result_buffer_maybenull_(*TargetPortGroupsInfoLength) PUCHAR *TargetPortGroupsInfo, + _Out_ PULONG TargetPortGroupsInfoLength + ) +/*++ + +Routine Description: + + Helper routine to send down ReportTargetPortGroups request synchronously. + Used if device supports ALUA. + + Note: This routine will allocate memory for the TPG info. It is the + responsibility of the caller to free this buffer, but only if the function + returns STATUS_SUCCESS. + +Arguments: + + DeviceObject - The port PDO to which the command should be sent. + TargetPortGroupsInfo - buffer containing the returned data. + TargetPortGroupsInfoLength - size of the returned buffer. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + PSPC3_CDB_REPORT_TARGET_PORT_GROUPS cdb; + NTSTATUS status = STATUS_SUCCESS; + PIRP irp = NULL; + PMDL mdl = NULL; + PSCSI_REQUEST_BLOCK srb = NULL; + PSENSE_DATA_EX senseInfoBuffer = NULL; + UCHAR senseInfoBufferLength = 0; + KEVENT completionEvent; + ULONG targetPortGroupsInfoLength = 0; + PUCHAR targetPortGroupsInfo = NULL; + PIO_STACK_LOCATION irpStack = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Entering function.\n", + DeviceObject)); + + if (TargetPortGroupsInfoLength == NULL || + TargetPortGroupsInfo == NULL) { + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpReportTargetPortGroups; + } + + *TargetPortGroupsInfoLength = 0; + *TargetPortGroupsInfo = NULL; + + senseInfoBuffer = (PSENSE_DATA_EX)DsmpAllocatePool(NonPagedPoolNx, + SENSE_BUFFER_SIZE_EX, + DSM_TAG_SCSI_SENSE_INFO); + if (senseInfoBuffer != NULL) { + + senseInfoBufferLength = SENSE_BUFFER_SIZE_EX; + + srb = (PSCSI_REQUEST_BLOCK)DsmpAllocatePool(NonPagedPoolNx, + sizeof(SCSI_REQUEST_BLOCK), + DSM_TAG_SCSI_REQUEST_BLOCK); + if (srb != NULL) { + + SrbSetSenseInfoBufferLength(srb, senseInfoBufferLength); + SrbSetSenseInfoBuffer(srb, senseInfoBuffer); + + // + // Take care of worst case scenario, which is: + // 1. 4-byte header (for allocation length) + // 2. 32 8-byte descriptors (for TPGs) + // 3. Each descriptor containing 32 4-byte identifiers (for TPs in each TPG) + // + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + (DSM_MAX_PATHS * (sizeof(SPC3_REPORT_TARGET_PORT_GROUP_DESCRIPTOR) + + DSM_MAX_PATHS * sizeof(ULONG))); + + targetPortGroupsInfo = (PUCHAR)DsmpAllocatePool(NonPagedPoolNx, + targetPortGroupsInfoLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate TPG info.\n", + DeviceObject)); + goto __Exit_DsmpReportTargetPortGroups; + } + + } else { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate SRB.\n", + DeviceObject)); + goto __Exit_DsmpReportTargetPortGroups; + } + + } else { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate Sense Info Buffer.\n", + DeviceObject)); + goto __Exit_DsmpReportTargetPortGroups; + } + + irp = IoAllocateIrp(DeviceObject->StackSize + 1, FALSE); + if (irp == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate IRP.\n", + DeviceObject)); + goto __Exit_DsmpReportTargetPortGroups; + } + + mdl = IoAllocateMdl(targetPortGroupsInfo, + targetPortGroupsInfoLength, + FALSE, + FALSE, + irp); + + if (mdl == NULL) { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Failed to allocate MDL.\n", + DeviceObject)); + goto __Exit_DsmpReportTargetPortGroups; + } + + MmBuildMdlForNonPagedPool(mdl); + +__Retry_DsmpReportTargetPortGroups: + + irp->MdlAddress = mdl; + + // + // Set up SRB for execute scsi request. Save SRB address in next stack + // for the port driver. + // + irpStack = IoGetNextIrpStackLocation(irp); + irpStack->MajorFunction = IRP_MJ_SCSI; + irpStack->MinorFunction = IRP_MN_SCSI_CLASS; + irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)srb; + irpStack->DeviceObject = DeviceObject; + + // + // Set the completion event and the completion routine. + // + KeInitializeEvent(&completionEvent, NotificationEvent, FALSE); + irp->UserEvent = &completionEvent; + IoSetCompletionRoutine(irp, + DsmpReportTargetPortGroupsSyncCompletion, + srb, + TRUE, + TRUE, + TRUE); + + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + srb->Length = sizeof(SCSI_REQUEST_BLOCK); + + SrbSetCdbLength(srb, sizeof(SPC3_CDB_REPORT_TARGET_PORT_GROUPS)); + cdb = (PSPC3_CDB_REPORT_TARGET_PORT_GROUPS)SrbGetCdb(srb); + cdb->OperationCode = SPC3_SCSIOP_REPORT_TARGET_PORT_GROUPS; + cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; + REVERSE_BYTES(&(cdb->AllocationLength), &targetPortGroupsInfoLength); + + SrbSetTimeOutValue(srb, SPC3_REPORT_TARGET_PORT_GROUPS_TIMEOUT); + SrbSetDataTransferLength(srb, targetPortGroupsInfoLength); + SrbSetDataBuffer(srb, targetPortGroupsInfo); + srb->SrbStatus = 0; + SrbSetScsiStatus(srb, 0); + SrbSetNextSrb(srb, NULL); + SrbSetSrbFlags(srb, SRB_FLAGS_DONT_START_NEXT_PACKET | SRB_FLAGS_QUEUE_ACTION_ENABLE | + SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER | + SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE); + SrbSetQueueAction(srb, SRB_HEAD_OF_QUEUE_TAG_REQUEST); + SrbSetOriginalRequest(srb, irp); + + ObReferenceObject(DeviceObject); + + // + // Finally, send the IRP down and wait for its completion. + // + status = IoCallDriver(DeviceObject, irp); + + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&completionEvent, + Executive, + KernelMode, + FALSE, + NULL); + status = irp->IoStatus.Status; + } + + ObDereferenceObject(DeviceObject); + + if ((status == STATUS_BUFFER_OVERFLOW) || + (NT_SUCCESS(status) && (SrbGetScsiStatus(srb) == SCSISTAT_GOOD))) { + + // + // The first 4 bytes of the returned data are the Returned Data Length + // field of the RTPG header. + // + ULONG returnedDataLength = 0; + REVERSE_BYTES(&returnedDataLength, targetPortGroupsInfo); + + status = STATUS_SUCCESS; + if (returnedDataLength > SrbGetDataTransferLength(srb)) { + + status = STATUS_BUFFER_OVERFLOW; + } + } + + if (NT_SUCCESS(status) && SrbGetScsiStatus(srb) == SCSISTAT_GOOD) { + + // + // RTPG was successful so return the TPG info to the caller. + // + + // + // The first 4 bytes of the returned data are the Returned Data Length + // field of the RTPG header. We need to return this value plus the header size. + // + ULONG returnedDataLength = 0; + REVERSE_BYTES(&returnedDataLength, targetPortGroupsInfo); + *TargetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + returnedDataLength; + + *TargetPortGroupsInfo = targetPortGroupsInfo; + + } else if (SrbGetScsiStatus(srb) == SCSISTAT_CHECK_CONDITION) { + + if (DsmpShouldRetryTPGRequest(senseInfoBuffer, senseInfoBufferLength)) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Retrying request.\n", + DeviceObject)); + + IoReuseIrp(irp, STATUS_SUCCESS); + + RtlZeroMemory(senseInfoBuffer, senseInfoBufferLength); + + goto __Retry_DsmpReportTargetPortGroups; + } + + if (DsmpIsDeviceRemoved(senseInfoBuffer, senseInfoBufferLength)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Device not available.\n", + DeviceObject)); + + // + // Sense key was illegal request. SPC 6.25 says response to TPG should follow Test Unit Ready responses + // + status = STATUS_NO_SUCH_DEVICE; + + } + + // RTPG was unsuccessful + // Here it is possible that status is success, but scsi status is not. + // and there was no RTPG retry. If so, set status to unsuccessful. + if (NT_SUCCESS(status)) { + status = STATUS_UNSUCCESSFUL; + } + + // + // TPG resulted HW to respond with Check Condition but Sense Key indicates it is not for retry or illegal request + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): TPG returned Check Condition, NTStatus 0x%x, ScsiStatus 0x%x.\n", + DeviceObject, + status, + SrbGetScsiStatus(srb))); + } else { + + // RTPG was unsuccessful + // Here it is possible that status is success, but scsi status is not. + // If so, set status to unsuccessful. + if (NT_SUCCESS(status)) { + status = STATUS_UNSUCCESSFUL; + } + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): NTStatus 0x%x, ScsiStatus 0x%x.\n", + DeviceObject, + status, + SrbGetScsiStatus(srb))); + } + +__Exit_DsmpReportTargetPortGroups: + + // + // The port driver may have allocated its own sense buffer so we need to + // make sure we free that here. + // + if (srb != NULL && + SrbGetSrbFlags(srb) & SRB_FLAGS_PORT_DRIVER_ALLOCSENSE && + SrbGetSrbFlags(srb) & SRB_FLAGS_FREE_SENSE_BUFFER && + SrbGetSenseInfoBuffer(srb) != NULL) { + DsmpFreePool(SrbGetSenseInfoBuffer(srb)); + } + + if (senseInfoBuffer) { + DsmpFreePool(senseInfoBuffer); + } + + if (srb) { + DsmpFreePool(srb); + } + + if (irp) { + if (irp->MdlAddress) { + IoFreeMdl(irp->MdlAddress); + } + IoFreeIrp(irp); + } + + if (!NT_SUCCESS(status) && targetPortGroupsInfo) { + DsmpFreePool(targetPortGroupsInfo); + *TargetPortGroupsInfoLength = 0; + *TargetPortGroupsInfo = NULL; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpReportTargetPortGroups (DevObj %p): Exiting function with status %x.\n", + DeviceObject, + status)); + + return status; +} + +NTSTATUS +DsmpReportTargetPortGroupsAsync( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, + _Inout_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, + _In_ IN ULONG TargetPortGroupsInfoLength, + _Inout_ __drv_aliasesMem IN OUT PUCHAR TargetPortGroupsInfo + ) +/*++ + +Routine Description: + + Helper routine to send down ReportTargetPortGroups request asynchronously. + Used if device supports ALUA. + + NOTE: Caller needs to free Irp, system buffer, and passThrough buffer. + +Arguments: + + DeviceInfo - The deviceInfo whose corresponding port PDO the command should be sent to. + CompletionRoutine - completion routine passed in by the caller. + CompletionContext - context to be passed to be completion routine. + TargetPortGroupsInfoLength - size of the returned buffer. + TargetPortGroupsInfo - preallocated (by caller) buffer that'll contain the returned data. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = CompletionContext; + PSCSI_REQUEST_BLOCK srb = NULL; + PSPC3_CDB_REPORT_TARGET_PORT_GROUPS cdb; + NTSTATUS status; + PIRP irp = NULL; + PIO_STACK_LOCATION irpStack; + PMDL mdl = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpReportTargetPortGroupsAsync (DevInfo %p): Entering function.\n", + DeviceInfo)); + + srb = tpgCompletionContext->Srb; + + SrbZeroSrb(srb); + + // + // Allocate an irp. + // + irp = IoAllocateIrp(DeviceInfo->TargetObject->StackSize + 1, FALSE); + if (!irp) { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpReportTargetPortGroupsAsync (DevInfo %p): Failed to allocate IRP.\n", + DeviceInfo)); + goto __Exit_DsmpReportTargetPortGroupsAsync; + } + + mdl = IoAllocateMdl(TargetPortGroupsInfo, + TargetPortGroupsInfoLength, + FALSE, + FALSE, + irp); + if (!mdl) { + + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpReportTargetPortGroupsAsync (DevInfo %p): Failed to allocate MDL.\n", + DeviceInfo)); + goto __Exit_DsmpReportTargetPortGroupsAsync; + } + + MmBuildMdlForNonPagedPool(irp->MdlAddress); + + // + // It is possible that if an implicit access state transition took place, + // each I_T nexus will return UA for asymmetric access state changed. So + // set the number of retries to be one more than the total number of paths. + // Worst case scenario is the it is sent down each path once (assuming every + // is a different I_T nexus) and then one more for a retry one one of the + // paths. + // + tpgCompletionContext->NumberRetries = DeviceInfo->Group->NumberDevices + 1; + + // + // Set-up the completion routine. + // + IoSetCompletionRoutine(irp, + CompletionRoutine, + (PVOID)CompletionContext, + TRUE, + TRUE, + TRUE); + + // + // Get the recipient's irpstack location. + // + irpStack = IoGetNextIrpStackLocation(irp); + + irpStack->Parameters.Scsi.Srb = srb; + irpStack->DeviceObject = DeviceInfo->TargetObject; + + // + // Set the major function code to IRP_MJ_SCSI. + // + irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + + // + // Set the minor function, or many requests will get kicked by by port. + // + irpStack->MinorFunction = IRP_MN_SCSI_CLASS; + + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + srb->Length = sizeof(SCSI_REQUEST_BLOCK); + + SrbSetCdbLength(srb, sizeof(SPC3_CDB_REPORT_TARGET_PORT_GROUPS)); + cdb = (PSPC3_CDB_REPORT_TARGET_PORT_GROUPS)SrbGetCdb(srb); + cdb->OperationCode = SPC3_SCSIOP_REPORT_TARGET_PORT_GROUPS; + cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; + Get4ByteArrayFromUlong(TargetPortGroupsInfoLength, cdb->AllocationLength); + + SrbSetTimeOutValue(srb, SPC3_REPORT_TARGET_PORT_GROUPS_TIMEOUT); + SrbSetSenseInfoBuffer(srb, tpgCompletionContext->SenseInfoBuffer); + SrbSetSenseInfoBufferLength(srb, tpgCompletionContext->SenseInfoBufferLength); + SrbSetDataTransferLength(srb, TargetPortGroupsInfoLength); + SrbSetDataBuffer(srb, TargetPortGroupsInfo); + srb->SrbStatus = 0; + SrbSetScsiStatus(srb, 0); + SrbSetNextSrb(srb, NULL); + SrbSetSrbFlags(srb, SRB_FLAGS_DONT_START_NEXT_PACKET | SRB_FLAGS_QUEUE_ACTION_ENABLE | + SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER | + SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE); + SrbSetQueueAction(srb, SRB_HEAD_OF_QUEUE_TAG_REQUEST); + SrbSetOriginalRequest(srb, irp); + + irp->UserBuffer = TargetPortGroupsInfo; + irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + // + // Send the IRP asynchronously + // + DsmSendRequestEx(((PDSM_CONTEXT)(DeviceInfo->DsmContext))->MPIOContext, + DeviceInfo->TargetObject, + irp, + (PVOID)DeviceInfo, + DSM_CALL_COMPLETION_ON_MPIO_ERROR); + + // + // We know that the completion routine will always be called. + // + status = STATUS_PENDING; + +__Exit_DsmpReportTargetPortGroupsAsync: + + if (status != STATUS_PENDING) { + + // + // This indicates Irp was never sent down to stack (completion routine was never called). + // We need to clean up. + // + if (irp) { + + if (irp->MdlAddress) { + IoFreeMdl(irp->MdlAddress); + } + + IoFreeIrp(irp); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpReportTargetPortGroupsAsync (DevInfo %p): Exiting function with status %x\n.", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryLBPolicyForDevice( + _In_ IN PWSTR RegistryKeyName, + _In_ IN ULONGLONG PathId, + _In_ IN DSM_LOAD_BALANCE_TYPE LoadBalanceType, + _Out_ OUT PULONG PrimaryPath, + _Out_ OUT PULONG OptimizedPath, + _Out_ OUT PULONG PathWeight + ) +/*++ + +Routine Description: + + This routine opens the device's registry subkey, builds the path subkey from + the passed in PathId, then queries that subkey for the value of PrimaryPath, + OptimizedPath and PathWeight. + +Arguments: + + RegistryKeyName - The device's registry subkey name. + PathId - The pathId for this instance of the device. + LoadBalanceType - The current load balance policy. + PrimaryPath - Output of the queried PrimaryPath value. + OptimizedPath - Output of the queried OptimizedPath value. + PathWeight - Output of the queried PathWeight value. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + HANDLE lbSettingsKey = NULL; + HANDLE deviceKey = NULL; + HANDLE dsmPathKey = NULL; + UNICODE_STRING subKeyName; + WCHAR dsmPathName[128] = {0}; + OBJECT_ATTRIBUTES objectAttributes; + NTSTATUS status; + NTSTATUS pathWeightQueryStatus = STATUS_SUCCESS; + + PAGED_CODE(); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Entering function.\n", + RegistryKeyName)); + + // + // Query PrimaryPath and PathWeight for the given path. + // These values are stored under DsmPath#Suffix key for + // this path. If this key doesn't exist create it and + // create PrimaryPath and PathWeight values - use the + // values passed in PrimaryPath and PathWeight in this case. + // + status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to open LB Settings key. Status %x.\n", + RegistryKeyName, + status)); + + goto __Exit_DsmpQueryLBPolicyForDevice; + } + + RtlInitUnicodeString(&subKeyName, RegistryKeyName); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + lbSettingsKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(&deviceKey, KEY_ALL_ACCESS, &objectAttributes); + if (NT_SUCCESS(status)) { + + // + // Create or open DsmPath#Suffix key for this path + // + DsmpGetDSMPathKeyName(PathId, dsmPathName, 128); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Will query %ws for PrimaryPath, OptimizedPath and PathWeight.\n", + RegistryKeyName, + dsmPathName)); + + RtlInitUnicodeString(&subKeyName, dsmPathName); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + deviceKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwCreateKey(&dsmPathKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (NT_SUCCESS(status)) { + + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + + // + // Query the Path Weight value. + // + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | + RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_PATH_WEIGHT; + queryTable[0].EntryContext = PathWeight; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + pathWeightQueryStatus = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + dsmPathKey, + queryTable, + dsmPathKey, + NULL); + + if (!NT_SUCCESS(pathWeightQueryStatus)) { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to query PathWeight. Status %x.\n", + RegistryKeyName, + pathWeightQueryStatus)); + } + + // + // Query the Primary Path value. + // + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | + RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_PRIMARY_PATH; + queryTable[0].EntryContext = PrimaryPath; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + dsmPathKey, + queryTable, + dsmPathKey, + NULL); + if (NT_SUCCESS(status)) { + + // + // Query the Optimized Path value. + // + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | + RTL_QUERY_REGISTRY_REQUIRED | + RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_OPTIMIZED_PATH; + queryTable[0].EntryContext = OptimizedPath; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + dsmPathKey, + queryTable, + dsmPathKey, + NULL); + if (!NT_SUCCESS(status)) { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to query OptimizedPath. Status %x.\n", + RegistryKeyName, + status)); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to query PrimaryPath. Status %x.\n", + RegistryKeyName, + status)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to create DSM Path key %ws. Status %x.\n", + RegistryKeyName, + dsmPathName, + status)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Failed to open key. Status %x.\n", + RegistryKeyName, + status)); + } + + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): PrimaryPath %d, OptmizedPath %d, PathWeight %d.\n", + RegistryKeyName, + *PrimaryPath, + *OptimizedPath, + *PathWeight)); + } + +__Exit_DsmpQueryLBPolicyForDevice: + + if (dsmPathKey) { + ZwClose(dsmPathKey); + } + + if (deviceKey) { + ZwClose(deviceKey); + } + + if (lbSettingsKey) { + ZwClose(lbSettingsKey); + } + + // + // If the load balance policy is Weighted Paths and we failed to read in + // the path weight value, we need to return the failure status from the + // path weight value query. + // + if (LoadBalanceType == DSM_LB_WEIGHTED_PATHS && !NT_SUCCESS(pathWeightQueryStatus)) { + status = pathWeightQueryStatus; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryLBPolicyForDevice (DevName %ws): Exiting function with status %x.\n", + RegistryKeyName, + status)); + + return status; +} + + +VOID +DsmpGetDSMPathKeyName( + _In_ ULONGLONG DSMPathId, + _Out_writes_(DsmPathKeyNameSize) PWCHAR DsmPathKeyName, + _In_ ULONG DsmPathKeyNameSize + ) +/*++ + +Routine Description: + + This routine builds the string that corresponds to the device's Path subkey + name in the registry. + +Arguments: + + DSMPathId - The pathId of this instance of the device. + DsmPathKeyName - Output buffer in which the subkey name for path is returned. + DsmPathKeyNameSize - size of the output buffer in WCHARs. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + PWCHAR pathPtr; + SIZE_T wcharsLeft; + SIZE_T size; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetDSMPathKeyName (PathId %I64x): Entering function.\n", + DSMPathId)); + + // + // This routine will build a name for a given DSM Path. + // The name is of the format DsmPath#Suffix, where Suffix + // is derived from the PathId + // + pathPtr = DsmPathKeyName; + + wcharsLeft = DsmPathKeyNameSize; + + size = wcslen(DSM_PATH); + + if (size < wcharsLeft) { + + // + // First copy the string DsmPath# + // + if (NT_SUCCESS(RtlStringCchCopyNW(pathPtr, wcharsLeft, DSM_PATH, wcslen(DSM_PATH)))) { + + wcharsLeft -= size; + pathPtr += size; + + if (wcharsLeft > 2) { + + RtlStringCchCatW(pathPtr, wcharsLeft, L"#"); + wcharsLeft--; + pathPtr++; + + // + // Each nibble in the path id would need 1 WCHAR + // upon conversion to WCHAR string. So we'll need + // 2 WCHARs for each byte. Include the NULL char also + // + size = (sizeof(PVOID) + 1) * 2; + if (size <= wcharsLeft) { + + PVOID pathId; + PUCHAR pathIdPtr; + ULONG inx; + UCHAR tmpChar; + + // + // Convert the ULONGLONG path id to a string and + // append that to DsmPath# + // + pathId = (PVOID) DSMPathId; + + pathIdPtr = (PUCHAR) &pathId; + + for (inx = 0; inx < sizeof(PVOID); inx++) { + + tmpChar = (*pathIdPtr & 0xF0) >> 4; + *pathPtr++ = DsmpGetAsciiForBinary(tmpChar); + + tmpChar = (*pathIdPtr & 0x0F); + *pathPtr++ = DsmpGetAsciiForBinary(tmpChar); + + pathIdPtr++; + } + + *pathPtr = WNULL; + } + } + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetDSMPathKeyName (PathId %I64x): Exiting function.\n", + DSMPathId)); + + return; +} + + +UCHAR +DsmpGetAsciiForBinary( + _In_ UCHAR BinaryChar + ) +/*++ + +Routine Description: + + This routine converts the passed in binary value into ASCII equivalent. + +Arguments: + + BinaryChar - The binary value that needs to be converted. + +Return Value: + + Corresponding ASCII value. + +--*/ +{ + UCHAR outChar = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetAsciiForBinary (BinaryChar %d): Entering function.\n", + BinaryChar)); + + // + // Convert a binary nibble into an ASCII character. + // + if ((BinaryChar >= 0) && (BinaryChar <= 9)) { + outChar = BinaryChar + '0'; + } else { + outChar = BinaryChar + 'A' - 10; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetAsciiForBinary (BinaryChar %d): Exiting function with outChar %c.\n", + BinaryChar, + outChar)); + + return outChar; +} + + +NTSTATUS +DsmpGetDeviceIdList( + _In_ IN PDEVICE_OBJECT DeviceObject, + _Out_ OUT PSTORAGE_DESCRIPTOR_HEADER *Descriptor + ) +/*++ + +Routine Description: + + This routine will perform a query for the StorageDeviceIdProperty and will + allocate a non-paged buffer to store the data in. + IMPORTANT: It is the responsibility of the caller to ensure that this buffer is freed. + +Arguments: + + DeviceObject - the device to query + Descriptor - a location to store a pointer to the buffer we allocate + +Return Value: + + status. + +--*/ +{ + STORAGE_PROPERTY_QUERY query; + PIO_STATUS_BLOCK ioStatus = NULL; + PSTORAGE_DESCRIPTOR_HEADER descriptor = NULL; + ULONG length; + NTSTATUS status = STATUS_UNSUCCESSFUL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetDeviceIdList (DevObj %p): Entering function.\n", + DeviceObject)); + + if (!DeviceObject) { + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpGetDeviceIdList; + } + + // + // Poison the passed in descriptor. + // + *Descriptor = NULL; + + // + // Setup the query buffer. + // + query.PropertyId = StorageDeviceIdProperty; + query.QueryType = PropertyStandardQuery; + query.AdditionalParameters[0] = 0; + + ioStatus = DsmpAllocatePool(NonPagedPoolNx, sizeof(IO_STATUS_BLOCK), DSM_TAG_IO_STATUS_BLOCK); + + if (!ioStatus) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetDeviceIdList (DevObj %p): Failed to allocate an IO_STATUS_BLOCK.\n", + DeviceObject)); + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpGetDeviceIdList; + } + + ioStatus->Status = 0; + ioStatus->Information = 0; + + // + // On the first call, just need to get the length of the descriptor. + // + descriptor = (PVOID)&query; + DsmSendDeviceIoControlSynchronous(IOCTL_STORAGE_QUERY_PROPERTY, + DeviceObject, + &query, + &query, + sizeof(STORAGE_PROPERTY_QUERY), + sizeof(STORAGE_DESCRIPTOR_HEADER), + FALSE, + ioStatus); + + status = ioStatus->Status; + + if(!NT_SUCCESS(status)) { + + descriptor = NULL; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetDeviceIdList (DevObj %p): Query failed (%x) on attempt 1.\n", + DeviceObject, + ioStatus->Status)); + + goto __Exit_DsmpGetDeviceIdList; + } + + NT_ASSERT(descriptor->Size); + if (descriptor->Size == 0) { + status = STATUS_UNSUCCESSFUL; + goto __Exit_DsmpGetDeviceIdList; + } + + // + // This time we know how much data there is so we can + // allocate a buffer of the correct size + // + length = descriptor->Size; + + descriptor = DsmpAllocatePool(NonPagedPoolNx, length, DSM_TAG_DEVICE_ID_LIST); + + if(!descriptor) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetDeviceIdList (DevObj %p): Couldn't allocate descriptor of %ld.\n", + DeviceObject, + length)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpGetDeviceIdList; + } + + // + // setup the query again. + // + query.PropertyId = StorageDeviceIdProperty; + query.QueryType = PropertyStandardQuery; + query.AdditionalParameters[0] = 0; + + // + // copy the input to the new outputbuffer + // + RtlCopyMemory(descriptor, + &query, + sizeof(STORAGE_PROPERTY_QUERY)); + + DsmSendDeviceIoControlSynchronous(IOCTL_STORAGE_QUERY_PROPERTY, + DeviceObject, + descriptor, + descriptor, + sizeof(STORAGE_PROPERTY_QUERY), + length, + 0, + ioStatus); + + status = ioStatus->Status; + + if(!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpGetDeviceIdList (DevObj %p): Query Failed (%x) on attempt 2.\n", + DeviceObject, + ioStatus->Status)); + + goto __Exit_DsmpGetDeviceIdList; + } + +__Exit_DsmpGetDeviceIdList: + + if (ioStatus) { + DsmpFreePool(ioStatus); + } + + if (!NT_SUCCESS(status)) { + + if (descriptor) { + DsmpFreePool(descriptor); + } + + } else { + *Descriptor = descriptor; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetDeviceIdList (DevObj %p): Exiting function with status %x.\n", + DeviceObject, + status)); + + return status; +} + + +NTSTATUS +DsmpSetTargetPortGroups( + _In_ IN PDEVICE_OBJECT DeviceObject, + _In_reads_bytes_(TargetPortGroupsInfoLength) IN PUCHAR TargetPortGroupsInfo, + _In_ IN ULONG TargetPortGroupsInfoLength + ) +/*++ + +Routine Description: + + Helper routine to send down SetTargetPortGroups request. + +Arguments: + + DeviceObject - The port PDO to which the command should be sent. + TargetPortGroupsInfo - buffer containing the TPG data. + TargetPortGroupsInfoLength - size of the TPG buffer. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER passThrough; + PSPC3_CDB_SET_TARGET_PORT_GROUPS cdb; + IO_STATUS_BLOCK ioStatus; + ULONG alignmentMask = DeviceObject->AlignmentRequirement; + PUCHAR dataBuffer = NULL; + SIZE_T allocatedLength = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpSetTargetPortGroups (DevObj %p): Entering function.\n", + DeviceObject)); + + NT_ASSERT(TargetPortGroupsInfoLength && TargetPortGroupsInfo); + + // + // Build request. + // + RtlZeroMemory(&passThrough, sizeof(passThrough)); + + dataBuffer = DsmpAllocateAlignedPool(NonPagedPoolNx, + TargetPortGroupsInfoLength, + alignmentMask, + DSM_TAG_PASS_THRU, + &allocatedLength); + if (!dataBuffer) { + + status = STATUS_INSUFFICIENT_RESOURCES; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetTargetPortGroups (DevObj %p): Failed to allocate mem for passthrough's databuffer.\n", + DeviceObject)); + goto __Exit_DsmpSetTargetPortGroups; + } + +__Retry_Request: + + // + // Build the cdb. + // + cdb = (PSPC3_CDB_SET_TARGET_PORT_GROUPS)passThrough.ScsiPassThroughDirect.Cdb; + + cdb->OperationCode = SPC3_SCSIOP_SET_TARGET_PORT_GROUPS; + cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; + Get4ByteArrayFromUlong(TargetPortGroupsInfoLength, cdb->ParameterListLength); + + passThrough.ScsiPassThroughDirect.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); + passThrough.ScsiPassThroughDirect.CdbLength = 12; + passThrough.ScsiPassThroughDirect.SenseInfoLength = SPTWB_SENSE_LENGTH; + passThrough.ScsiPassThroughDirect.DataIn = 0; + passThrough.ScsiPassThroughDirect.DataTransferLength = TargetPortGroupsInfoLength; + passThrough.ScsiPassThroughDirect.TimeOutValue = 20; + passThrough.ScsiPassThroughDirect.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, SenseInfoBuffer); + passThrough.ScsiPassThroughDirect.DataBuffer = dataBuffer; + RtlCopyMemory(dataBuffer, + TargetPortGroupsInfo, + TargetPortGroupsInfoLength); + + DsmSendDeviceIoControlSynchronous(IOCTL_SCSI_PASS_THROUGH_DIRECT, + DeviceObject, + &passThrough, + &passThrough, + sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), + sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), + FALSE, + &ioStatus); + + if ((passThrough.ScsiPassThroughDirect.ScsiStatus == SCSISTAT_GOOD) && + (NT_SUCCESS(ioStatus.Status))) { + + status = STATUS_SUCCESS; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetTargetPortGroups (DevObj %p): STPG succeeded.\n", + DeviceObject)); + + } else if (NT_SUCCESS(ioStatus.Status) && + passThrough.ScsiPassThroughDirect.ScsiStatus == SCSISTAT_CHECK_CONDITION && + DsmpShouldRetryTPGRequest((PSENSE_DATA)&passThrough.SenseInfoBuffer, passThrough.ScsiPassThroughDirect.SenseInfoLength)) { + + // + // Retry the request + // + RtlZeroMemory(dataBuffer, TargetPortGroupsInfoLength); + goto __Retry_Request; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetTargetPortGroups (DevObj %p): NTStatus 0%x, ScsiStatus 0x%x.\n", + DeviceObject, + ioStatus.Status, + passThrough.ScsiPassThroughDirect.ScsiStatus)); + + status = ioStatus.Status; + } + +__Exit_DsmpSetTargetPortGroups: + + // + // Free the passthrough + data buffer. + // + if (dataBuffer) { + DsmpFreePool(dataBuffer); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpSetTargetPortGroups (DevObj %p): Exiting function with status %x.\n", + DeviceObject, + status)); + + return status; +} + + +NTSTATUS +DsmpSetTargetPortGroupsAsync( + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN PIO_COMPLETION_ROUTINE CompletionRoutine, + _In_ __drv_aliasesMem IN PDSM_TPG_COMPLETION_CONTEXT CompletionContext, + _In_ IN ULONG TargetPortGroupsInfoLength, + _In_ __drv_aliasesMem IN PUCHAR TargetPortGroupsInfo + ) +/*++ + +Routine Description: + + Helper routine to send down SetTargetPortGroups request asynchronously. + + IMPORTANT: Caller needs to free the IRP and allocated system buffer. + +Arguments: + + DeviceInfo - The deviceInfo whose corresponding port PDO the command should be sent to. + CompletionRoutine - completion routine provided by the caller. + CompletionContext - context passed into the completion routine. + TargetPortGroupsInfoLength - size of the TPG buffer. + TargetPortGroupsInfo - buffer containing the TPG data. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + PDSM_TPG_COMPLETION_CONTEXT tpgCompletionContext = CompletionContext; + PSCSI_REQUEST_BLOCK srb; + PSPC3_CDB_SET_TARGET_PORT_GROUPS cdb; + NTSTATUS status; + PIRP irp = NULL; + PIO_STACK_LOCATION irpStack; + PMDL mdl = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetTargetPortGroupsAsync (DevInfo %p): Entering function.\n", + DeviceInfo)); + + srb = tpgCompletionContext->Srb; + + SrbZeroSrb(srb); + + // + // Allocate an irp. + // + irp = IoAllocateIrp(DeviceInfo->TargetObject->StackSize + 1, FALSE); + if (!irp) { + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetTargetPortGroupsAsync (DevInfo %p): Failed to allocate IRP.\n", + DeviceInfo)); + goto __Exit_DsmpSetTargetPortGroupsAsync; + } + + mdl = IoAllocateMdl(TargetPortGroupsInfo, + TargetPortGroupsInfoLength, + FALSE, + FALSE, + irp); + if (!mdl) { + + status = STATUS_INSUFFICIENT_RESOURCES; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_RW, + "DsmpSetTargetPortGroupsAsync (DevInfo %p): Failed to allocate MDL.\n", + DeviceInfo)); + goto __Exit_DsmpSetTargetPortGroupsAsync; + } + + MmBuildMdlForNonPagedPool(irp->MdlAddress); + + // + // It is possible that an implicit state transition may have occurred which + // will cause every I_T nexus to return an UA (for asymmetric access state + // changed). So set the number of retries to number of paths (worst case of + // every path being a separate I_T nexus) plus one for a retry down one of + // paths. + // + tpgCompletionContext->NumberRetries = DeviceInfo->Group->NumberDevices + 1; + + // + // Set-up the completion routine. + // + IoSetCompletionRoutine(irp, + CompletionRoutine, + (PVOID)CompletionContext, + TRUE, + TRUE, + TRUE); + + // + // Get the recipient's irpstack location. + // + irpStack = IoGetNextIrpStackLocation(irp); + + irpStack->Parameters.Scsi.Srb = srb; + irpStack->DeviceObject = DeviceInfo->TargetObject; + + // + // Set the major function code to IRP_MJ_SCSI. + // + irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; + + // + // Set the minor function, or many requests will get kicked by by port. + // + irpStack->MinorFunction = IRP_MN_SCSI_CLASS; + + srb->Function = SRB_FUNCTION_EXECUTE_SCSI; + srb->Length = sizeof(SCSI_REQUEST_BLOCK); + + SrbSetCdbLength(srb, sizeof(SPC3_CDB_SET_TARGET_PORT_GROUPS)); + cdb = (PSPC3_CDB_SET_TARGET_PORT_GROUPS)SrbGetCdb(srb); + cdb->OperationCode = SPC3_SCSIOP_SET_TARGET_PORT_GROUPS; + cdb->ServiceAction = SPC3_SERVICE_ACTION_TARGET_PORT_GROUPS; + Get4ByteArrayFromUlong(TargetPortGroupsInfoLength, cdb->ParameterListLength); + + SrbSetTimeOutValue(srb, SPC3_SET_TARGET_PORT_GROUPS_TIMEOUT); + SrbSetSenseInfoBuffer(srb, tpgCompletionContext->SenseInfoBuffer); + SrbSetSenseInfoBufferLength(srb, tpgCompletionContext->SenseInfoBufferLength); + SrbSetDataTransferLength(srb, TargetPortGroupsInfoLength); + SrbSetDataBuffer(srb, TargetPortGroupsInfo); + srb->SrbStatus = 0; + SrbSetScsiStatus(srb, 0); + SrbSetNextSrb(srb, NULL); + SrbSetSrbFlags(srb, SRB_FLAGS_DONT_START_NEXT_PACKET | SRB_FLAGS_QUEUE_ACTION_ENABLE | + SRB_FLAGS_DATA_OUT | SRB_FLAGS_DISABLE_SYNCH_TRANSFER | + SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE); + SrbSetQueueAction(srb, SRB_HEAD_OF_QUEUE_TAG_REQUEST); + SrbSetOriginalRequest(srb, irp); + + irp->UserBuffer = TargetPortGroupsInfo; + irp->Tail.Overlay.Thread = PsGetCurrentThread(); + + // + // Send the IRP asynchronously + // + DsmSendRequestEx(((PDSM_CONTEXT)(DeviceInfo->DsmContext))->MPIOContext, + DeviceInfo->TargetObject, + irp, + DeviceInfo, + DSM_CALL_COMPLETION_ON_MPIO_ERROR); + + // + // We know that the completion routine will always be called. + // + status = STATUS_PENDING; + + +__Exit_DsmpSetTargetPortGroupsAsync: + + if (status != STATUS_PENDING) { + + // + // This indicates Irp was never sent down to stack (completion routine was never called). + // We need to clean up. + // + if (irp) { + + if (irp->MdlAddress) { + IoFreeMdl(irp->MdlAddress); + } + + IoFreeIrp(irp); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_RW, + "DsmpSetTargetPortGroupsAsync (DevInfo %p): Exiting function with status %x.\n", + DeviceInfo, + status)); + + return status; +} + + +PDSM_LOAD_BALANCE_POLICY_SETTINGS +DsmpCopyLoadBalancePolicies( + _In_ IN PDSM_GROUP_ENTRY GroupEntry, + _In_ IN ULONG DsmWmiVersion, + _In_ IN PVOID SupportedLBPolicies + ) +/*+++ + +Routine Description: + + This routine copies the LB Policies that needs to be persisted in registry. + This is done because registry routines can be called at PASSIVE IRQL only. + So a spinlock cannot be held while accessing registry. So hold a spinlock, + save the values in a temp buffer, release spinlock, and save data to registry + from the temp buffer. + + NOTE: This routine MUST be called with DSM_CONTEXT lock held. + +Arguements: + + GroupEntry - Group entry + DsmWmiVersion - version of the MPIO_DSM_Path class to use + SupportedLBPolicies - LB policy for the group + + Return Value: + + Pointer to LOAD_BALANCE_POLICY_SETTINGS if successful. Else, NULL +--*/ +{ + PDSM_LOAD_BALANCE_POLICY_SETTINGS lbSettings = NULL; + ULONG sizeNeeded; + ULONG inx; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpCopyLoadBalancePolicies (Group %p): Entering function.\n", + GroupEntry)); + + if (((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount == 0) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpCopyLoadBalancePolicies (Group %p): No paths specified in Set LB policies.\n", + GroupEntry)); + + goto __Exit_DsmpCopyLoadBalancePolicies; + } + + sizeNeeded = sizeof(DSM_LOAD_BALANCE_POLICY_SETTINGS) + + ((((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount - 1) * sizeof(MPIO_DSM_Path_V2));; + + lbSettings = DsmpAllocatePool(NonPagedPoolNx, + sizeNeeded, + DSM_TAG_LB_POLICY); + + if (!lbSettings) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpCopyLoadBalancePolicies (Group %p): Failed to allocate memory for LBSettings.\n", + GroupEntry)); + goto __Exit_DsmpCopyLoadBalancePolicies; + } + + // + // Copy the registry key name used to store the LB policies. + // + RtlStringCchCopyNW(lbSettings->RegistryKeyName, + sizeof(lbSettings->RegistryKeyName) / sizeof(lbSettings->RegistryKeyName[0]), + GroupEntry->RegistryKeyName, + ((sizeof(lbSettings->RegistryKeyName) - sizeof(WCHAR))/sizeof(WCHAR))); + + // + // Copy the Load Balance settings for this group + // + lbSettings->LoadBalancePolicy = ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->LoadBalancePolicy; + + lbSettings->PathCount = ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount; + + for (inx = 0; inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount; inx++) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + RtlCopyMemory(&(lbSettings->DsmPath[inx]), + &(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]), + sizeof(MPIO_DSM_Path)); + + // + // DSM_WMI_VERSION_1 supports only active and standby states + // + (lbSettings->DsmPath[inx]).OptimizedPath = TRUE; + + } else { + + RtlCopyMemory(&(lbSettings->DsmPath[inx]), + &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]), + sizeof(MPIO_DSM_Path_V2)); + } + } + +__Exit_DsmpCopyLoadBalancePolicies: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpCopyLoadBalancePolicies (Group %p): Exiting function with lbSettings %p.\n", + GroupEntry, + lbSettings)); + + return lbSettings; +} + + +NTSTATUS +DsmpPersistLBSettings( + _In_ IN PDSM_LOAD_BALANCE_POLICY_SETTINGS LoadBalanceSettings + ) +/*+++ + +Routine Description: + + This routine will save the Load Balance settings from LoadBalanceSettings + to registry. + + NOTE: This routine MUST be called at PASSIVE IRQL + + The format of the registry tree is : + + Services\MSDSM\LoadBalanceSettings -> + + DeviceName -> LoadBalancePolicy REG_DWORD + + DsmPath#Suffix -> PrimaryPath REG_DWORD + OptimizedPath REG_DWORD + PathWeight REG_DWORD + + The device name is the one built in DsmpBuildDeviceName + + The Suffix in DsmPath#Suffix is built from the PathId. It is built in + the routine DsmpGetDSMPathKeyName. + +Arguements: + + LoadBalanceSettings - Load Balance settings to be persisted in registry + +Return Value: + + STATUS_SUCCESS if the data could be successfully stored in the registry + Appropriate NT Status code on failure. +--*/ +{ + PMPIO_DSM_Path_V2 dsmPath; + HANDLE lbSettingsKey = NULL; + HANDLE deviceKey = NULL; + HANDLE dsmPathKey = NULL; + UNICODE_STRING subKeyName; + WCHAR dsmPathName[128]; + OBJECT_ATTRIBUTES objectAttributes; + NTSTATUS status; + ULONG inx; + PMPIO_DSM_Path_V2 preferredPath = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Entering function.\n", + LoadBalanceSettings->RegistryKeyName)); + + // + // First open LoadBalanceSettings key under the Service key + // + status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to open LB Settings key. Status %x.\n", + LoadBalanceSettings->RegistryKeyName, + status)); + + goto __Exit_DsmpPersistLBSettings; + } + + // + // Now open the key under which the LB settings for the given device is stored + // + RtlInitUnicodeString(&subKeyName, LoadBalanceSettings->RegistryKeyName); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + lbSettingsKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(&deviceKey, KEY_ALL_ACCESS, &objectAttributes); + + if (NT_SUCCESS(status)) { + + // + // Remove all LB policy information as we are going to rewrite it. + // We do this in case there is stale information about a path that + // no longer exists + // + status = DsmpRegDeleteTree(deviceKey); + + if (NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Deleted key along with its subkeys.\n", + LoadBalanceSettings->RegistryKeyName)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to delete key. Status %x\n", + LoadBalanceSettings->RegistryKeyName, + status)); + + } + + ZwClose(deviceKey); + deviceKey = NULL; + + } + + status = ZwCreateKey(&deviceKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (NT_SUCCESS(status)) { + + PDSM_DEVICE_INFO devInfo; + + for (inx = 0; inx < LoadBalanceSettings->PathCount; inx++) { + + dsmPath = &(LoadBalanceSettings->DsmPath[inx]); + + if (dsmPath->DsmPathId == 0) { + + continue; + } + + RtlZeroMemory(dsmPathName, sizeof(dsmPathName)); + + // + // Get the sub key name under which the LB settings for + // the given path is stored. + // + DsmpGetDSMPathKeyName(dsmPath->DsmPathId, dsmPathName, 128); + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Will open subkey %ws.\n", + LoadBalanceSettings->RegistryKeyName, + dsmPathName)); + + RtlInitUnicodeString(&subKeyName, dsmPathName); + + RtlZeroMemory(&objectAttributes, sizeof(OBJECT_ATTRIBUTES)); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + deviceKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwCreateKey(&dsmPathKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (NT_SUCCESS(status)) { + + if (dsmPath->PreferredPath) { + + preferredPath = dsmPath; + } + + devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; + + // + // Save PrimaryPath, PathWeight and OptimizedPath values for this path + // + if (devInfo->DesiredState != DSM_DEV_UNDETERMINED) { + + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + dsmPathKey, + DSM_PRIMARY_PATH, + REG_DWORD, + &(dsmPath->PrimaryPath), + sizeof(ULONG)); + + if (NT_SUCCESS(status)) { + + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + dsmPathKey, + DSM_OPTIMIZED_PATH, + REG_DWORD, + &(dsmPath->OptimizedPath), + sizeof(ULONG)); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to save OptimizedPath. Status %x.\n", + LoadBalanceSettings->RegistryKeyName, + status)); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to save Primary Path. Status %x.\n", + LoadBalanceSettings->RegistryKeyName, + status)); + } + } + + if (NT_SUCCESS(status)) { + + if (LoadBalanceSettings->LoadBalancePolicy == DSM_LB_WEIGHTED_PATHS) { + + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + dsmPathKey, + DSM_PATH_WEIGHT, + REG_DWORD, + &(dsmPath->PathWeight), + sizeof(ULONG)); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to save PathWeight. Status %x.\n", + LoadBalanceSettings->RegistryKeyName, + status)); + } + } + } + + ZwClose(dsmPathKey); + dsmPathKey = NULL; + } else { + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to open DSM Path key. Status %x.\n", + LoadBalanceSettings->RegistryKeyName, + status)); + } + + if (!NT_SUCCESS(status)) { + break; + } + } + + if (NT_SUCCESS(status)) { + + // + // Save the new Load Balance Policy value, + // + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_LOAD_BALANCE_POLICY, + REG_DWORD, + &(LoadBalanceSettings->LoadBalancePolicy), + sizeof(ULONG)); + if (NT_SUCCESS(status)) { + + UCHAR explicitlySet = TRUE; + + // + // Write out that the policy has been explicitly set + // + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_POLICY_EXPLICITLY_SET, + REG_BINARY, + &explicitlySet, + sizeof(UCHAR)); + + if (NT_SUCCESS(status)) { + + // + // If FailOver-Only policy, set the PreferredPath, if specified + // + if (preferredPath) { + + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_PREFERRED_PATH, + REG_BINARY, + &(preferredPath->DsmPathId), + sizeof(ULONGLONG)); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to save LB Settings (ES).\n", + LoadBalanceSettings->RegistryKeyName)); + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Failed to save LB Settings (LBP).\n", + LoadBalanceSettings->RegistryKeyName)); + } + } + } + +__Exit_DsmpPersistLBSettings: + + if (dsmPathKey) { + ZwClose(dsmPathKey); + } + + if (deviceKey) { + ZwClose(deviceKey); + } + + if (lbSettingsKey) { + ZwClose(lbSettingsKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpPersistLBSettings (DevName %ws): Exiting function with status %x.\n", + LoadBalanceSettings->RegistryKeyName, + status)); + + return status; +} + + +NTSTATUS +DsmpSetDeviceALUAState( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_ IN DSM_DEVICE_STATE DevState + ) +/*++ + +Routine Description: + + Helper routine to build the STPG info and send it down to modify the passed in + devInfo's state. + +Arguments: + + DsmContext - DSM context. + DeviceInfo - DevInfo whose state needs to be changed. + DevState - New state to be set. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength; + PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR tpgDescriptor = NULL; + NTSTATUS status; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpSetDeviceALUAState (DevInfo %p): Entering function.\n", + DeviceInfo)); + + // + // Send down SetTPG to set the appropriate access state + // (The TPG block will contain the header and a SetTPG descriptor). + // + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); + + targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, + targetPortGroupsInfoLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo) { + + tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)(targetPortGroupsInfo + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE); + tpgDescriptor->AsymmetricAccessState = DevState; + REVERSE_BYTES_SHORT(&tpgDescriptor->TPG_Identifier, &DeviceInfo->TargetPortGroup->Identifier); + + status = DsmpSetTargetPortGroups(DeviceInfo->TargetObject, + targetPortGroupsInfo, + targetPortGroupsInfoLength); + + if (NT_SUCCESS(status)) { + + // + // An explicit transition may cause changes to some other TPGs. + // So we need to query for the states of all the TPGs and update + // our internal list and its elements. + // + status = DsmpGetDeviceALUAState(DsmContext, + DeviceInfo, + NULL); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetDeviceALUAState (DevInfo %p): Failed to SetTPG with %x.\n", + DeviceInfo, + status)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpSetDeviceALUAState (DevInfo %p): Failed to allocate TPG.\n", + DeviceInfo)); + status = STATUS_INSUFFICIENT_RESOURCES; + } + + if (targetPortGroupsInfo) { + DsmpFreePool(targetPortGroupsInfo); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpSetDeviceALUAState (DevInfo %p): Exiting function with status %x\n", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpAdjustDeviceStatesALUA( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_opt_ IN PDSM_DEVICE_INFO PreferredActiveDeviceInfo, + _In_ IN ULONG SpecialHandlingFlag + ) +/*++ + +Routine Description: + + Helper routine to build the adjust every device state in the group taking + the following into consideration: + 1. PreferredActiveDeviceInfo + 2. DeviceInfo's TPG state + 3. Preferred Path + 4. LB Policy + +Arguments: + + Group - Pseudo-LUN whose path states need to be adjusted. + PreferredActiveDeviceInfo - DevInfo whose state needs to preferrably made + A/O, if possible. This parameter is optional. + + SpecialHandlingFlag - Flags to indicate any special handling requirement + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + ULONG index; + PDSM_DEVICE_INFO deviceInfo; + PDSM_DEVICE_INFO activeDevice = NULL; + DSM_DEVICE_STATE devState; + NTSTATUS status = STATUS_SUCCESS; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): Entering function with preferred active devInfo %p.\n", + Group, + PreferredActiveDeviceInfo)); + + // + // Ensure that: + // 1. All devices match their ALUA state. + // 2. For RRWS, if a device's desired state is non-A/O, but ALUA state is A/O, mask it. + // 3. For FOO there must be only one A/O device. Preferably the preferred path. + // + for (index = 0; index < DSM_MAX_PATHS; index++) { + + deviceInfo = Group->DeviceList[index]; + + if (deviceInfo) { + + devState = deviceInfo->State; + + if (!DsmpIsDeviceFailedState(deviceInfo->State) && + DsmpIsDeviceInitialized(deviceInfo) && + DsmpIsDeviceUsable(deviceInfo) && + DsmpIsDeviceUsablePR(deviceInfo)) { + + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = deviceInfo->ALUAState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (its ALUA state).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + + if (deviceInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { + + // + // In FOO and RRWS, we need to mask states. + // + switch (Group->LoadBalanceType) { + case DSM_LB_FAILOVER: { + + // + // Cache the first available devInfo that is in A/O + // + if (!activeDevice) { + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p choosen as the active device.\n", + Group, + activeDevice)); + + break; + } + + // + // Check if this deviceInfo is the preferred path. If yes, + // mask the active device's state and make this the new + // active device. + // + if (Group->PreferredPath == (ULONGLONG)((ULONG_PTR)deviceInfo->FailGroup->PathId)) { + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || + activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): Previous active devInfo %p transitioning from %u to %u.\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active device (preferred path).\n", + Group, + activeDevice)); + + break; + } + + // + // If active device's desired state is not A/O but this + // deviceInfo's is, then mask the active device's state + // and make this one the new active device. + // + if (activeDevice->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + activeDevice->DesiredState != DSM_DEV_UNDETERMINED) { + + // + // The exception though is if the current active device + // is the preferred path + // + if (Group->PreferredPath == (ULONGLONG)((ULONG_PTR)activeDevice->FailGroup->PathId)) { + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = (deviceInfo->DesiredState == DSM_DEV_UNDETERMINED || + deviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : deviceInfo->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (active DI is PrefPath).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + } else { + + // + // If this is the devInfo that is preferred to be A/O, make it such + // + if (PreferredActiveDeviceInfo && + PreferredActiveDeviceInfo == deviceInfo) { + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (found a preferred active DI).\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active DI (preferred).\n", + Group, + activeDevice)); + } else { + + // + // Check if this devInfo desires to be in A/O, since the currently + // active one doesn't want to be. + // + if (deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + deviceInfo->DesiredState != DSM_DEV_UNDETERMINED) { + + // + // This deviceInfo's desire is also not to be in A/O, + // so just leave the current one active. + // + if (devState == DSM_DEV_ACTIVE_OPTIMIZED) { + + // + // Exception is if we're processing the device whose state before + // RTPG was sent was already A/O, it is best to leave this device + // in A/O state. + // + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || + activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u. Found a DI that was previously active.\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p now the new active device (previously A/O).\n", + Group, + activeDevice)); + } else { + + // + // This device wasn't in A/O state before, so just leave + // the currently selected active device as is. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = deviceInfo->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (active device already exists).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + } + } else { + + // + // Current devInfo wants (or doesn't) mind being in + // A/O, whereas the current active device doesn't, so + // mask the active device and make this devInfo the + // active device. + // + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u. Current DI prefers being A/O.\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active device (desired state).\n", + Group, + activeDevice)); + } + } + } + } else { + + // + // The single overriding factor is always the preferred path. + // Everything else is secondary, so first check if the currently + // active device can even be overridden by another one. + // + if (Group->PreferredPath != (ULONGLONG)((ULONG_PTR)activeDevice->FailGroup->PathId)) { + + // + // It can't be overridden, so we're done. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = (deviceInfo->DesiredState == DSM_DEV_UNDETERMINED || + deviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : deviceInfo->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (current active DI is PrefPath).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + } else { + + // + // Active device's desired state is A/O but it isn't the preferred + // path. Check if this devInfo is preferred as A/O. + // + if (PreferredActiveDeviceInfo && + PreferredActiveDeviceInfo == deviceInfo) { + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || + activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u. New DI is preferred active.\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is now the new active device (this DI is preferred active).\n", + Group, + activeDevice)); + } else { + + // + // Active device's desired state is A/O but it isn't the + // preferred path. Check if this devInfo's desired state + // is also A/O. If yes, we'll need to make certain decisions. + // + if (deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + deviceInfo->DesiredState != DSM_DEV_UNDETERMINED) { + + // + // Since this device doesn't desire to be in + // A/O and we already have an active device, just + // mask its state. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = deviceInfo->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (prefers being in non-A/O).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + } else { + + // + // Active device is in A/O and this device desires to be in + // A/O too. Make this the new active device only if its state + // before the RTPG was already A/O. + // + if (devState == DSM_DEV_ACTIVE_OPTIMIZED) { + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = (activeDevice->DesiredState == DSM_DEV_UNDETERMINED || + activeDevice->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (new DI was already in A/O previously).\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p is new active device (since it was in A/O previously too).\n", + Group, + activeDevice)); + } else { + + // + // Just leave the currently active one alone. + // + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = (deviceInfo->DesiredState == DSM_DEV_UNDETERMINED || + deviceInfo->DesiredState == DSM_DEV_ACTIVE_OPTIMIZED) ? DSM_DEV_ACTIVE_UNOPTIMIZED : deviceInfo->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (leave current active DI alone).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + } + } + } + } + } + break; + } + + case DSM_LB_ROUND_ROBIN_WITH_SUBSET: { + + // + // At least one path needs to be in A/O state, so + // cache the first available devInfo that is in A/O + // + if (!activeDevice) { + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): We have atleast one A/O DevInfo %p.\n", + Group, + activeDevice)); + + break; + } + + // + // Check if this device is preferred to be in A/O + // + if (PreferredActiveDeviceInfo && + PreferredActiveDeviceInfo == deviceInfo) { + + // + // If the currently active device, doesn't desire to be in + // A/O state, mask its state. + // + if (activeDevice->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + activeDevice->DesiredState != DSM_DEV_UNDETERMINED) { + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (desired state non-A/O).\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + } + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p now the new active device (preferred active DI).\n", + Group, + activeDevice)); + } else { + + // + // If this device's desired state is specified and not A/O, + // mask its path state. + // + if (deviceInfo->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + deviceInfo->DesiredState != DSM_DEV_UNDETERMINED) { + + deviceInfo->PreviousState = deviceInfo->State; + deviceInfo->State = deviceInfo->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (desires to be in non-A/O).\n", + Group, + deviceInfo, + deviceInfo->PreviousState, + deviceInfo->State)); + } else { + + // + // Since this devInfo desires to be in A/O, we are assured + // of at least one path in A/O. So check to see if the + // currently active device doesn't desire to be in A/O. + // + if (activeDevice->DesiredState != DSM_DEV_ACTIVE_OPTIMIZED && + activeDevice->DesiredState != DSM_DEV_UNDETERMINED) { + + activeDevice->PreviousState = activeDevice->State; + activeDevice->State = activeDevice->DesiredState; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p transitioning from %u to %u (new DI desires to be in A/O).\n", + Group, + activeDevice, + activeDevice->PreviousState, + activeDevice->State)); + + activeDevice = deviceInfo; + + TracePrint((TRACE_LEVEL_INFORMATION, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): DevInfo %p now the new active DI (desires to be in A/O).\n", + Group, + activeDevice)); + } + } + } + + break; + } + + default: { + + // + // For RR, LQD and WP, paths must be in the same + // state as their corresponding TPG. Preferably + // all should be A/O. + // + if (deviceInfo->State != DSM_DEV_ACTIVE_OPTIMIZED) { + DSM_ASSERT(deviceInfo->State == deviceInfo->ALUAState); + } + + break; + } + } + } + } + } + } + + // + // There may have been a change to the device states. + // DsmpGetPath() will pick these changes for RR, RRWS and LQD. + // However, it won't for FOO and WP, so update PTBU if needed. + // + if (Group->LoadBalanceType == DSM_LB_FAILOVER || + Group->LoadBalanceType == DSM_LB_WEIGHTED_PATHS) { + + deviceInfo = DsmpGetActivePathToBeUsed(Group, FALSE, SpecialHandlingFlag); + + if (deviceInfo) { + + InterlockedExchangePointer(&(Group->PathToBeUsed), deviceInfo->FailGroup); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpAdjustDeviceStatesALUA (Group %p): Exiting function with status %x\n", + Group, + status)); + + return status; +} + + +PDSM_WORKITEM +DsmpAllocateWorkItem( + _In_ IN PDEVICE_OBJECT DeviceObject, + _In_ IN PVOID Context + ) +/*++ + +Routine Description: + + Allocates a work item to handle reservation failover. + +Arguments: + + DeviceObject - Target device. + Context - Workitem context + +Return Value: + + Allocated workitem or NULL (if low memory). + +--*/ +{ + PDSM_WORKITEM dsmWorkItem = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpAllocateWorkItem (DevObj %p): Entering function.\n", + DeviceObject)); + + dsmWorkItem = DsmpAllocatePool(NonPagedPoolNx, + sizeof(DSM_WORKITEM), + DSM_TAG_WORKITEM); + if (dsmWorkItem != NULL) { + + dsmWorkItem->WorkItem = IoAllocateWorkItem(DeviceObject); + if (dsmWorkItem->WorkItem != NULL) { + + dsmWorkItem->Context = Context; + } else { + + DsmpFreePool(dsmWorkItem); + dsmWorkItem = NULL; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpAllocateWorkItem (DevObj %p): Exiting function. dsmWorkItem %p.\n", + DeviceObject, + dsmWorkItem)); + + return dsmWorkItem; +} + + +VOID +DsmpFreeWorkItem( + _In_ IN PDSM_WORKITEM DsmWorkItem + ) +{ + PVOID temp = DsmWorkItem; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpFreeWorkItem (WorkItem %p): Entering function.\n", + DsmWorkItem)); + + if (DsmWorkItem != NULL) { + + if (DsmWorkItem->WorkItem != NULL) { + IoFreeWorkItem(DsmWorkItem->WorkItem); + } + + DsmpFreePool(DsmWorkItem); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_IOCTL, + "DsmpFreeWorkItem (WorkItem %p): Exiting function.\n", + temp)); + + return; +} + + +VOID +DsmpFreeZombieGroupList( + _In_ IN PDSM_FAILOVER_GROUP FailGroup + ) +{ + PLIST_ENTRY zombieEntry = NULL; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFreeZombieGroupList (FailGroup %p): Entering function.\n", + FailGroup)); + + while (!IsListEmpty(&FailGroup->ZombieGroupList)) { + + zombieEntry = RemoveHeadList(&FailGroup->ZombieGroupList); + + if (zombieEntry) { + + DsmpFreePool(zombieEntry); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpFreeZombieGroupList (FailGroup %p): Exiting function.\n", + FailGroup)); +} + + +NTSTATUS +DsmpGetDeviceALUAState( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_DEVICE_INFO DeviceInfo, + _In_opt_ IN PDSM_DEVICE_STATE DevState + ) +/*++ + +Routine Description: + + Helper routine to build the RTPG info and send it down to retrieve the + devInfo's current state. + +Arguments: + + DsmContext - DSM context. + DeviceInfo - DevInfo whose state needs to be changed. + DevState - Current state of passed in DeviceInfo. + +Return Value: + + STATUS_SUCCESS or appropriate failure code. + +--*/ +{ + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength = 0; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup = NULL; + KIRQL irql; + NTSTATUS status; + ULONG index; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetDeviceALUAState (DevInfo %p): Entering function.\n", + DeviceInfo)); + + status = DsmpReportTargetPortGroups(DeviceInfo->TargetObject, + &targetPortGroupsInfo, + &targetPortGroupsInfoLength); + + + if (NT_SUCCESS(status) && targetPortGroupsInfo != NULL) { + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + status = DsmpParseTargetPortGroupsInformation(DsmContext, + DeviceInfo->Group, + targetPortGroupsInfo, + targetPortGroupsInfoLength); + + for (index = 0; index < DSM_MAX_PATHS; index++) { + + targetPortGroup = DeviceInfo->Group->TargetPortGroupList[index]; + + if (targetPortGroup) { + + DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + if (DevState) { + + *DevState = DeviceInfo->State; + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_GENERAL, + "DsmpGetDeviceALUAState (DevInfo %p): ReportTPG failed with %x.\n", + DeviceInfo, + status)); + } + + if (targetPortGroupsInfo) { + + DsmpFreePool(targetPortGroupsInfo); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_GENERAL, + "DsmpGetDeviceALUAState (DevInfo %p): Exiting function with status %x\n", + DeviceInfo, + status)); + + return status; +} + + +NTSTATUS +DsmpRegCopyTree( + _In_ IN HANDLE SourceKey, + _In_ IN HANDLE DestKey + ) +/*++ + +Routine Description: + + Copies a reg subtree from source key to destination key. + This routine will first copy over all the key's values, and then + copy the subkeys, each time recursively handling the subkey's + values and its subtree. + +Arguments: + + SourceKey - Handle to the root of the subtree to copy over. + DestKey - Handle to the root of the new tree. + +Return Value: + + STATUS_SUCCESS upon successfully coping over the tree. + Appropriate NT error code in case of failure. + +--*/ +{ + ULONG numValues = 0; + ULONG numSubKeys = 0; + ULONG lengthOfValueName = 0; + ULONG lengthOfValueData = 0; + ULONG lengthOfKeyName = 0; + LPWSTR valueBuf = NULL; + BYTE *valueDataBuf = NULL; + ULONG valueDataType; + ULONG titleIndex; + HANDLE srcSubKey = NULL; + HANDLE destSubKey = NULL; + LPWSTR subKey = NULL; + NTSTATUS status; + PKEY_FULL_INFORMATION keyFullInfo = NULL; + ULONG length = sizeof(KEY_FULL_INFORMATION); + ULONG index = 0; + PKEY_VALUE_FULL_INFORMATION keyValueFullInfo = NULL; + PKEY_BASIC_INFORMATION keyBasicInfo = NULL; + OBJECT_ATTRIBUTES objectAttributes; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Entering function.\n", + SourceKey)); + + if (!SourceKey || !DestKey) { + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpRegCopyTree; + } + + // + // Query the source key for information about number of subkeys, number of values, etc. + // + do { + if (keyFullInfo) { + + DsmpFreePool(keyFullInfo); + } + + keyFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); + + if (!keyFullInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for key full info.\n", + SourceKey)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegCopyTree; + } + + status = ZwQueryKey(SourceKey, + KeyFullInformation, + keyFullInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to query key. Status %x.\n", + SourceKey, + status)); + + goto __Exit_DsmpRegCopyTree; + } + + numSubKeys = keyFullInfo->SubKeys; + numValues = keyFullInfo->Values; + lengthOfKeyName = keyFullInfo->MaxNameLen + sizeof(WCHAR); + lengthOfValueName = keyFullInfo->MaxValueNameLen + sizeof(WCHAR); + lengthOfValueData = keyFullInfo->MaxValueDataLen + sizeof(WCHAR); + + // + // Allocate a buffer for the name of the value + // + valueBuf = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + lengthOfValueName, + DSM_TAG_REG_KEY_RELATED); + if (!valueBuf) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for value name.\n", + SourceKey)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegCopyTree; + } + + // + // Allocate a buffer for the value data + // + valueDataBuf = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + lengthOfValueData, + DSM_TAG_REG_KEY_RELATED); + + if (!valueDataBuf) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for value's data.\n", + SourceKey)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegCopyTree; + } + + // + // First enumerate all of the values + // + status = STATUS_SUCCESS; + for (index = 0; index < numValues && NT_SUCCESS(status); index++) { + + UNICODE_STRING valueName; + + length = sizeof(KEY_VALUE_FULL_INFORMATION); + + do { + + if (keyValueFullInfo) { + + DsmpFreePool(keyValueFullInfo); + } + + keyValueFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); + + if (!keyValueFullInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for value full info.\n", + SourceKey)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegCopyTree; + } + + // + // Get the information of the index'th value + // + status = ZwEnumerateValueKey(SourceKey, + index, + KeyValueFullInformation, + keyValueFullInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to enumerate key's value information. Status %x.\n", + SourceKey, + status)); + + goto __Exit_DsmpRegCopyTree; + } + + // + // Capture the data type, data value, and value name. + // + titleIndex = keyValueFullInfo->TitleIndex; + valueDataType = keyValueFullInfo->Type; + + RtlZeroMemory(valueDataBuf, lengthOfValueData); + RtlCopyMemory(valueDataBuf, + (PUCHAR)keyValueFullInfo + keyValueFullInfo->DataOffset, + keyValueFullInfo->DataLength); + + RtlZeroMemory(valueBuf, lengthOfValueName); + RtlStringCbCopyNW(valueBuf, lengthOfValueName, keyValueFullInfo->Name, keyValueFullInfo->NameLength); + RtlInitUnicodeString(&valueName, valueBuf); + + // + // Copy the value over to the new key + // + status = ZwSetValueKey(DestKey, + &valueName, + titleIndex, + valueDataType, + valueDataBuf, + keyValueFullInfo->DataLength); + } + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate set new key's value information. Status %x.\n", + SourceKey, + status)); + + goto __Exit_DsmpRegCopyTree; + } + + // + // Allocate buffer for subkey name + // + subKey = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + lengthOfKeyName, + DSM_TAG_REG_KEY_RELATED); + + if(!subKey) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for sub key name.\n", + SourceKey)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegCopyTree; + } + + // + // Now Enumerate all of the subkeys + // + length = sizeof(KEY_BASIC_INFORMATION); + for(index = 0; index < numSubKeys && NT_SUCCESS(status); index++) { + + UNICODE_STRING subKeyName; + + do { + if (keyBasicInfo) { + + DsmpFreePool(keyBasicInfo); + } + + keyBasicInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + length, + DSM_TAG_REG_KEY_RELATED); + + if (!keyBasicInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to allocate resources for key basic info.\n", + SourceKey)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegCopyTree; + } + + // + // Enumerate the index'th subkey + // + status = ZwEnumerateKey(SourceKey, + index, + KeyBasicInformation, + keyBasicInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to enumerate sub key's info. Status %x.\n", + SourceKey, + status)); + + goto __Exit_DsmpRegCopyTree; + } + + RtlZeroMemory(subKey, lengthOfKeyName); + RtlStringCbCopyNW(subKey, lengthOfKeyName, keyBasicInfo->Name, keyBasicInfo->NameLength); + RtlInitUnicodeString(&subKeyName, subKey); + + // + // Open a handle to the the subkey on the old device. + // + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + SourceKey, + (PSECURITY_DESCRIPTOR) NULL); + + if (srcSubKey) { + ZwClose(srcSubKey); + srcSubKey = NULL; + } + + status = ZwOpenKey(&srcSubKey, + KEY_ALL_ACCESS, + &objectAttributes); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to open reg key %ws. Status %x.\n", + SourceKey, + subKey, + status)); + + goto __Exit_DsmpRegCopyTree; + } + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + DestKey, + (PSECURITY_DESCRIPTOR) NULL); + + if (destSubKey) { + ZwClose(destSubKey); + destSubKey = NULL; + } + + // + // Create the subkey on the new device. + // + status = ZwCreateKey(&destSubKey, + KEY_ALL_ACCESS, + &objectAttributes, + 0, + NULL, + REG_OPTION_NON_VOLATILE, + NULL); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Failed to create reg key %ws. Status %x.\n", + SourceKey, + subKey, + status)); + + goto __Exit_DsmpRegCopyTree; + } + + // + // That's it. We've got everything we need (ie. handles to the two new + // subtrees' roots. Call recursively. + // + status = DsmpRegCopyTree(srcSubKey, destSubKey); + } + +__Exit_DsmpRegCopyTree: + + if (keyFullInfo) { + DsmpFreePool(keyFullInfo); + } + + if (valueBuf) { + DsmpFreePool(valueBuf); + } + + if (valueDataBuf) { + DsmpFreePool(valueDataBuf); + } + + if (keyValueFullInfo) { + DsmpFreePool(keyValueFullInfo); + } + + if (subKey) { + DsmpFreePool(subKey); + } + + if (keyBasicInfo) { + DsmpFreePool(keyBasicInfo); + } + + if (srcSubKey) { + ZwClose(srcSubKey); + } + + if (destSubKey) { + ZwClose(destSubKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRegCopyTree (SrcKey %p): Exiting function with status %x.\n", + SourceKey, + status)); + + return status; +} + + +NTSTATUS +DsmpRegDeleteTree( + _In_ IN HANDLE KeyRoot + ) +/*++ +Routine Description: + + This routine is a recursive worker that enumerates the subkeys + of a given key, applies itself to each one, then deletes itself. + +Arguments: + + KeyRoot - Supplies a handle to the root of subtree to be deleted. + +Return Value: + + STATUS_SUCCESS - upon successful deletion of subtree. + Appropriate NT error code upon failure. + +--*/ +{ + NTSTATUS status; + PKEY_FULL_INFORMATION keyFullInfo = NULL; + ULONG length = sizeof(KEY_FULL_INFORMATION); + ULONG numSubKeys; + ULONG lengthOfKeyName; + LPWSTR subKey = NULL; + PKEY_BASIC_INFORMATION keyBasicInfo = NULL; + ULONG index = 0; + HANDLE srcSubKey = NULL; + OBJECT_ATTRIBUTES objectAttributes; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Entering function.\n", + KeyRoot)); + + if (!KeyRoot) { + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpRegDeleteTree; + } + + // + // Query the source key for information about number of subkeys and max + // length needed for subkey name. + // + do { + if (keyFullInfo) { + + DsmpFreePool(keyFullInfo); + } + + keyFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); + + if (!keyFullInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Failed to allocate resources for key full info.\n", + KeyRoot)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegDeleteTree; + } + + status = ZwQueryKey(KeyRoot, + KeyFullInformation, + keyFullInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Failed to query key. Status %x.\n", + KeyRoot, + status)); + + goto __Exit_DsmpRegDeleteTree; + } + + numSubKeys = keyFullInfo->SubKeys; + lengthOfKeyName = keyFullInfo->MaxNameLen + sizeof(WCHAR); + + if (numSubKeys) { + + // + // Allocate buffer for subkey name + // + subKey = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + lengthOfKeyName, + DSM_TAG_REG_KEY_RELATED); + + if(!subKey) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Failed to allocate resources for sub key.\n", + KeyRoot)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegDeleteTree; + } + + // + // Now Enumerate all of the subkeys + // + index = numSubKeys - 1; + length = sizeof(KEY_BASIC_INFORMATION); + do { + + UNICODE_STRING subKeyName; + + do { + if (keyBasicInfo) { + + DsmpFreePool(keyBasicInfo); + } + + keyBasicInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + length, + DSM_TAG_REG_KEY_RELATED); + + if (!keyBasicInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Failed to allocate resources for key basic info.\n", + KeyRoot)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpRegDeleteTree; + } + + // + // Enumerate the index'th subkey + // + status = ZwEnumerateKey(KeyRoot, + index, + KeyBasicInformation, + keyBasicInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (NT_SUCCESS(status)) { + + RtlZeroMemory(subKey, lengthOfKeyName); + RtlStringCbCopyNW(subKey, lengthOfKeyName, keyBasicInfo->Name, keyBasicInfo->NameLength); + RtlInitUnicodeString(&subKeyName, subKey); + + // + // Open a handle to the the current root's subkey. + // + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + KeyRoot, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(&srcSubKey, + KEY_ALL_ACCESS, + &objectAttributes); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Failed to open key %ws. Status %x.\n", + KeyRoot, + subKey, + status)); + + goto __Exit_DsmpRegDeleteTree; + } + + // + // Delete this key's subtree (recursively). + // + status = DsmpRegDeleteTree(srcSubKey); + + ZwClose(srcSubKey); + srcSubKey = NULL; + } + + index--; + + } while (status != STATUS_NO_MORE_ENTRIES && (LONG)index >= 0); + + if (status == STATUS_NO_MORE_ENTRIES) { + + status = STATUS_SUCCESS; + } + } + + ZwDeleteKey(KeyRoot); + +__Exit_DsmpRegDeleteTree: + + if (srcSubKey) { + ZwClose(srcSubKey); + } + + if (keyFullInfo) { + DsmpFreePool(keyFullInfo); + } + + if (subKey) { + DsmpFreePool(subKey); + } + + if (keyBasicInfo) { + DsmpFreePool(keyBasicInfo); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpRegDeleteTree (SrcKey %p): Exiting function with status %x.\n", + KeyRoot, + status)); + + return status; +} + + +#if defined (_WIN64) +VOID +DsmpPassThroughPathTranslate32To64( + _In_ IN PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32, + _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64 + ) +/*++ + +Routine Description: + + On WIN64, the SCSI_PASS_THROUGH field of the MPIO_PASS_THROUGH_PATH structure + sent down by a 32-bit application must be marshaled into a 64-bit version + of the structure. This function performs that marshaling. + +Arguments: + + MpioPassThroughPath32 - Supplies a pointer to a 32-bit MPIO_PASS_THROUGH_PATH + struct. + + MpioPassThroughPath64 - Supplies a pointer to a 64-bit MPIO_PASS_THROUGH_PATH + structure, into which we'll copy the marshaled + 32-bit data. + +Return Value: + + None. + +--*/ +{ + // + // Copy the first set of fields out of the 32-bit structure. These + // fields all line up between the 32 & 64 bit versions. + // + // Note that we do NOT adjust the length in the SrbControl. This is to + // allow the calling routine to compare the length of the actual + // control area against the offsets embedded within. If we adjusted the + // length then requests with the sense area backed against the control + // area would be rejected because the 64-bit control area is 4 bytes + // longer. + // + RtlCopyMemory(MpioPassThroughPath64, + MpioPassThroughPath32, + FIELD_OFFSET(SCSI_PASS_THROUGH, DataBufferOffset)); + + // + // Copy over the CDB. + // + RtlCopyMemory(MpioPassThroughPath64->PassThrough.Cdb, + MpioPassThroughPath32->PassThrough.Cdb, + 16 * sizeof(UCHAR) + ); + + // + // Copy over the rest of the fields of the structure. + // + MpioPassThroughPath64->Version = MpioPassThroughPath32->Version; + MpioPassThroughPath64->Length = MpioPassThroughPath32->Length; + MpioPassThroughPath64->Flags = MpioPassThroughPath32->Flags; + MpioPassThroughPath64->PortNumber = MpioPassThroughPath32->PortNumber; + MpioPassThroughPath64->MpioPathId = MpioPassThroughPath32->MpioPathId; + + // + // Copy the fields that follow the ULONG_PTR. + // + MpioPassThroughPath64->PassThrough.DataBufferOffset = (ULONG_PTR)MpioPassThroughPath32->PassThrough.DataBufferOffset; + MpioPassThroughPath64->PassThrough.SenseInfoOffset = MpioPassThroughPath32->PassThrough.SenseInfoOffset; + + return; +} + + +VOID +DsmpPassThroughPathTranslate64To32( + _In_ IN PMPIO_PASS_THROUGH_PATH MpioPassThroughPath64, + _Inout_ IN OUT PMPIO_PASS_THROUGH_PATH32 MpioPassThroughPath32 + ) +/*++ + +Routine Description: + + On WIN64, the SCSI_PASS_THROUGH field of MPIO_PASS_THROUGH_PATH structure + sent down by a 32-bit application must be marshaled into a 64-bit version + of the structure. This function marshals a 64-bit version of the structure + back into a 32-bit version. + +Arguments: + + MpioPassThroughPath64 - Supplies a pointer to a 64-bit MPIO_PASS_THROUGH_PATH + struct. + + MpioPassThroughPath32 - Supplies the address of a pointer to a 32-bit + MPIO_PASS_THROUGH_PATH structure, into which we'll + copy the marshaled 64-bit data. + +Return Value: + + None. + +--*/ +{ + // + // Copy back the fields through the data offsets. + // + RtlCopyMemory(MpioPassThroughPath32, + MpioPassThroughPath64, + FIELD_OFFSET(SCSI_PASS_THROUGH, DataBufferOffset)); + + + // + // Copy over the CDB. + // + RtlCopyMemory(MpioPassThroughPath32->PassThrough.Cdb, + MpioPassThroughPath64->PassThrough.Cdb, + 16 * sizeof(UCHAR) + ); + + // + // Copy over the rest of the fields of the structure. + // + MpioPassThroughPath32->Version = MpioPassThroughPath64->Version; + MpioPassThroughPath32->Length = MpioPassThroughPath64->Length; + MpioPassThroughPath32->Flags = MpioPassThroughPath64->Flags; + MpioPassThroughPath32->PortNumber = MpioPassThroughPath64->PortNumber; + MpioPassThroughPath32->MpioPathId = MpioPassThroughPath64->MpioPathId; + + return; +} +#endif + + +NTSTATUS +DsmpGetMaxPRRetryTime( + _In_ IN PDSM_CONTEXT Context, + _Out_ OUT PULONG RetryTime + ) +/*++ + +Routine Description: + + This routine is used to get the max time period for which a PR request failing + with a retry-able unit attention should be retried before failing back to MSCS. + The value is determined by querying the value found at + "msdsm\Parameters\DsmMaximumStateTransitionTime" + +Arguments: + + Context - The DSM Context value. + RetryTime - The output parameter that will receive the value to be used. + +Return Value: + + Status of the RtlQueryRegistryValues call. + +--*/ +{ + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + WCHAR registryKeyName[56] = {0}; + NTSTATUS status; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetMaxPRRetryTime (DsmCtxt %p): Entering function.\n", + Context)); + + NT_ASSERT(RetryTime); + *RetryTime = DSM_MAX_PR_UNIT_ATTENTION_RETRY_TIME; + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + // + // Build the key value name that we want as the base of the query. + // + RtlStringCbPrintfW(registryKeyName, + sizeof(registryKeyName), + DSM_PARAMETER_PATH_W); + + // + // The query table has two entries. One for the state transition time and + // the second which is the 'NULL' terminator. + // + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_MAX_STATE_TRANSITION_TIME_VALUE_NAME; + queryTable[0].EntryContext = RetryTime; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + registryKeyName, + queryTable, + registryKeyName, + NULL); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpGetMaxPRRetryTime (DsmCtxt %p): Exiting function with status %x.\n", + Context, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryCacheInformationFromRegistry( + _In_ IN PDSM_CONTEXT DsmContext, + _Out_ OUT PBOOLEAN UseCacheForLeastBlocks, + _Out_ OUT PULONGLONG CacheSizeForLeastBlocks + ) +/*++ + +Routine Description: + + This routine is used to get the information about whether sequential IO + should use the same path when employing Least Blocks policy. + It also queries the size of cache set by the administrator. + The value is determined by querying the value found at + "msdsm\Parameters\DsmUseCacheForLeastBlocks" and + "msdsm\Parameters\DsmCacheSizeForLeastBlocks" + +Arguments: + + Context - The DSM Context value. + UseCacheForLeastBlocks - Returns the flag that indicates whether or not to + use same path for sequential IO when LB policy + is Least Blocks. + CacheSizeForLeastBlocks - Returns the size of the cache (in bytes) set by + the Admin to indicate the amount of sequential + data that should be use the same path when LB + policy is Least Blocks. + +Return Value: + + Status of the RtlQueryRegistryValues call. + +--*/ +{ + RTL_QUERY_REGISTRY_TABLE queryTable[2] = {0}; + WCHAR registryKeyName[56] = {0}; + HANDLE parametersKey = NULL; + UNICODE_STRING keyValueName; + NTSTATUS status; + struct _cacheSizeForLeastBlocks { + KEY_VALUE_PARTIAL_INFORMATION KeyValueInfo; + ULONGLONG Data; + } cacheSizeForLeastBlocks; + ULONG length = 0; + BOOLEAN useCacheForLeastBlocksDefault = FALSE; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryCacheInformationFromRegistry (DsmCtxt %p): Entering function.\n", + DsmContext)); + + NT_ASSERT(UseCacheForLeastBlocks); + NT_ASSERT(CacheSizeForLeastBlocks); + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + // + // Build the key value name that we want as the base of the query. + // + RtlStringCbPrintfW(registryKeyName, + sizeof(registryKeyName), + DSM_PARAMETER_PATH_W); + + // + // The query table has two entries. One for whether to use cache, and + // and the second which is the 'NULL' terminator. + // + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_USE_CACHE_FOR_LEAST_BLOCKS; + queryTable[0].EntryContext = UseCacheForLeastBlocks; + queryTable[0].DefaultType = (REG_BINARY << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_BINARY; + queryTable[0].DefaultLength = sizeof(BOOLEAN); + queryTable[0].DefaultData = &useCacheForLeastBlocksDefault; + + status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, + registryKeyName, + queryTable, + registryKeyName, + NULL); + + if (NT_SUCCESS(status)) { + + status = DsmpOpenDsmServicesParametersKey(KEY_QUERY_VALUE, ¶metersKey); + + if (NT_SUCCESS(status)) { + + RtlInitUnicodeString(&keyValueName, DSM_CACHE_SIZE_FOR_LEAST_BLOCKS); + + status = ZwQueryValueKey(parametersKey, + &keyValueName, + KeyValuePartialInformation, + &cacheSizeForLeastBlocks, + sizeof(cacheSizeForLeastBlocks), + &length); + + if (NT_SUCCESS(status)) { + + NT_ASSERT(cacheSizeForLeastBlocks.KeyValueInfo.DataLength == sizeof(ULONGLONG)); + *CacheSizeForLeastBlocks = *((ULONGLONG UNALIGNED *)&(cacheSizeForLeastBlocks.KeyValueInfo.Data)); + } + } + + if (parametersKey) { + ZwClose(parametersKey); + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_PNP, + "DsmpQueryCacheInformationFromRegistry (DsmCtxt %p): Exiting function with status %x.\n", + DsmContext, + status)); + + return status; +} + +BOOLEAN +DsmpConvertSharedSpinLockToExclusive( + _Inout_ _Requires_lock_held_(*_Curr_) PEX_SPIN_LOCK SpinLock + ) +/*++ + +Routine Description: + + This routine is a wrapper around ExTryConvertSharedSpinLockExclusive() that + guarantees the given EX_SPIN_LOCK will be acquired in Exclusive mode once + this function returns. + + It's possible the lock may be released and re-acquired within this function + so the caller should be very careful about the use of this function. + + N.B. The caller MUST have acquired the given lock in Shared mode before + calling this function. + +Arguments: + + SpinLock - The EX_SPIN_LOCK to convert from Shared to Exclusive mode. + +Return Value: + + Status of the ExTryConvertSharedSpinLockExclusive() call. This function + will always return with the lock acquired in Exclusive mode. The FALSE is + returned, then the lock had to be released and re-acquired. + +--*/ +{ + BOOLEAN converted = FALSE; + + converted = (BOOLEAN)ExTryConvertSharedSpinLockExclusive(SpinLock); + + // + // If the conversion attempt failed, then we should release the lock from + // Shared mode and try to pick it back up in Exclusive mode to guarantee + // this function will always return with the lock in Exclusive mode. + // + if (converted == FALSE) { + ExReleaseSpinLockSharedFromDpcLevel(SpinLock); + ExAcquireSpinLockExclusiveAtDpcLevel(SpinLock); + } + + return converted; +} + + diff --git a/tests/projects/windows/driver/wdm/msdsm/wmi.c b/tests/projects/windows/driver/wdm/msdsm/wmi.c new file mode 100644 index 000000000..0ee882192 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/wmi.c @@ -0,0 +1,3822 @@ + +/*++ + +Copyright (C) 2004-2010 Microsoft Corporation + +Module Name: + + wmi.c + +Abstract: + + This driver is the Microsoft Device Specific Module (DSM). + It exports behaviours that mpio.sys will use to determine how to + multipath SPC-3 compliant devices. + + This file contains WMI related functions. + +Environment: + + kernel mode only + +Notes: + +--*/ + + + +#include "precomp.h" +#include "msdsmwmi.h" +#include "msdsmdsm.h" + +#ifdef DEBUG_USE_WPP +#include "wmi.tmh" +#endif + +#pragma warning (disable:4305) + +extern BOOLEAN DoAssert; + +#define USE_BINARY_MOF_RESOURCE + +#define DSM_INVALID_LOAD_BALANCE_POLICY STATUS_INVALID_PARAMETER +#define DSM_UNSUPPORTED_VERSION STATUS_NOT_SUPPORTED + +// +// Max length for each of the DeviceId strings (supported device list) +// NOTE: This must be kept in sync with msdsmdsm.mof +// +#define MSDSM_MAX_DEVICE_ID_LENGTH 31 +#define MSDSM_MAX_DEVICE_ID_SIZE (MSDSM_MAX_DEVICE_ID_LENGTH * sizeof(WCHAR)) + +// +// List of supported DSM-centric guids +// +GUID MSDSM_SUPPORTED_DEVICES_LISTGUID = MSDSM_SUPPORTED_DEVICES_LISTGuid; +GUID MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID = MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGuid; +GUID MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID = MSDSM_DEFAULT_LOAD_BALANCE_POLICYGuid; + +// +// Symbolic names for the DSM-centric guid indexes +// +#define MSDSM_SUPPORTED_DEVICES_LISTGUID_Index 0 +#define MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID_Index 1 +#define MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID_Index 2 + +WMIGUIDREGINFO MSDsmGuidList[] = { + { + &MSDSM_SUPPORTED_DEVICES_LISTGUID, + 1, + 0 + }, + + { + &MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID, + 1, + 0 + }, + + { + &MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID, + 1, + 0 + } +}; + +#define MSDsmGuidCount (sizeof(MSDsmGuidList) / sizeof(WMIGUIDREGINFO)) + +// +// List of supported Device-centric guids +// +GUID DSM_LBOperationsGUID = DSM_LB_OperationsGuid; +GUID DSM_QueryLBPolicyGUID = DSM_QueryLBPolicyGuid; +GUID DSM_QuerySupportedLBPoliciesGUID = DSM_QuerySupportedLBPoliciesGuid; +GUID DSM_QueryDsmUniqueIdGUID = DSM_QueryUniqueIdGuid; +GUID DSM_QueryLBPolicyV2GUID = DSM_QueryLBPolicy_V2Guid; +GUID DSM_QuerySupportedLBPoliciesV2GUID = DSM_QuerySupportedLBPolicies_V2Guid; +GUID MSDSM_DEVICE_PERFGUID = MSDSM_DEVICE_PERFGuid; +GUID MSDSM_WMI_METHODSGUID = MSDSM_WMI_METHODSGuid; + +// +// Symbolic names for the Device-centric guid indexes +// +#define DSM_LBOperationsGUID_Index 0 +#define DSM_QueryLBPolicyGUID_Index 1 +#define DSM_QuerySupportedLBPoliciesGUID_Index 2 +#define DSM_QueryDsmUniqueIdGUID_Index 3 +#define DSM_QueryLBPolicyV2GUID_Index 4 +#define DSM_QuerySupportedLBPoliciesV2GUID_Index 5 +#define MSDSM_DEVICE_PERFGuidIndex 6 +#define MSDSM_WMI_METHODSGuidIndex 7 + +WMIGUIDREGINFO DsmGuidList[] = { + { + &DSM_LBOperationsGUID, + 1, + 0 + }, + + { + &DSM_QueryLBPolicyGUID, + 1, + 0 + }, + + { + &DSM_QuerySupportedLBPoliciesGUID, + 1, + 0 + }, + + { + &DSM_QueryDsmUniqueIdGUID, + 1, + 0 + }, + + { + &DSM_QueryLBPolicyV2GUID, + 1, + 0 + }, + + { + &DSM_QuerySupportedLBPoliciesV2GUID, + 1, + 0 + }, + + { + &MSDSM_DEVICE_PERFGUID, + 1, + 0 + }, + + { + &MSDSM_WMI_METHODSGUID, + 1, + 0 + } +}; + +#define DsmGuidCount (sizeof(DsmGuidList) / sizeof(WMIGUIDREGINFO)) + +VOID +DsmpDsmWmiInitialize( + _In_ IN PDSM_WMILIB_CONTEXT WmiGlobalInfo, + _In_ IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + This routine intializes the DSM-specific WmiGlobalInfo structure that is passed + back to MPIO during DriverEntry. + +Arguments: + + WmiGlobalInfo - WMI information structure to initialize. + RegistryPath - Registry path to the service key for this driver. + +Return Value: + + None + +--*/ +{ + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmpDsmWmiInitialize (RegPath %ws): Entering function.\n", + RegistryPath->Buffer)); + + RtlZeroMemory(WmiGlobalInfo, sizeof(DSM_WMILIB_CONTEXT)); + + // + // Build the mof resource name. This tells wmi via the busdriver, + // where to find the mof data. This is found in the .rc. + // + RtlInitUnicodeString(&WmiGlobalInfo->MofResourceName, L"DsmMofResourceName"); + + // + // This will jam in the entry points and guids for supported WMI + // operations. SetDataBlock, SetDataItem, ExecuteMethod and FunctionControl are + // currently not needed, so leave them set to zero. + // + WmiGlobalInfo->GuidCount = MSDsmGuidCount; + WmiGlobalInfo->GuidList = MSDsmGuidList; + + WmiGlobalInfo->QueryWmiDataBlockEx = DsmGlobalQueryData; + WmiGlobalInfo->SetWmiDataBlockEx = DsmGlobalSetData; + + // + // Allocate a buffer for the reg. path. + // + WmiGlobalInfo->RegistryPath.Buffer = DsmpAllocatePool(NonPagedPoolNx, + RegistryPath->MaximumLength, + DSM_TAG_REG_PATH); + if (WmiGlobalInfo->RegistryPath.Buffer) { + + // + // Set maximum length of the new string and copy it. + // + WmiGlobalInfo->RegistryPath.MaximumLength = RegistryPath->MaximumLength; + + RtlCopyUnicodeString(&WmiGlobalInfo->RegistryPath, RegistryPath); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "DsmpDsmWmiInitialize (RegPath %ws): Failed to allocate memory for Registry path in WmiGlobalInfo.\n", + RegistryPath->Buffer)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmpDsmWmiInitialize (RegPath %ws): Exiting function.\n", + RegistryPath->Buffer)); + + return; +} + + +NTSTATUS +DsmGlobalQueryData( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG InstanceCount, + _Inout_ IN OUT PULONG InstanceLengthArray, + _In_ IN ULONG BufferAvail, + _Out_writes_to_(BufferAvail, *DataLength) OUT PUCHAR Buffer, + _Out_ OUT PULONG DataLength, + ... + ) +/*++ + +Routine Description: + + This is the WMI query entry point for DSM-specific GUIDs. The index into the + GUID array is found and assuming the buffer is large enough, the data will be + copied over. + +Arguments: + + DsmContext - Global DSM Context + DsmIds - Dsm Ids + Irp - The WMI Irp + GuidIndex - Index into the WMIGUIDINFO array + InstanceIndex - Index of the data instance + InstanceCount - Number of instances + InstanceLengthArray - Array of ULONGs that indicate per-instance data lengths. + BufferAvail - Size of the buffer in which data is returned. + Buffer - Buffer in which the data is returned. + DataLength - Storage for the actual data length written. + +Return Value: + + STATUS_BUFFER_TOO_SMALL - If output buffer is not big enough to + to return all the available data. + STATUS_WMI_GUID_NOT_FOUND - If GuidIndex doesn't correspond to an actual entry + in the reginfo array. + STATUS_SUCCESS - On success. + +--*/ +{ + NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; + UNREFERENCED_PARAMETER(DsmContext); + UNREFERENCED_PARAMETER(InstanceLengthArray); + UNREFERENCED_PARAMETER(InstanceCount); + UNREFERENCED_PARAMETER(InstanceIndex); + UNREFERENCED_PARAMETER(Irp); + UNREFERENCED_PARAMETER(DsmIds); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmGlobalQueryData (DsmContext %p): Entering function - GuidIndex %u.\n", + DsmContext, + GuidIndex)); + + // + // Check the GuidIndex - the index into the DsmGuildList array - to see + // whether this is a supported GUID or not. + // + switch(GuidIndex) { + + case MSDSM_SUPPORTED_DEVICES_LISTGUID_Index: { + + *DataLength = BufferAvail; + + status = DsmpQuerySupportedDevicesList(DsmContext, + BufferAvail, + DataLength, + Buffer); + + break; + } + + case MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { + + *DataLength = BufferAvail; + + status = DsmpQueryTargetsDefaultPolicy(DsmContext, + BufferAvail, + DataLength, + Buffer); + + break; + } + + case MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { + + *DataLength = BufferAvail; + + status = DsmpQueryDsmDefaultPolicy(DsmContext, + BufferAvail, + DataLength, + Buffer); + + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalQueryData (DsmContext %p): Unknown GuidIndex %d.\n", + DsmContext, + GuidIndex)); + + *DataLength = 0; + + break; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmGlobalQueryData (DsmContext %p): Exiting function with status 0x%x.\n", + DsmContext, + status)); + + return status; +} + + +NTSTATUS +DsmGlobalSetData( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG BufferAvail, + _In_reads_bytes_(BufferAvail) IN PUCHAR Buffer, + ... + ) +/*++ + +Routine Description: + + This is the WMI set entry point for DSM-specific GUIDs. The index into the + GUID array is found and the contents of the buffer are set to the passed in + instance index. + +Arguments: + + DsmContext - Global DSM Context + DsmIds - Dsm Ids + Irp - The WMI Irp + GuidIndex - Index into the WMIGUIDINFO array + InstanceIndex - Index of the data instance + BufferAvail - Size of the buffer in which data is returned. + Buffer - Buffer in which the data is returned. + +Return Value: + + STATUS_BUFFER_TOO_SMALL - If output buffer is not big enough to + to return all the available data. + STATUS_WMI_GUID_NOT_FOUND - If GuidIndex doesn't correspond to an actual entry + in the reginfo array. + STATUS_SUCCESS - On success. + +--*/ +{ + NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; + ULONG dataLength; + PDSM_CONTEXT dsmContext = (PDSM_CONTEXT)DsmContext; + + UNREFERENCED_PARAMETER(DsmIds); + UNREFERENCED_PARAMETER(Irp); + UNREFERENCED_PARAMETER(InstanceIndex); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): Entering function - GuidIndex %u.\n", + DsmContext, + GuidIndex)); + + switch (GuidIndex) { + + case MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { + + PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY targetsPolicyInfo = (PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY)Buffer; + PMSDSM_TARGET_DEFAULT_POLICY_INFO targetPolicyInfo; + PWSTR vidpidIndex; + DSM_LOAD_BALANCE_TYPE loadBalancePolicy; + ULONGLONG preferredPath; + DWORD index; + NTSTATUS errorStatus = STATUS_SUCCESS; + + // + // Determine the correct buffer size. + // + dataLength = AlignOn8Bytes(FIELD_OFFSET(MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY, TargetDefaultPolicyInfo)); + + if (BufferAvail < dataLength) { + + status = STATUS_BUFFER_TOO_SMALL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Incorrect buffer size. Status %x\n", + DsmContext, + GuidIndex, + status)); + break; + } + + dataLength += targetsPolicyInfo->NumberDevices * sizeof(MSDSM_TARGET_DEFAULT_POLICY_INFO); + + if (BufferAvail < dataLength) { + + status = STATUS_BUFFER_TOO_SMALL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Incorrect buffer size for %u targets. Status %x\n", + DsmContext, + GuidIndex, + targetsPolicyInfo->NumberDevices, + status)); + break; + } + + targetPolicyInfo = targetsPolicyInfo->TargetDefaultPolicyInfo; + + for (index = 0; index < targetsPolicyInfo->NumberDevices; index++, targetPolicyInfo++) { + + size_t stringLength = 0; + + // + // First ensure that these values make sense. The VID/PID should be + // a string of 8+16 chars and the LB policy must be one that MSDSM + // supports. + // + // The WMI string is like a unicode string with the first USHORT + // containing the size. + // + vidpidIndex = targetPolicyInfo->HardwareId; + vidpidIndex++; + + if (!NT_SUCCESS(RtlStringCchLengthW(vidpidIndex, DSM_VENDPROD_ID_LEN + 1, &stringLength)) || (stringLength != DSM_VENDPROD_ID_LEN)) { + + errorStatus = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Ignoring incorrect VID/PID %ws. Status %x\n", + DsmContext, + GuidIndex, + vidpidIndex, + errorStatus)); + continue; + } + + if (targetPolicyInfo->LoadBalancePolicy >= DSM_LB_VENDOR_SPECIFIC) { + + errorStatus = STATUS_INVALID_PARAMETER; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Ignoring policy %u for %ws. Status %x\n", + DsmContext, + GuidIndex, + targetPolicyInfo->LoadBalancePolicy, + vidpidIndex, + errorStatus)); + continue; + } + + loadBalancePolicy = targetPolicyInfo->LoadBalancePolicy; + preferredPath = (ULONGLONG)((ULONG_PTR)targetPolicyInfo->PreferredPath); + + // + // Now update/create the key in the registry with the LB policy info. + // If the LB policy is specified as 0, delete the key. + // + status = DsmpSetVidPidLBPolicyInRegistry(vidpidIndex, loadBalancePolicy, preferredPath); + + // + // If above was successful, find the group that corresponds to this + // targetId and update its LB policy as well as the states of the paths + // + if (NT_SUCCESS(status)) { + + DsmpSetLBForVidPidPolicyAdjustment(dsmContext, vidpidIndex, loadBalancePolicy, preferredPath); + } else { + errorStatus = status; + } + } + + // + // If any error occurred, return the last error. + // + if (!NT_SUCCESS(errorStatus)) { + status = errorStatus; + } + + break; + } + + case MSDSM_DEFAULT_LOAD_BALANCE_POLICYGUID_Index: { + + PMSDSM_DEFAULT_LOAD_BALANCE_POLICY dsmPolicyInfo = (PMSDSM_DEFAULT_LOAD_BALANCE_POLICY)Buffer; + DSM_LOAD_BALANCE_TYPE loadBalancePolicy; + ULONGLONG preferredPath; + + // + // Determine the correct buffer size. + // + dataLength = sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY); + + if (BufferAvail < dataLength) { + + status = STATUS_BUFFER_TOO_SMALL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Incorrect buffer size. Status %x\n", + DsmContext, + GuidIndex, + status)); + break; + } + + loadBalancePolicy = dsmPolicyInfo->LoadBalancePolicy; + preferredPath = (ULONGLONG)((ULONG_PTR)dsmPolicyInfo->PreferredPath); + + // + // First ensure that the values make sense. + // + if (loadBalancePolicy >= DSM_LB_VENDOR_SPECIFIC) { + + status = STATUS_INVALID_PARAMETER; + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): GuidIndex %u. Invalid policy %u specified. Status %x\n", + DsmContext, + GuidIndex, + loadBalancePolicy, + status)); + + } else { + + // + // Update/create the values in the registry with the LB policy info. + // If the LB policy is specified as 0, delete the values. + // + status = DsmpSetDsmLBPolicyInRegistry(loadBalancePolicy, preferredPath); + + // + // If above is successful, find the groups that haven't had their LB policy + // explicitly set or haven't had their policy set in accordance with target + // hardware id. For each of these, adjust the states of the paths as well. + // + if (NT_SUCCESS(status)) { + + DsmpSetLBForDsmPolicyAdjustment(dsmContext, loadBalancePolicy, preferredPath); + } + } + + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): Unknown GuidIndex %d.\n", + DsmContext, + GuidIndex)); + + break; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmGlobalSetData (DsmContext %p): Exiting function with status 0x%x.\n", + DsmContext, + status)); + + return status; +} + + +VOID +DsmpWmiInitialize( + _In_ IN PDSM_WMILIB_CONTEXT WmiInfo, + _In_ IN PUNICODE_STRING RegistryPath + ) +/*++ + +Routine Description: + + This routine intializes the Device-specific WmiInfo structure that is passed + back to MPIO during DriverEntry. + +Arguments: + + WmiInfo - WMI information structure to initialize. + RegistryPath - Registry path to the service key for this driver. + +Return Value: + + None + +--*/ +{ + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmpWmiInitialize (RegPath %ws): Entering function.\n", + RegistryPath->Buffer)); + + RtlZeroMemory(WmiInfo, sizeof(DSM_WMILIB_CONTEXT)); + + // + // Build the mof resource name. This tells wmi via the busdriver, + // where to find the mof data. This is found in the .rc. + // + RtlInitUnicodeString(&WmiInfo->MofResourceName, L"MofResourceName"); + + // + // This will jam in the entry points and guids for supported WMI + // operations. SetDataBlock, SetDataItem, and FunctionControl are + // currently not needed, so leave them set to zero. + // + WmiInfo->GuidCount = DsmGuidCount; + WmiInfo->GuidList = DsmGuidList; + + WmiInfo->QueryWmiDataBlockEx = DsmQueryData; + WmiInfo->ExecuteWmiMethodEx = DsmExecuteMethod; + + // + // Allocate a buffer for the reg. path. + // + WmiInfo->RegistryPath.Buffer = DsmpAllocatePool(NonPagedPoolNx, + RegistryPath->MaximumLength, + DSM_TAG_REG_PATH); + if (WmiInfo->RegistryPath.Buffer) { + + // + // Set maximum length of the new string and copy it. + // + WmiInfo->RegistryPath.MaximumLength = RegistryPath->MaximumLength; + + RtlCopyUnicodeString(&WmiInfo->RegistryPath, RegistryPath); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_INIT, + "DsmpWmiInitialize (RegPath %ws): Failed to allocate memory for Registry path in WMIInfo.\n", + RegistryPath->Buffer)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_INIT, + "DsmpWmiInitialize (RegPath %ws): Exiting function.\n", + RegistryPath->Buffer)); + + return; +} + + +NTSTATUS +DsmQueryData( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG InstanceCount, + _Inout_ IN OUT PULONG InstanceLengthArray, + _In_ IN ULONG BufferAvail, + _When_(GuidIndex == DSM_LBOperationsGUID_Index || GuidIndex == MSDSM_WMI_METHODSGuidIndex, _Pre_notnull_ _Const_) + _When_(!(GuidIndex == DSM_LBOperationsGUID_Index || GuidIndex == MSDSM_WMI_METHODSGuidIndex), _Out_writes_to_(BufferAvail, *DataLength)) + OUT PUCHAR Buffer, + _Out_ OUT PULONG DataLength, + ... + ) +/*++ + +Routine Description: + + This is the main WMI query entry point. The index into the GUID array is found + and assuming the buffer is large enough, the data will be copied over. + +Arguments: + + DsmContext - Global DSM Context + DsmIds - Dsm Ids + Irp - The WMI Irp + GuidIndex - Index into the WMIGUIDINFO array + InstanceIndex - Index of the data instance + InstanceCount - Number of instances + InstanceLengthArray - Array of ULONGs that indicate per-instance data lengths. + BufferAvail - Size of the buffer in which data is returned. + Buffer - Buffer in which the data is returned. + DataLength - Storage for the actual data length written. + +Return Value: + + STATUS_BUFFER_TOO_SMALL - If output buffer is not big enough to + to return all the available data. + STATUS_WMI_GUID_NOT_FOUND - If GuidIndex doesn't correspond to an actual entry + in the reginfo array. + STATUS_SUCCESS - On success. + +--*/ +{ + ULONG sizeNeeded; + NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; + + UNREFERENCED_PARAMETER(DsmContext); + UNREFERENCED_PARAMETER(InstanceCount); + UNREFERENCED_PARAMETER(InstanceIndex); + UNREFERENCED_PARAMETER(Irp); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmQueryData (DsmIds %p): Entering function - GuidIndex %u.\n", + DsmIds, + GuidIndex)); + + // + // Check the GuidIndex - the index into the DsmGuildList array - to see + // whether this is a supported GUID or not. + // + switch(GuidIndex) { + + case DSM_LBOperationsGUID_Index: { + + // + // Even though this class only has methods, we need to respond + // to any queries for it since WMI expects that there is an actual + // instance of the class on which to execute the method + // + + sizeNeeded = sizeof(ULONG); + + *DataLength = sizeNeeded; + + if (BufferAvail >= sizeNeeded) { + + *InstanceLengthArray = sizeNeeded; + status = STATUS_SUCCESS; + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_WMI, + "DsmQueryData (DsmIds %p): Buffer too small in query data. Needed %d, Given %d.\n", + DsmIds, + sizeNeeded, + BufferAvail)); + + status = STATUS_BUFFER_TOO_SMALL; + } + + break; + } + + case DSM_QueryLBPolicyGUID_Index: + case DSM_QueryLBPolicyV2GUID_Index: { + + *DataLength = BufferAvail; + + status = DsmpQueryLoadBalancePolicy(DsmContext, + DsmIds, + ((GuidIndex == DSM_QueryLBPolicyGUID_Index) ? DSM_WMI_VERSION_1 : DSM_WMI_VERSION_2), + BufferAvail, + DataLength, + Buffer); + break; + } + + case DSM_QuerySupportedLBPoliciesGUID_Index: + case DSM_QuerySupportedLBPoliciesV2GUID_Index: { + + *DataLength = BufferAvail; + + status = DsmpQuerySupportedLBPolicies(DsmContext, + DsmIds, + BufferAvail, + ((GuidIndex == DSM_QuerySupportedLBPoliciesGUID_Index) ? DSM_WMI_VERSION_1 : DSM_WMI_VERSION_2), + DataLength, + Buffer); + break; + } + + case DSM_QueryDsmUniqueIdGUID_Index: { + + PDSM_QueryUniqueId dsmQueryUniqueId; + + *DataLength = sizeof(DSM_QueryUniqueId); + + if (BufferAvail >= sizeof(DSM_QueryUniqueId)) { + + dsmQueryUniqueId = (PDSM_QueryUniqueId) Buffer; + dsmQueryUniqueId->DsmUniqueId = (ULONGLONG)((ULONG_PTR)DsmContext); + status = STATUS_SUCCESS; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmQueryData (DsmIds %p): Buffersize %d too small for Query Unique Id.\n", + DsmIds, + BufferAvail)); + + status = STATUS_BUFFER_TOO_SMALL; + } + + break; + } + + case MSDSM_DEVICE_PERFGuidIndex: { + + *DataLength = BufferAvail; + + status = DsmpQueryDevicePerf(DsmContext, + DsmIds, + BufferAvail, + DataLength, + Buffer); + + break; + } + + case MSDSM_WMI_METHODSGuidIndex: { + + // + // Even though this class only has methods, we need to respond + // to any queries for it since WMI expects that there is an actual + // instance of the class on which to execute the method + // + + sizeNeeded = sizeof(ULONG); + + *DataLength = sizeNeeded; + + if (BufferAvail >= sizeNeeded) { + + *InstanceLengthArray = sizeNeeded; + status = STATUS_SUCCESS; + + } else { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_WMI, + "DsmQueryData (DsmIds %p): Buffer too small in query data. Needed %d, Given %d.\n", + DsmIds, + sizeNeeded, + BufferAvail)); + + status = STATUS_BUFFER_TOO_SMALL; + } + + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmQueryData (DsmIds %p): Unknown GuidIndex %d in DsmQueryData.\n", + DsmIds, + GuidIndex)); + + *DataLength = 0; + + break; + } + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmQueryData (DsmIds %p): Exiting function with status 0x%x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryLoadBalancePolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG DsmWmiVersion, + _In_ IN ULONG InBufferSize, + _In_ IN PULONG OutBufferSize, + _Out_writes_bytes_(*OutBufferSize) OUT PVOID Buffer + ) +/*+++ + +Routine Description: + + This routine returns the current Load Balance policy settings + for the given device. + +Arguements: + + DsmContext - Global DSM context + DsmIds - DSM Ids for the given device + DsmWmiVersion - version of the MPIO_DSM_Path class to use + InBufferSize - Size of the input buffer + OutBufferSize - Size of the output buffer + Buffer - Buffer in which the current Load Balance policy settings + is returned, if the buffer is big enough + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + PDSM_GROUP_ENTRY groupEntry; + PDSM_DEVICE_INFO devInfo; + PDSM_DEVICE_INFO rtpgDeviceInfo = NULL; + ULONG inx; + ULONG sizeNeeded; + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + PDSM_Load_Balance_Policy_V2 supportedLBPolicies; + PMPIO_DSM_Path_V2 dsmPath; + PDSM_FAILOVER_GROUP foGroup; + ULONG SpecialHandlingFlag = 0; + + UNREFERENCED_PARAMETER(InBufferSize); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryLoadBalancePolicy (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // At least one device should be given + // + if (DsmIds->Count == 0) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryLoadBalancePolicy (DsmIds %p): No DSM Ids given in DsmpQueryLoadBalancePolicy.\n", + DsmIds)); + + *OutBufferSize = 0; + status = STATUS_INVALID_PARAMETER; + + goto __Exit_DsmpQueryLoadBalancePolicy; + } + + // + // Compute the size needed for returning LoadBalance policy information + // + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths)); + sizeNeeded += (DsmIds->Count) * sizeof(MPIO_DSM_Path); + + } else { + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths)); + sizeNeeded += (DsmIds->Count * sizeof(MPIO_DSM_Path_V2)); + } + + if (*OutBufferSize < sizeNeeded) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryLoadBalancePolicy (DsmIds %p): Output buffer too small for QueryLBPolicy.\n", + DsmIds)); + + *OutBufferSize = sizeNeeded; + status = STATUS_BUFFER_TOO_SMALL; + + goto __Exit_DsmpQueryLoadBalancePolicy; + } + + // + // Set the size of the data returned to user + // + *OutBufferSize = sizeNeeded; + + // + // Zero out the output buffer first + // + RtlZeroMemory(Buffer, sizeNeeded); + + devInfo = DsmIds->IdList[0]; + DSM_ASSERT(devInfo && devInfo->DeviceSig == DSM_DEVICE_SIG); + groupEntry = devInfo->Group; + + // + // Send down an RTPG to get the current state info if implicit transitions + // are supported, since the states may have changed from under us. + // Storages that support both implicit and explicit transitions that haven't + // allowed us to turn OFF their implicit transitions, may have also changed + // TPG states from under us. So do this for such storages also. + // + if (!DsmpIsSymmetricAccess(devInfo) && + devInfo->ALUASupport != DSM_DEVINFO_ALUA_EXPLICIT) { + + rtpgDeviceInfo = DsmpGetActivePathToBeUsed(groupEntry, FALSE, SpecialHandlingFlag); + + if (!rtpgDeviceInfo) { + + BOOLEAN sendTPG = FALSE; + + rtpgDeviceInfo = DsmpFindStandbyPathToActivateALUA(groupEntry, &sendTPG, SpecialHandlingFlag); + } + + if (rtpgDeviceInfo) { + + status = DsmpGetDeviceALUAState(DsmContext, rtpgDeviceInfo, NULL); + } + } + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // If an RTPG was sent down, update all the devInfo states. + // + if (NT_SUCCESS(status) && rtpgDeviceInfo) { + + DsmpAdjustDeviceStatesALUA(groupEntry, NULL, SpecialHandlingFlag); + } + + supportedLBPolicies = &(((PDSM_QueryLBPolicy_V2)Buffer)->LoadBalancePolicy); + supportedLBPolicies->Version = DSM_WMI_VERSION; + supportedLBPolicies->LoadBalancePolicy = groupEntry->LoadBalanceType; + supportedLBPolicies->DSMPathCount = DsmIds->Count; + dsmPath = supportedLBPolicies->DSM_Paths; + + // + // Indicate which path is active and which path(s) are standby paths + // + inx = 0; + while (inx < DsmIds->Count) { + + devInfo = (PDSM_DEVICE_INFO)DsmIds->IdList[inx]; + + dsmPath->PathWeight = devInfo->PathWeight; + dsmPath->Reserved = DSM_STATE_ACTIVE_OPTIMIZED_SUPPORTED; + + if (devInfo->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED) { + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + dsmPath->TargetPortGroup_State = DSM_DEV_NOT_USED_STATE; + } + + dsmPath->Reserved |= DSM_STATE_STANDBY_SUPPORTED; + + } else { + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + dsmPath->TargetPortGroup_State = devInfo->TargetPortGroup->AsymmetricAccessState; + dsmPath->TargetPortGroup_Preferred = devInfo->TargetPortGroup->Preferred; + dsmPath->TargetPortGroup_Identifier = devInfo->TargetPortGroup->Identifier; + + if (devInfo->TargetPort) { + + dsmPath->TargetPort_Identifier = devInfo->TargetPort->Identifier; + } + + if (groupEntry->Symmetric) { + + // + // For certain policies like FOO and RRWS, we need to be able to put + // path in standby. + // + dsmPath->Reserved |= DSM_STATE_STANDBY_SUPPORTED; + } + } + + dsmPath->Reserved |= devInfo->TargetPortGroup->ActiveUnoptimizedSupported ? DSM_STATE_ACTIVE_UNOPTIMIZED_SUPPORTED : 0; + dsmPath->Reserved |= devInfo->TargetPortGroup->StandBySupported ? DSM_STATE_STANDBY_SUPPORTED : 0; + dsmPath->Reserved |= devInfo->TargetPortGroup->UnavailableSupported ? DSM_STATE_UNAVAILABLE_SUPPORTED : 0; + } + + groupEntry = devInfo->Group; + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + dsmPath->SymmetricLUA = groupEntry->Symmetric; + dsmPath->ALUASupport = devInfo->ALUASupport; + + } + + if (DsmpIsDeviceFailedState(devInfo->State) || !DsmpIsDeviceInitialized(devInfo)) { + + dsmPath->PrimaryPath = FALSE; + dsmPath->DsmPathId = 0; + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + dsmPath->OptimizedPath = dsmPath->PreferredPath = FALSE; + dsmPath->FailedPath = TRUE; + } + + } else { + + foGroup = devInfo->FailGroup; + dsmPath->DsmPathId = (ULONGLONG)((ULONG_PTR)foGroup->PathId); + + if (DsmpIsDeviceStateActive(devInfo->State)) { + + dsmPath->PrimaryPath = TRUE; + } + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + if (devInfo->State == DSM_DEV_ACTIVE_OPTIMIZED || + devInfo->State == DSM_DEV_STANDBY) { + + dsmPath->OptimizedPath = TRUE; + } + + if (((ULONGLONG)((ULONG_PTR)(foGroup->PathId))) == (devInfo->Group->PreferredPath)) { + + dsmPath->PreferredPath = TRUE; + } + } + } + +#if DBG + if (!dsmPath->PrimaryPath && + !dsmPath->FailedPath) { + NT_ASSERT(groupEntry->LoadBalanceType != DSM_LB_ROUND_ROBIN && + groupEntry->LoadBalanceType != DSM_LB_WEIGHTED_PATHS && + groupEntry->LoadBalanceType != DSM_LB_DYN_LEAST_QUEUE_DEPTH && + groupEntry->LoadBalanceType != DSM_LB_LEAST_BLOCKS); + } +#endif + + dsmPath = DsmWmiVersion == DSM_WMI_VERSION_1 ? + (PVOID)((PUCHAR)dsmPath + sizeof(MPIO_DSM_Path)) : + (PVOID)((PUCHAR)dsmPath + sizeof(MPIO_DSM_Path_V2)); + + inx++; + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + +__Exit_DsmpQueryLoadBalancePolicy: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryLoadBalancePolicy (DsmIds %p): Exiting with status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpQuerySupportedLBPolicies( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG BufferAvail, + _In_ IN ULONG DsmWmiVersion, + _Out_ OUT PULONG OutBufferSize, + _Out_writes_to_(BufferAvail, *OutBufferSize) OUT PUCHAR Buffer + ) +/*+++ + +Routine Description: + + This routine returns the load balance policies supported by this DSM for the + given LUN (specified by the DsmIds). + +Arguements: + + DsmContext - Global DSM context + DsmIds - DSM Ids for the given device + BufferAvail - Size of buffer available. + DsmWmiVersion - Indicates which version of MPIO_DSMPath to use. + OutBufferSize - Size of the output buffer. + Buffer - Buffer in which the supported Load Balance policies are + returned, if the buffer is big enough. + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + PDSM_QuerySupportedLBPolicies_V2 supportedLBPolicies; + PDSM_Load_Balance_Policy_V2 dsmLBPolicy; + ULONG sizeNeeded; + ULONG policyCount; + ULONG inx; + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN skipRR = FALSE; + PDSM_DEVICE_INFO devInfo = NULL; + PUCHAR endOfBuffer; + + UNREFERENCED_PARAMETER(DsmContext); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI,"DsmpQuerySupportedLBPolicies (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // At least one device should be given + // + if (DsmIds->Count == 0) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQuerySupportedLBPolicies (DsmIds %p): No DSM Ids given in DsmpQuerySupportedLBPolicies.\n", + DsmIds)); + + *OutBufferSize = 0; + status = STATUS_INVALID_PARAMETER; + + goto __Exit_DsmpQuerySupportedLBPolicies; + } + + devInfo = DsmIds->IdList[0]; + DSM_ASSERT(devInfo && devInfo->DeviceSig == DSM_DEVICE_SIG); + + policyCount = DSM_NUMBER_OF_LB_POLICIES; + + // + // Round Robin policy is not supported for arrays that are AAA. + // + if (!DsmpIsSymmetricAccess(devInfo)) { + + skipRR = TRUE; + policyCount--; + } + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_QuerySupportedLBPolicies, Supported_LB_Policies)); + sizeNeeded += policyCount * AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths)); + + } else { + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(DSM_QuerySupportedLBPolicies_V2, Supported_LB_Policies)); + sizeNeeded += policyCount * AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths)); + } + + // + // Set the size of the data returned to user or needed but not provided. + // + *OutBufferSize = sizeNeeded; + + if (sizeNeeded > BufferAvail) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQuerySupportedLBPolicies (Buffer %p): Output buffer too small. Size needed = %u.\n", + Buffer, + sizeNeeded)); + + status = STATUS_BUFFER_TOO_SMALL; + + goto __Exit_DsmpQuerySupportedLBPolicies; + } + + endOfBuffer = Buffer + sizeNeeded - 1; + + // + // Zero out the output buffer first + // + supportedLBPolicies = (PDSM_QuerySupportedLBPolicies_V2)Buffer; + RtlZeroMemory(Buffer, sizeNeeded); + + supportedLBPolicies->SupportedLBPoliciesCount = policyCount; + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + dsmLBPolicy = &(supportedLBPolicies->Supported_LB_Policies[0]); + + } else { + + dsmLBPolicy = (PVOID)&(((PDSM_QuerySupportedLBPolicies)supportedLBPolicies)->Supported_LB_Policies[0]); + } + + // + // All Load Balance policies are supported in Windows Server 2003 + // and above. + // + for (inx = 0; inx < DSM_NUMBER_OF_LB_POLICIES; inx++) { + + // + // Skip reporting Round Robin for AAA arrays. + // + if (((inx + 1) == DSM_LB_ROUND_ROBIN) && skipRR) { + + continue; + } + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + if ((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths)) - 1 > endOfBuffer) { + + status = STATUS_BUFFER_TOO_SMALL; + break; + } + } else { + + if ((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths)) - 1 > endOfBuffer) { + + status = STATUS_BUFFER_TOO_SMALL; + break; + } + } + + dsmLBPolicy->Version = DSM_WMI_VERSION; + + // + // The value set for LoadBalancePolicy is based on + // the #define for LB policies in LBPolicy.h + // + dsmLBPolicy->LoadBalancePolicy = inx + 1; + + // + // Point to the next DSM_Load_Balance_Policy area + // + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + dsmLBPolicy = (PDSM_Load_Balance_Policy_V2)((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths))); + + } else { + + dsmLBPolicy = (PVOID)((PUCHAR)dsmLBPolicy + AlignOn8Bytes(FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths))); + } + } + +__Exit_DsmpQuerySupportedLBPolicies: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQuerySupportedLBPolicies (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmExecuteMethod( + _In_ IN PVOID DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN PIRP Irp, + _In_ IN ULONG GuidIndex, + _In_ IN ULONG InstanceIndex, + _In_ IN ULONG MethodId, + _In_ IN ULONG InBufferSize, + _In_ IN PULONG OutBufferSize, + _Inout_ IN OUT PUCHAR Buffer, + ... + ) +/*++ + +Routine Description: + + This routine handles the invocation of WMI methods defined in the DSM mof. + +Arguments: + + DsmContext - Global DSM context + DsmIds - DSM Ids + Irp - The WMI Irp + GuidIndex - Index into the WMIGUIDINFO array + InstanceIndex - Index value indicating for which instance data should be returned. + MethodId - Specifies which method to invoke. + InBufferSize - Buffer size, in bytes, of input parameter data. + OutBufferSize - Buffer size, in bytes, of output data. + Buffer - Buffer to which the data is read/written. + +Return Value: + + Status of the method, or STATUS_WMI_ITEMID_NOT_FOUND + +--*/ +{ + NTSTATUS status = STATUS_WMI_GUID_NOT_FOUND; + UNREFERENCED_PARAMETER(DsmContext); + UNREFERENCED_PARAMETER(InstanceIndex); + UNREFERENCED_PARAMETER(Irp); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmExecuteMethod (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // This should be the index for ExecMethod Index + // + if (GuidIndex == DSM_LBOperationsGUID_Index) { + + switch (MethodId) { + + case DsmSetLoadBalancePolicy: + case DsmSetLoadBalancePolicyALUA: { + + status = DsmpSetLoadBalancePolicy(DsmContext, + DsmIds, + (MethodId == DsmSetLoadBalancePolicy) ? DSM_WMI_VERSION_1 : DSM_WMI_VERSION_2, + InBufferSize, + OutBufferSize, + Buffer); + break; + } + + default: { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmExecuteMethod (DsmIds %p): Unknown MethodId %d in DsmExecuteMethod.\n", + DsmIds, + MethodId)); + + status = STATUS_WMI_ITEMID_NOT_FOUND; + + break; + } + } + } else if (GuidIndex == MSDSM_WMI_METHODSGuidIndex) { + + if (MethodId == MSDsmClearCounters) { + + status = DsmpClearPerfCounters(DsmContext, DsmIds); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmExecuteMethod (DsmIds %p): Unknown MethodId %d for GuidIndex %d in DsmExecuteMethod.\n", + DsmIds, + MethodId, + GuidIndex)); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmExecuteMethod (DsmIds %p): Unknown GuidIndex %d in DsmExecuteMethod.\n", + DsmIds, + GuidIndex)); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmExecuteMethod (DsmIds %p): Exiting function with status 0x%x.\n", + DsmIds, + status)); + + return status; +} + +NTSTATUS +DsmpClearLoadBalancePolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds + ) +/*++ + +Routine Description: + + This routine is called to clear the LUN-specific load balance policy for the given device. + + First, the routine will try to clear the "explicitly set" registry key for the device. If + this fails, the whole routine is aborted. + + If the registry key is successfully cleared, the following happens: + 1. Check to see if there is a target-wide load balance policy set for this device's VID/PID. + If yes, we set the device's load balance policy accordingly and return. + 2. Check to see if there is an MSDSM-wide load balance policy set. + If yes, we set the device's load balance policy accordingly and return. + 3. If steps 1 and 2 fall through, we set the device's load balance policy to RR, or RRWS if + ALUA is enabled. + +Arguements: + + DsmContext - Global DSM context + DsmIds - DSM Ids for the given device + +Return Value: + + Appropriate status indicating the error if the input is malformed or + if the function was unable to clear the load balance policy. + STATUS_SUCCESS on success + +--*/ + +{ + NTSTATUS status = STATUS_SUCCESS; + PDSM_DEVICE_INFO deviceInfo = NULL; + PDSM_GROUP_ENTRY group = NULL; + HANDLE lbSettingsKey = NULL; + HANDLE deviceKey = NULL; + UNICODE_STRING subKeyName; + OBJECT_ATTRIBUTES objectAttributes; + DSM_LOAD_BALANCE_TYPE loadBalanceType; + ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + ULONG devInfoIndex; + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpClearLoadBalancePolicy (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // There should be at least one device + // + if (DsmIds->Count == 0) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_WMI, + "DsmpClearLoadBalancePolicy (DsmIds %p): No DSM Ids given.\n", + DsmIds)); + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpClearLoadBalancePolicy; + } + + deviceInfo = (PDSM_DEVICE_INFO)DsmIds->IdList[0]; + group = deviceInfo->Group; + + // + // First open LoadBalanceSettings key under the Services key + // + status = DsmpOpenLoadBalanceSettingsKey(KEY_ALL_ACCESS, &lbSettingsKey); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpClearLoadBalancePolicy (DevName %ws): Failed to open LB Settings key. Status %x.\n", + group->RegistryKeyName, + status)); + + goto __Exit_DsmpClearLoadBalancePolicy; + } + + // + // Now open the key under which the LB settings for the given device is stored + // and clear the DsmLoadBalancePolicyExplicitlySet key. + // + RtlInitUnicodeString(&subKeyName, group->RegistryKeyName); + + InitializeObjectAttributes(&objectAttributes, + &subKeyName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + lbSettingsKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(&deviceKey, KEY_ALL_ACCESS, &objectAttributes); + + if (NT_SUCCESS(status)) { + + UCHAR explicitlySet = FALSE; + + status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, + deviceKey, + DSM_POLICY_EXPLICITLY_SET, + REG_BINARY, + &explicitlySet, + sizeof(UCHAR)); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpClearLoadBalancePolicy (DevName %ws): Failed to clear DsmLoadBalancePolicyExplicitlySet key.\n", + group->RegistryKeyName)); + + goto __Exit_DsmpClearLoadBalancePolicy; + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpClearLoadBalancePolicy (DevName %ws): Failed to open device subkey.\n", + group->RegistryKeyName)); + + goto __Exit_DsmpClearLoadBalancePolicy; + } + + + + // + // Set the defaults. These will be used if no target-wide or MSDSM-wide + // load balance policies are set. + // + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_ALUA_CAPABILITY; + loadBalanceType = DSM_LB_ROUND_ROBIN; + preferredPath = 0; + + // + // Check to see if target-wide (VID/PID) LB policy is set for this device. + // + status = DsmpQueryTargetLBPolicyFromRegistry(deviceInfo, + &loadBalanceType, + &preferredPath); + if (NT_SUCCESS(status)) { + + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_VID_PID; + + } else if (status == STATUS_OBJECT_NAME_NOT_FOUND) { + + // + // Since the policy hasn't been set for this VID/PID, check if + // overall MSDSM-wide policy has been set. + // + status = DsmpQueryDsmLBPolicyFromRegistry(&loadBalanceType, + &preferredPath); + if (NT_SUCCESS(status)) { + + group->LBPolicySelection = DSM_DEFAULT_LB_POLICY_DSM_WIDE; + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpClearLoadBalancePolicy (DevInfo %p): Failed to query Dsm overall LB policy from registry. Status %x.\n", + deviceInfo, + status)); + + NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); + status = STATUS_SUCCESS; + } + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_PNP, + "DsmpClearLoadBalancePolicy (DevInfo %p): Failed to query VID/PID LB policy from registry. Status %x.\n", + deviceInfo, + status)); + + NT_ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND); + status = STATUS_SUCCESS; + } + + + // + // If the storage is ALUA enabled and we specified Round Robin, change + // it to Round Robin with Subset instead. + // + if (!DsmpIsSymmetricAccess(deviceInfo) && loadBalanceType == DSM_LB_ROUND_ROBIN) { + + loadBalanceType = DSM_LB_ROUND_ROBIN_WITH_SUBSET; + } + + // + // Finally set the load balance policy and the preferred path. + // + group->LoadBalanceType = loadBalanceType; + group->PreferredPath = preferredPath; + + // + // Update the path states in accordance with the new policy. + // + for (devInfoIndex = 0; devInfoIndex < DSM_MAX_PATHS; devInfoIndex++) { + + DsmpSetNewDefaultLBPolicy(DsmContext, + group->DeviceList[devInfoIndex], + group->LoadBalanceType, + SpecialHandlingFlag); + } + +__Exit_DsmpClearLoadBalancePolicy: + + if (deviceKey) { + ZwClose(deviceKey); + } + + if (lbSettingsKey) { + ZwClose(lbSettingsKey); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpClearLoadBalancePolicy (DsmIds %p): Exiting function with status 0x%x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpSetLoadBalancePolicy( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG DsmWmiVersion, + _In_ IN ULONG InBufferSize, + _In_ IN PULONG OutBufferSize, + _In_ IN PVOID Buffer + ) +/*++ + +Routine Description: + + This routine is called to set the load balance policy for the given device. + + If zero is passed in as the load balance policy, the LUN-specific load balance + policy will attempt to be cleared. See DsmpClearLoadBalancePolicy for more details. + +Arguements: + + DsmContext - Global DSM context + DsmIds - DSM Ids for the given device + DsmWmiVersion - version of the MPIO_DSM_Path class to use + InBufferSize - Size of the input buffer + OutBufferSize - Size of the output buffer + Buffer - Buffer for input\output data + +Return Value: + + STATUS_BUFFER_TOO_SMALL - If the input buffer is too small + Appropriate status indicating the error if the input is malformed. + STATUS_SUCCESS on success + +--*/ + +{ + PDsmSetLoadBalancePolicyALUA_IN setLoadBalancePolicyIN = (PDsmSetLoadBalancePolicyALUA_IN) Buffer; + PDsmSetLoadBalancePolicyALUA_OUT setLoadBalancePolicyOUT = (PDsmSetLoadBalancePolicyALUA_OUT) Buffer; + PVOID supportedLBPolicies; + PMPIO_DSM_Path_V2 dsmPath; + ULONG inx = 0; + ULONG jnx; + NTSTATUS status = STATUS_SUCCESS; + BOOLEAN lengthOkay = TRUE; + PDSM_DEVICE_INFO devInfo = NULL; + PDSM_DEVICE_INFO tempDevInfo = NULL; + PDSM_GROUP_ENTRY groupEntry; + PDSM_LOAD_BALANCE_POLICY_SETTINGS savedLBSettings = NULL; + KIRQL irql; + BOOLEAN optimized = TRUE; + BOOLEAN preferred = FALSE; + ULONG activePaths = 0; + ULONG activeTPGs = 0; + ULONG numberDevInfoChanged = 0; + ULONG numberPreferredPaths = 0; + DSM_LOAD_BALANCE_TYPE loadBalancePolicy; + BOOLEAN sendSTPG = FALSE; + ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + ULONG SpecialHandlingFlag = 0; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // There should be at least one device + // + if (DsmIds->Count == 0) { + + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): No DSM Ids given.\n", + DsmIds)); + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpSetLoadBalancePolicy; + } + + groupEntry = ((PDSM_DEVICE_INFO)DsmIds->IdList[0])->Group; + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + if (*OutBufferSize < sizeof(DsmSetLoadBalancePolicy_OUT)) { + + *OutBufferSize = sizeof(DsmSetLoadBalancePolicy_OUT); + lengthOkay = FALSE; + } + } else { + + if (*OutBufferSize < sizeof(DsmSetLoadBalancePolicyALUA_OUT)) { + + *OutBufferSize = sizeof(DsmSetLoadBalancePolicyALUA_OUT); + lengthOkay = FALSE; + } + } + + if (!lengthOkay) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Buffer too small for SetLBPolicy.\n", + DsmIds)); + + status = STATUS_BUFFER_TOO_SMALL; + goto __Exit_DsmpSetLoadBalancePolicy; + } + + *OutBufferSize = (DsmWmiVersion == DSM_WMI_VERSION_1) ? sizeof(DsmSetLoadBalancePolicy_OUT) : sizeof(DsmSetLoadBalancePolicyALUA_OUT); + + // + // If the user specified zero as the load balance policy, we need to clear the + // LUN-specific load balance policy. + // + if (setLoadBalancePolicyIN->LoadBalancePolicy.LoadBalancePolicy == 0) { + status = DsmpClearLoadBalancePolicy(DsmContext, DsmIds); + goto __Exit_DsmpSetLoadBalancePolicy; + } + + status = DsmpValidateSetLBPolicyInput(DsmContext, + DsmIds, + DsmWmiVersion, + Buffer, + InBufferSize); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Failed to validate input. Status %x.\n", + DsmIds, + status)); + + goto __Exit_DsmpSetLoadBalancePolicy; + } + + // + // At this point the Reserved field in each MPIO_DSM_Path should + // contain the respective Device Info + // + supportedLBPolicies = &(setLoadBalancePolicyIN->LoadBalancePolicy); + loadBalancePolicy = ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->LoadBalancePolicy; + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Cache each DeviceInfo's current state. + // This will be used to rollback in case of errors. + // + DsmpSaveDeviceState(supportedLBPolicies, DsmWmiVersion); + + while (inx < ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSMPathCount) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); + + optimized = TRUE; + preferred = FALSE; + + } else { + + dsmPath = &(((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSM_Paths[inx]); + + optimized = dsmPath->OptimizedPath ? TRUE : FALSE; + preferred = dsmPath->PreferredPath ? TRUE : FALSE; + + if (preferred && loadBalancePolicy == DSM_LB_FAILOVER) { + + preferredPath = dsmPath->DsmPathId; + + if (preferredPath != 0) { + + numberPreferredPaths++; + } + + if (numberPreferredPaths > 1) { + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + status = STATUS_INVALID_PARAMETER; + break; + } + } + } + + // + // Reserved field in MPIO_DSM_Path is set to DeviceInfo in + // DsmpValidateSetLBPolicyInput routine. + // + devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; + + if (!devInfo) { + + inx++; + continue; + + } else { + + if (!tempDevInfo) { + + tempDevInfo = devInfo; + + if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || + loadBalancePolicy == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { + + InterlockedExchangePointer(&(groupEntry->PathToBeUsed), NULL); + } + } + } + + if (!DsmpIsDeviceFailedState(devInfo->State)) { + + if (devInfo->ALUAState == DSM_DEV_ACTIVE_OPTIMIZED) { + + activeTPGs++; + } + + if (dsmPath->PrimaryPath) { + + // + // Optimized flag decides between AO and AU + // + if (optimized) { + + // + // For implicit-only ALUA, state cannot be explicitly changed to A/O + // + if (!DsmpIsSymmetricAccess(devInfo) && devInfo->ALUASupport == DSM_DEVINFO_ALUA_IMPLICIT) { + + // + // While we can mask off acutal A/O to be A/U, there is no + // way to explicitly make non-A/O state A/O + // + if (devInfo->ALUAState != DSM_DEV_ACTIVE_OPTIMIZED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Can't make non-AO path A/O for Implicit-only transitions.\n", + DsmIds)); + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + status = STATUS_INVALID_PARAMETER; + break; + } + } + + numberDevInfoChanged++; + + devInfo->State = DSM_DEV_ACTIVE_OPTIMIZED; + activePaths++; + + // + // Check to see if the actual making of this path state A/O + // will require an STPG to be sent down. + // + if (devInfo->TargetPortGroup && + devInfo->ALUAState != DSM_DEV_ACTIVE_OPTIMIZED) { + + sendSTPG = TRUE; + } + + if (loadBalancePolicy == DSM_LB_FAILOVER) { + + // + // Only ONE path can be specified as AO for FailOverOnly policy. + // + if (activePaths > 1) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): More than one AO node given for FO Only.\n", + DsmIds)); + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + status = STATUS_INVALID_PARAMETER; + break; + } + } + + if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || + loadBalancePolicy == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { + + if (!groupEntry->PathToBeUsed) { + InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)devInfo->FailGroup); + } + } + } else { + + // + // This is an ActiveUnoptimized path + // + devInfo->State = DSM_DEV_ACTIVE_UNOPTIMIZED; + + // + // For LB policy RR, WP, LB and LQD, all paths must be in A/O + // state. However, this is not possible for ALUA storages. + // For these storages, A/U is allowable only if that is the + // access state that the TPG is in. + // + if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || + loadBalancePolicy == DSM_LB_WEIGHTED_PATHS || + loadBalancePolicy == DSM_LB_DYN_LEAST_QUEUE_DEPTH || + loadBalancePolicy == DSM_LB_LEAST_BLOCKS) { + + if (devInfo->TargetPortGroup && devInfo->ALUAState != DSM_DEV_ACTIVE_UNOPTIMIZED) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Path (%u) specified in A/U state when TPG is in %u state (for LB %u).\n", + DsmIds, + inx, + devInfo->ALUAState, + loadBalancePolicy)); + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + status = STATUS_INVALID_PARAMETER; + break; + } + } + } + } else { + + if (optimized) { + + // + // This is a standby path + // + devInfo->State = DSM_DEV_STANDBY; + + } else { + + // + // This is unavailable path + // + devInfo->State = DSM_DEV_UNAVAILABLE; + } + + // + // For RR, LQD, LB and WP, all paths must be in A/O state for non-ALUA + // storage. For ALUA storage, the only time path states can be in + // S/B or U/A is if the TPG itself is in that state. + // + if (loadBalancePolicy == DSM_LB_ROUND_ROBIN || + loadBalancePolicy == DSM_LB_WEIGHTED_PATHS || + loadBalancePolicy == DSM_LB_DYN_LEAST_QUEUE_DEPTH || + loadBalancePolicy == DSM_LB_LEAST_BLOCKS) { + + if ((!devInfo->TargetPortGroup) || + (devInfo->TargetPortGroup && devInfo->State != devInfo->ALUAState)) { + + // + // No paths can be in SB or UA unless its TPG is in that state. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Path (%u) specified in non-active state for LB %u.\n", + DsmIds, + inx, + loadBalancePolicy)); + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + status = STATUS_INVALID_PARAMETER; + break; + } + } else if (loadBalancePolicy == DSM_LB_ROUND_ROBIN_WITH_SUBSET) { + + // + // It is okay to set a path to be in S/B or U/A state in RRWS + // if either the storage is non-ALUA, or if the storage is + // ALUA but the TPG is in A/O (where it can be masked) or the + // TPG is in the state that the path is being set to. + // + if ((devInfo->TargetPortGroup) && + (devInfo->ALUAState != DSM_DEV_ACTIVE_OPTIMIZED && devInfo->State != devInfo->ALUAState)) { + + // + // No paths can be in SB or UA unless its TPG is in that state. + // + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Path (%u) (in TPG state %u) can't be specified in non-active state for LB %u.\n", + DsmIds, + inx, + devInfo->ALUAState, + loadBalancePolicy)); + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + status = STATUS_INVALID_PARAMETER; + break; + } + } + } + } + + inx++; + } + + if (NT_SUCCESS(status)) { + + + // + // If we arrive here, that means DsmpValidateSetLBPolicyInput already returned success. + // The device info is found. + // + _Analysis_assume_(tempDevInfo != NULL); + + // + // There must be at least one AO path. Unless there are no A/O TPGs. + // eg. During a controller failover, it is possible that the TPG through + // the TPG through other controller is still in non-A/O state and the + // storage supports implicit transitions and is still in the midst of + // making the transition of the non-A/O TPG to A/O. During such windows + // the states for all paths will be non-A/O and there's nothing that can + // be done about it. This is not an error condition. + // + if (!activePaths) { + + if ((tempDevInfo->ALUASupport == DSM_DEVINFO_ALUA_NOT_SUPPORTED) || + (tempDevInfo->ALUASupport != DSM_DEVINFO_ALUA_NOT_SUPPORTED && activeTPGs)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): No active node given for LB %u.\n", + DsmIds, + loadBalancePolicy)); + + // + // Roll back to DeviceState to the state it was before + // processing this SetLB policy request + // + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + + status = STATUS_INVALID_PARAMETER; + } + } + } + + if (NT_SUCCESS(status)) { + + // + // If we arrive here, that means DsmpValidateSetLBPolicyInput already returned success. + // The device info is found. + // + _Analysis_assume_(tempDevInfo != NULL); + + // + // If device supports explicit transitions, we need to send down an + // STPG to enforce A/O path selection if we need to make a path in a + // non-A/O TPG active/optimized. + // + if (tempDevInfo->ALUASupport >= DSM_DEVINFO_ALUA_EXPLICIT && sendSTPG) { + + PUCHAR targetPortGroupsInfo = NULL; + ULONG targetPortGroupsInfoLength = 0; + PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR tpgDescriptor = NULL; + + // + // Build the target port groups info to set the new states. + // Send down an STPG for TPG descriptors for those devInfos' TPGs + // that need to be in AO state. If this causes side-effects in + // state transitions (these can't be considered implicit according + // to the spec), fake the devInfo states to what was selected. + // + targetPortGroupsInfoLength = SPC3_TARGET_PORT_GROUPS_HEADER_SIZE + + activePaths * sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR); + + targetPortGroupsInfo = DsmpAllocatePool(NonPagedPoolNx, + targetPortGroupsInfoLength, + DSM_TAG_TARGET_PORT_GROUPS); + + if (targetPortGroupsInfo) { + + PDSM_DEVICE_INFO devInfoToUse = NULL; + + // + // Set the new asymmetric access states for the the devices' target port groups + // + tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)(targetPortGroupsInfo + SPC3_TARGET_PORT_GROUPS_HEADER_SIZE); + + for (inx = 0, jnx = 0; + inx < ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSMPathCount; + inx++) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); + + } else { + + dsmPath = &(((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSM_Paths[inx]); + } + + devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; + + if (!devInfo) { + + continue; + } + + if (devInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { + + tpgDescriptor->AsymmetricAccessState = devInfo->State; + REVERSE_BYTES_SHORT(&tpgDescriptor->TPG_Identifier, &devInfo->TargetPortGroup->Identifier); + + tpgDescriptor = (PSPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)((PUCHAR)tpgDescriptor + sizeof(SPC3_SET_TARGET_PORT_GROUP_DESCRIPTOR)); + + jnx++; + } + + if (devInfo->TempPreviousStateForLB == DSM_DEV_ACTIVE_OPTIMIZED) { + + devInfoToUse = devInfo; + } + } + + NT_ASSERT(jnx == numberDevInfoChanged); + NT_ASSERT(devInfoToUse); + + if (devInfoToUse) { + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + status = DsmpSetTargetPortGroups(devInfoToUse->TargetObject, + targetPortGroupsInfo, + targetPortGroupsInfoLength); + + if (NT_SUCCESS(status)) { + + DsmpFreePool(targetPortGroupsInfo); + targetPortGroupsInfo = NULL; + targetPortGroupsInfoLength = 0; + status = DsmpReportTargetPortGroups(devInfoToUse->TargetObject, + &targetPortGroupsInfo, + &targetPortGroupsInfoLength); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): STPG failed with status %x.\n", + DsmIds, + status)); + + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + } + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + } + + if (NT_SUCCESS(status)) { + + ULONG index; + PDSM_TARGET_PORT_GROUP_ENTRY targetPortGroup; + + status = DsmpParseTargetPortGroupsInformation(DsmContext, + groupEntry, + targetPortGroupsInfo, + targetPortGroupsInfoLength); + + NT_ASSERT(NT_SUCCESS(status)); + + for (index = 0; index < DSM_MAX_PATHS; index++) { + + targetPortGroup = groupEntry->TargetPortGroupList[index]; + + if (targetPortGroup) { + + DsmpUpdateTargetPortGroupDevicesStates(targetPortGroup, targetPortGroup->AsymmetricAccessState); + } + } + + // + // Update TPGs with new state + // + for (inx = 0; + inx < ((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSMPathCount; + inx++) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); + + } else { + + dsmPath = &(((PDSM_Load_Balance_Policy_V2)supportedLBPolicies)->DSM_Paths[inx]); + } + + devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; + + if (devInfo) { + + // + // An explicit state transition can cause TPGs that were not specified + // in the parameter list to also change (this is not considered to be + // an implicit transition. It is SPC3 behavior and we must take + // this into consideration and update the devInfo states. + // This is an unfortunate side-effect in that the Admin may not get + // the paths to be in the exact states that he has set. + // + if (devInfo->State == DSM_DEV_ACTIVE_OPTIMIZED) { + + if (devInfo->ALUAState == DSM_DEV_ACTIVE_UNOPTIMIZED || + devInfo->ALUAState == DSM_DEV_STANDBY || + devInfo->ALUAState == DSM_DEV_UNAVAILABLE) { + + // + // An A/O TPG's devInfos can be masked as A/U. + // However, the reverse the is not true (ie. we can't + // mark a non-A/O TPG's devInfo(s) to be in A/O state. + // + devInfo->State = devInfo->ALUAState; + } + } + + // + // The devInfo->State has already been set. Update its previous state. + // + devInfo->PreviousState = devInfo->TempPreviousStateForLB; + } + } + + NT_ASSERT(jnx == numberDevInfoChanged); + } + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Failed to allocate targetPortGroupsInfo.\n", + DsmIds)); + + status = STATUS_INSUFFICIENT_RESOURCES; + } + } + + if (NT_SUCCESS(status)) { + + groupEntry->LoadBalanceType = loadBalancePolicy; + + if (loadBalancePolicy == DSM_LB_FAILOVER) { + + groupEntry->PreferredPath = preferredPath; + } + + savedLBSettings = DsmpCopyLoadBalancePolicies(groupEntry, + DsmWmiVersion, + supportedLBPolicies); + + } else { + + // + // Roll back to DeviceState to the state it was before + // processing this SetLB policy request + // + DsmpRestorePreviousDeviceState(supportedLBPolicies, DsmWmiVersion); + } + } + + if (NT_SUCCESS(status)) { + + // + // LUN's LB policy has been explicitly set by Admin + // + groupEntry->LBPolicySelection = DSM_DEFAULT_LB_POLICY_LUN_EXPLICIT; + + // + // Update the states and if appropriate, the path weight + // + DsmpUpdateDesiredStateAndWeight(groupEntry, + DsmWmiVersion, + supportedLBPolicies); + + // + // Update the next path to be used for the group + // + devInfo = DsmpGetActivePathToBeUsed(groupEntry, + DsmpIsSymmetricAccess(tempDevInfo), + SpecialHandlingFlag); + if (devInfo != NULL) { + + InterlockedExchangePointer(&(groupEntry->PathToBeUsed), (PVOID)devInfo->FailGroup); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): After setting LB policy No FOG available for group %p\n", + DsmIds, + groupEntry)); + + InterlockedExchangePointer(&(groupEntry->PathToBeUsed), NULL); + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + if (NT_SUCCESS(status) && savedLBSettings) { + + DsmpPersistLBSettings(savedLBSettings); + + DsmpFreePool(savedLBSettings); + } + +__Exit_DsmpSetLoadBalancePolicy: + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + ((PDsmSetLoadBalancePolicy_OUT)setLoadBalancePolicyOUT)->Status = status; + + } else { + + setLoadBalancePolicyOUT->Status = status; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSetLoadBalancePolicy (DsmIds %p): Exiting function with status 0x%x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpValidateSetLBPolicyInput( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds, + _In_ IN ULONG DsmWmiVersion, + _In_ IN PVOID SetLoadBalancePolicyIN, + _In_ IN ULONG InBufferSize + ) +/*++ + +Routine Description: + + This routine validates the input buffer given for setting + Load Balance policy + +Arguements: + + DsmContext - DSM Global Context + DsmIds - DSM Ids for the given device + DsmWmiVersion - version of the MPIO_DSM_Path class to use + SetLoadBalancePolicyIN - Describes the load balance policy to be set + InBufferSize - Number of bytes in SetLoadBalancePolicyIN + +Return Value: + + STATUS_SUCCESS - if the input buffer is well formed + Appropriate error status if the input buffer is malformed. + +--*/ +{ + PDSM_Load_Balance_Policy_V2 supportedLBPolicies; + PMPIO_DSM_Path_V2 dsmPath0; + PMPIO_DSM_Path_V2 dsmPath1; + NTSTATUS status = STATUS_SUCCESS; + ULONG inx; + ULONG jnx; + ULONG sizeNeeded; + KIRQL irql; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // Validate the input buffer for setting Load Balance policy + // + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + sizeNeeded = FIELD_OFFSET(DSM_Load_Balance_Policy_V2, DSM_Paths); + + } else { + + sizeNeeded = FIELD_OFFSET(DSM_Load_Balance_Policy, DSM_Paths); + } + + if (InBufferSize < sizeNeeded) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Insufficient buffer in SetLB. Expected %d, Given %d.\n", + DsmIds, + sizeNeeded, + InBufferSize)); + + status = STATUS_BUFFER_TOO_SMALL; + goto __Exit_DsmpValidateSetLBPolicyInput; + } + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + supportedLBPolicies = (PVOID)&(((PDsmSetLoadBalancePolicy_IN)SetLoadBalancePolicyIN)->LoadBalancePolicy); + + sizeNeeded += supportedLBPolicies->DSMPathCount * sizeof(MPIO_DSM_Path); + + } else { + + supportedLBPolicies = &(((PDsmSetLoadBalancePolicyALUA_IN)SetLoadBalancePolicyIN)->LoadBalancePolicy); + + sizeNeeded += supportedLBPolicies->DSMPathCount * sizeof(MPIO_DSM_Path_V2); + } + + if (InBufferSize < sizeNeeded) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Insufficient buffer in SetLB. Expected %d, Given %d.\n", + DsmIds, + sizeNeeded, + InBufferSize)); + + status = STATUS_BUFFER_TOO_SMALL; + goto __Exit_DsmpValidateSetLBPolicyInput; + } + + if (supportedLBPolicies->Version > DSM_WMI_VERSION) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): WMI Version mismatch. Expected %d, Given %d.\n", + DsmIds, + DSM_WMI_VERSION, + supportedLBPolicies->Version)); + + status = DSM_UNSUPPORTED_VERSION; + goto __Exit_DsmpValidateSetLBPolicyInput; + + } else if (supportedLBPolicies->Version < DSM_WMI_VERSION) { + + ULONG dsmWmiVersion = DSM_WMI_VERSION; + TracePrint((TRACE_LEVEL_WARNING, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Use of older management app (WMI-Version %x) with newer DSM (WMI-Version %x).\n", + DsmIds, + supportedLBPolicies->Version, + dsmWmiVersion)); + + NT_ASSERT(supportedLBPolicies->Version == DSM_WMI_VERSION); + } + + if ((supportedLBPolicies->LoadBalancePolicy < DSM_LB_FAILOVER) || + (supportedLBPolicies->LoadBalancePolicy > DSM_LB_LEAST_BLOCKS)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Invalid LB Policy %d.\n", + DsmIds, + supportedLBPolicies->LoadBalancePolicy)); + + status = DSM_INVALID_LOAD_BALANCE_POLICY; + goto __Exit_DsmpValidateSetLBPolicyInput; + } + + // + // It is expected that the user provide LB policy settings + // for all the paths and not just a subset of the paths. + // + if (supportedLBPolicies->DSMPathCount != DsmIds->Count) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Path Count %d not equal to DSM IDs count %d.\n", + DsmIds, + supportedLBPolicies->DSMPathCount, + DsmIds->Count)); + + status = STATUS_INVALID_PARAMETER; + goto __Exit_DsmpValidateSetLBPolicyInput; + } + + // + // Make sure user did not provide duplicate path ids + // + for (inx = 0; inx < supportedLBPolicies->DSMPathCount && NT_SUCCESS(status); inx++) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath0 = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[inx]); + + } else { + + dsmPath0 = &(supportedLBPolicies->DSM_Paths[inx]); + } + + dsmPath0->Reserved = 0; + + for (jnx = 0; jnx < supportedLBPolicies->DSMPathCount; jnx++) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath1 = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[jnx]); + + } else { + + dsmPath1 = &(supportedLBPolicies->DSM_Paths[jnx]); + } + + if ((inx != jnx) && + ((dsmPath0->DsmPathId == dsmPath1->DsmPathId) && (dsmPath1->DsmPathId != 0))) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Duplicate path id %I64x at %d and %d.\n", + DsmIds, + dsmPath0->DsmPathId, + inx, + jnx)); + + status = STATUS_INVALID_PARAMETER; + + break; + } + } + } + + if (NT_SUCCESS(status)) { + + PDSM_DEVICE_INFO devInfo; + PDSM_FAILOVER_GROUP foGroup; + PVOID pathId; + BOOLEAN foundPath; + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + // + // Make sure the user has provided path id corresponding + // to all the DSM IDs given to us. + // + for (inx = 0; inx < DsmIds->Count; inx++) { + + devInfo = DsmIds->IdList[inx]; + + if (!DsmpIsDeviceInitialized(devInfo)) { + + continue; + } + + foGroup = devInfo->FailGroup; + if (!foGroup) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): FO Group NULL for %p at index %d.\n", + DsmIds, + devInfo, + inx)); + + status = STATUS_INVALID_PARAMETER; + + break; + } + + foundPath = FALSE; + + for (jnx = 0; jnx < supportedLBPolicies->DSMPathCount; jnx++) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath0 = (PVOID)&(((PDSM_Load_Balance_Policy)supportedLBPolicies)->DSM_Paths[jnx]); + + } else { + + dsmPath0 = &(supportedLBPolicies->DSM_Paths[jnx]); + } + + pathId = (PVOID) dsmPath0->DsmPathId; + if (foGroup->PathId == pathId) { + + // + // Found the device info corresponding to the given path. + // Use the reserved field in MPIO_DSM_Path to store + // the pointer to the device info. Device Info is used + // later on to set the load balance policy for the device. + // + foundPath = TRUE; + + dsmPath0->Reserved = (ULONG_PTR) devInfo; + + // + // If ALUA, RoundRobin is not an allowed LB policy since not all paths can + // be in A/O state. RRWS must be used instead. + // + if (supportedLBPolicies->LoadBalancePolicy == DSM_LB_ROUND_ROBIN && !DsmpIsSymmetricAccess(devInfo)) { + + status = DSM_INVALID_LOAD_BALANCE_POLICY; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Invalid LB policy for ALUA. Status %x.\n", + DsmIds, + status)); + } + + break; + } + } + + if (!foundPath) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Failed to find path %p for %p at index %d.\n", + DsmIds, + foGroup->PathId, + devInfo, + inx)); + + status = STATUS_INVALID_PARAMETER; + + break; + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + } + +__Exit_DsmpValidateSetLBPolicyInput: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpValidateSetLBPolicyInput (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +VOID +DsmpSaveDeviceState( + _In_ IN PVOID SupportedLBPolicies, + _In_ IN ULONG DsmWmiVersion + ) +/*+++ + +Routine Description: + + This routine saves the current Load Balance policy settings. + If there is any error while setting the new policy given + by the user, the saved values will be used to restore + the old state. + + Note: This routine MUST be called with DsmContextLock held in Exclusive mode. + +Arguements: + + SupportedLBPolicies - New Load Balance policy values + DsmWmiVersion - version of the MPIO_DSM_Path class to use + +Return Value: + + None +--*/ +{ + PDSM_DEVICE_INFO devInfo; + PMPIO_DSM_Path_V2 dsmPath; + ULONG inx; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSaveDeviceState (LBP %p): Entering function.\n", + SupportedLBPolicies)); + + inx = 0; + + while (inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]); + + } else { + + dsmPath = &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]); + } + + devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; + + if (devInfo) { + + devInfo->TempPreviousStateForLB = devInfo->State; + } + + inx++; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpSaveDeviceState (LBP %p): Exiting function.\n", + SupportedLBPolicies)); + + return; +} + + +VOID +DsmpRestorePreviousDeviceState( + _In_ IN PVOID SupportedLBPolicies, + _In_ IN ULONG DsmWmiVersion + ) +/*++ + +Routine Description: + + This routine restores the old Load Balance policy settings. + If there is any error while setting the new policy given + by the user, the old state is restored from the saved state. + + Note: This routine MUST be called with DsmContextLock held in Exclusive mode. + +Arguements: + + SupportedLBPolicies - New Load Balance policy values + DsmWmiVersion - version of the MPIO_DSM_Path class to use + +Return Value: + + None +--*/ +{ + PDSM_DEVICE_INFO devInfo; + PMPIO_DSM_Path_V2 dsmPath; + ULONG inx; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpRestorePreviousDeviceState (LBP %p): Entering function.\n", + SupportedLBPolicies)); + + inx = 0; + + while (inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]); + + } else { + + dsmPath = &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]); + } + + devInfo = (PDSM_DEVICE_INFO)dsmPath->Reserved; + + if (devInfo) { + + devInfo->State = devInfo->TempPreviousStateForLB; + } + + inx++; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpRestorePreviousDeviceState (LBP %p): Exiting function.\n", + SupportedLBPolicies)); + + return; +} + + +VOID +DsmpUpdateDesiredStateAndWeight( + _In_ IN PDSM_GROUP_ENTRY Group, + _In_ IN ULONG DsmWmiVersion, + _In_ IN PVOID SupportedLBPolicies + ) +/*++ + +Routine Description: + + This routine updates the desired state and path weights + based on admin's LB selection. + + Note: This routine MUST be called with DsmContextLock held in Exclusive mode. + +Arguements: + + Group - The group entry correponding to the pseudo-LUN. + SupportedLBPolicies - New Load Balance policy values + DsmWmiVersion - version of the MPIO_DSM_Path class to use + +Return Value: + + None +--*/ +{ + PMPIO_DSM_Path_V2 dsmPath; + PDSM_DEVICE_INFO devInfo; + ULONG inx; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpUpdatedDesiredState (Group %p): Entering function.\n", + Group)); + + inx = 0; + while (inx < ((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSMPathCount) { + + if (DsmWmiVersion == DSM_WMI_VERSION_1) { + + dsmPath = (PVOID)&(((PDSM_Load_Balance_Policy)SupportedLBPolicies)->DSM_Paths[inx]); + + } else { + + dsmPath = &(((PDSM_Load_Balance_Policy_V2)SupportedLBPolicies)->DSM_Paths[inx]); + } + + devInfo = (PDSM_DEVICE_INFO) dsmPath->Reserved; + + if (!devInfo) { + + inx++; + continue; + } + + DSM_ASSERT(devInfo->DeviceSig == DSM_DEVICE_SIG); + NT_ASSERT(devInfo->Group == Group); + + // + // We'll honor the chosen path for FOO for ALUA storage + // since we know for a fact that the Admin has chosen the path. + // We'll also honor path state in RRWS if it is different from TPG state + // as that too is an indication that it was explicitly selected. + // + if ((DsmpIsSymmetricAccess(devInfo)) || + (Group->LoadBalanceType == DSM_LB_FAILOVER) || + (!DsmpIsSymmetricAccess(devInfo) && Group->LoadBalanceType == DSM_LB_ROUND_ROBIN_WITH_SUBSET && devInfo->State != devInfo->ALUAState)) { + + // + // Check if this is the primary path or a standby path + // + if (dsmPath->PrimaryPath) { + + devInfo->DesiredState = DSM_DEV_ACTIVE_OPTIMIZED; + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + if (!dsmPath->OptimizedPath) { + + devInfo->DesiredState = DSM_DEV_ACTIVE_UNOPTIMIZED; + } + } + + } else { + + devInfo->DesiredState = DSM_DEV_STANDBY; + + if (DsmWmiVersion > DSM_WMI_VERSION_1) { + + if (!dsmPath->OptimizedPath) { + + devInfo->DesiredState = DSM_DEV_UNAVAILABLE; + } + } + } + } else { + + devInfo->DesiredState = DSM_DEV_UNDETERMINED; + } + + if (Group->LoadBalanceType == DSM_LB_WEIGHTED_PATHS) { + + devInfo->PathWeight = dsmPath->PathWeight; + } + + inx++; + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpUpdatedDesiredState (Group %p): Exiting function.\n", + Group)); + + return; +} + + +NTSTATUS +DsmpQueryDevicePerf( + _In_ PDSM_CONTEXT DsmContext, + _In_ PDSM_IDS DsmIds, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ) +/*++ + +Routine Description: + + This routine returns the perf counters for each path for the + device that corresponds to the passed in DsmIds. + +Arguements: + + DsmContext - Global DSM context + DsmIds - DSM Ids for the given device + InBufferSize - Size of the input buffer + OutBufferSize - Size of the output buffer + Buffer - Buffer in which the current Load Balance policy settings + is returned, if the buffer is big enough + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PDSM_DEVICE_INFO devInfo; + ULONG sizeNeeded; + PMSDSM_DEVICE_PERF devicePerf; + ULONG i; + PMSDSM_DEVICEPATH_PERF pathPerf; + KIRQL irql; + + UNREFERENCED_PARAMETER(InBufferSize); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryDevicePerf (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // At least one device should be given + // + if (DsmIds->Count == 0) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryDevicePerf (DsmIds %p): No DSM Ids given.\n", + DsmIds)); + + *OutBufferSize = 0; + status = STATUS_INVALID_PARAMETER; + + goto __Exit_DsmpQueryDevicePerf; + } + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(MSDSM_DEVICE_PERF, PerfInfo)); + sizeNeeded += (DsmIds->Count * sizeof(MSDSM_DEVICEPATH_PERF)); + + if (*OutBufferSize < sizeNeeded) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryDevicePerf (DsmIds %p): Output buffer too small for QueryLBPolicy.\n", + DsmIds)); + + *OutBufferSize = sizeNeeded; + status = STATUS_BUFFER_TOO_SMALL; + + goto __Exit_DsmpQueryDevicePerf; + } + + // + // Zero out the output buffer first + // + RtlZeroMemory(Buffer, sizeNeeded); + +#if DBG + devInfo = DsmIds->IdList[0]; + DSM_ASSERT(devInfo); + DSM_ASSERT(devInfo->DeviceSig == DSM_DEVICE_SIG); +#endif + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + devicePerf = (PMSDSM_DEVICE_PERF)Buffer; + devicePerf->NumberPaths = DsmIds->Count; + + // + // For each path, get the stats info + // + for (i = 0; i < DsmIds->Count; i++) { + + pathPerf = &devicePerf->PerfInfo[i]; + devInfo = DsmIds->IdList[i]; + + if (DsmpIsDeviceInitialized(devInfo)) { + + pathPerf->PathId = (ULONGLONG)((ULONG_PTR)((devInfo->FailGroup)->PathId)); + pathPerf->NumberReads = (devInfo->DeviceStats).NumberReads; + pathPerf->NumberWrites = (devInfo->DeviceStats).NumberWrites; + pathPerf->BytesRead = (devInfo->DeviceStats).BytesRead; + pathPerf->BytesWritten = (devInfo->DeviceStats).BytesWritten; + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + + *OutBufferSize = sizeNeeded; + +__Exit_DsmpQueryDevicePerf: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryDevicePerf (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpClearPerfCounters( + _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PDSM_IDS DsmIds + ) +/*++ + +Routine Description: + + This routine clears the perf counters for each path for the + device that corresponds to the passed in DsmIds. + +Arguements: + + DsmContext - Global DSM context + DsmIds - DSM Ids for the given device + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + NTSTATUS status = STATUS_SUCCESS; + PDSM_DEVICE_INFO devInfo; + KIRQL irql; + ULONG i; + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpClearPerfCounters (DsmIds %p): Entering function.\n", + DsmIds)); + + // + // At least one device should be given + // + if (DsmIds->Count == 0) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpClearPerfCounters (DsmIds %p): No DSM Ids given.\n", + DsmIds)); + + status = STATUS_INVALID_PARAMETER; + + goto __Exit_DsmpClearPerfCounters; + } + + irql = ExAcquireSpinLockExclusive(&(DsmContext->DsmContextLock)); + + for (i = 0; i < DsmIds->Count; i++) { + + devInfo = DsmIds->IdList[i]; + DSM_ASSERT(devInfo); + DSM_ASSERT(devInfo->DeviceSig == DSM_DEVICE_SIG); + + if (devInfo) { + (devInfo->DeviceStats).BytesRead = 0; + (devInfo->DeviceStats).BytesWritten = 0; + (devInfo->DeviceStats).NumberReads = 0; + (devInfo->DeviceStats).NumberWrites = 0; + } + } + + ExReleaseSpinLockExclusive(&(DsmContext->DsmContextLock), irql); + +__Exit_DsmpClearPerfCounters: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpClearPerfCounters (DsmIds %p): Exiting function with status %x.\n", + DsmIds, + status)); + + return status; +} + + +NTSTATUS +DsmpQuerySupportedDevicesList( + _In_ PDSM_CONTEXT DsmContext, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ) +/*++ + +Routine Description: + + This routine returns the list of devices that are supported by MSDSM. + +Arguements: + + DsmContext - Global DSM context + InBufferSize - Size of the input buffer + OutBufferSize - Size of the output buffer + Buffer - Buffer in which the current Load Balance policy settings + is returned, if the buffer is big enough + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + NTSTATUS status; + ULONG sizeNeeded; + PMSDSM_SUPPORTED_DEVICES_LIST supportedDeviceIds; + PWSTR szIndex; + PWSTR deviceIdIndex; + ULONG numberDeviceIds = 0; + ULONG index = 0; + KIRQL oldIrql; + PWSTR tempBuffer = NULL; + + UNREFERENCED_PARAMETER(InBufferSize); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQuerySupportedDevicesList (DsmContext %p): Entering function.\n", + DsmContext)); + + // + // It is possible that manually changes to the registry weren't yet picked up, + // so query for the list in its current state. Failure to get this list is not + // fatal, so ignore errors. + // +#if DBG + status = DsmpGetDeviceList(DsmContext); + NT_ASSERT(NT_SUCCESS(status)); +#else + DsmpGetDeviceList(DsmContext); +#endif + + // + // Since it is possible that this list may change if a new device arrival + // gets processed at the same time as this query being processed, we need + // to protect it. + // + KeAcquireSpinLock(&DsmContext->SupportedDevicesListLock, &oldIrql); + + tempBuffer = DsmpAllocatePool(NonPagedPoolNx, DsmContext->SupportedDevices.MaximumLength, DSM_TAG_REG_VALUE_RELATED); + + if (tempBuffer) { + + RtlCopyMemory(tempBuffer, DsmContext->SupportedDevices.Buffer, DsmContext->SupportedDevices.Length); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQuerySupportedDevicesList (DsmContext %p): Failed to allocate temporary list.\n", + DsmContext)); + + status = STATUS_INSUFFICIENT_RESOURCES; + KeReleaseSpinLock(&DsmContext->SupportedDevicesListLock, oldIrql); + + goto __Exit_DsmpQuerySupportedDevicesList; + } + + KeReleaseSpinLock(&DsmContext->SupportedDevicesListLock, oldIrql); + + status = STATUS_SUCCESS; + szIndex = tempBuffer; + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(MSDSM_SUPPORTED_DEVICES_LIST, DeviceId)); + + if (szIndex) { + + while (*szIndex) { + + szIndex += wcslen(szIndex) + 1; + numberDeviceIds++; + } + + sizeNeeded += numberDeviceIds * (MSDSM_MAX_DEVICE_ID_SIZE + sizeof(WNULL)); + } + + if (*OutBufferSize < sizeNeeded) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQuerySupportedDevicesList (DsmContext %p): Output buffer too small for QuerySupportedDevicesList.\n", + DsmContext)); + + *OutBufferSize = sizeNeeded; + status = STATUS_BUFFER_TOO_SMALL; + + goto __Exit_DsmpQuerySupportedDevicesList; + } + + // + // Zero out the output buffer first + // + RtlZeroMemory(Buffer, sizeNeeded); + + *OutBufferSize = sizeNeeded; + + supportedDeviceIds = (PMSDSM_SUPPORTED_DEVICES_LIST)Buffer; + supportedDeviceIds->NumberDevices = numberDeviceIds; + + for (index = 0, szIndex = tempBuffer, deviceIdIndex = supportedDeviceIds->DeviceId; + index < numberDeviceIds; + index++, szIndex += wcslen(szIndex) + 1, deviceIdIndex += MSDSM_MAX_DEVICE_ID_LENGTH) { + + *((PUSHORT)deviceIdIndex) = MSDSM_MAX_DEVICE_ID_SIZE; + deviceIdIndex++; + + RtlStringCchCopyW(deviceIdIndex, + MSDSM_MAX_DEVICE_ID_LENGTH - 1, + szIndex); + } + +__Exit_DsmpQuerySupportedDevicesList: + + if (tempBuffer) { + DsmpFreePool(tempBuffer); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQuerySupportedDevicesList (DsmContext %p): Exiting function with status %x.\n", + DsmContext, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryTargetsDefaultPolicy( + _In_ PDSM_CONTEXT DsmContext, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ) +/*++ + +Routine Description: + + This routine is used to build the target list (for which the override default LB policy + was explicitly set), by querying the services key for the subkeys under + "msdsm\Parameters\DsmTargetsLoadBalanceSetting" + +Arguements: + + Context - The DSM Context value. It contains storage for the target hardware ids and their + default policy info. + InBufferSize - Size of the input buffer + OutBufferSize - Size of the output buffer + Buffer - Buffer in which the current targets whose default policy settings is returned, if the buffer is big enough + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + ULONG sizeNeeded; + PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY targetsPolicyInfo = (PMSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY)Buffer; + PMSDSM_TARGET_DEFAULT_POLICY_INFO targetPolicyInfo; + HANDLE targetsLBSettingKey = NULL; + NTSTATUS status; + PKEY_FULL_INFORMATION keyFullInfo = NULL; + ULONG length = sizeof(KEY_FULL_INFORMATION); + ULONG numSubKeys = 0; + WCHAR vidPid[25] = {0}; + PKEY_BASIC_INFORMATION keyBasicInfo = NULL; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE targetKey = NULL; + ULONG index = 0; + RTL_QUERY_REGISTRY_TABLE queryTable[2]; + DSM_LOAD_BALANCE_TYPE loadBalanceType; + ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + PWCHAR policyInfoIndex; + UNICODE_STRING keyValueName; + PKEY_VALUE_PARTIAL_INFORMATION keyValueInfo = NULL; + + UNREFERENCED_PARAMETER(InBufferSize); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Entering function.\n", + DsmContext)); + + status = DsmpOpenTargetsLoadBalanceSettingKey(KEY_ALL_ACCESS, &targetsLBSettingKey); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to open Targets LB Setting key. Status %x.\n", + DsmContext, + status)); + + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + // + // Query for number of subkeys + // + do { + if (keyFullInfo) { + + DsmpFreePool(keyFullInfo); + } + + keyFullInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); + + if (!keyFullInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to allocate resources for key full info.\n", + DsmContext)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + status = ZwQueryKey(targetsLBSettingKey, + KeyFullInformation, + keyFullInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to query key. Status %x.\n", + DsmContext, + status)); + + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + // + // Calculate total buffer size required + // + numSubKeys = keyFullInfo->SubKeys; + + sizeNeeded = AlignOn8Bytes(FIELD_OFFSET(MSDSM_TARGETS_DEFAULT_LOAD_BALANCE_POLICY, TargetDefaultPolicyInfo)); + sizeNeeded += numSubKeys * sizeof(MSDSM_TARGET_DEFAULT_POLICY_INFO); + + if (*OutBufferSize < sizeNeeded) { + + *OutBufferSize = sizeNeeded; + status = STATUS_BUFFER_TOO_SMALL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Buffer insufficient. Status %x.\n", + DsmContext, + status)); + + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + *OutBufferSize = sizeNeeded; + RtlZeroMemory(Buffer, *OutBufferSize); + + targetsPolicyInfo->NumberDevices = numSubKeys; + targetPolicyInfo = targetsPolicyInfo->TargetDefaultPolicyInfo; + + // + // Now Enumerate all of the subkeys + // + for(index = 0; index < numSubKeys && NT_SUCCESS(status); index++) { + + UNICODE_STRING targetName; + + if (targetKey) { + ZwClose(targetKey); + targetKey = NULL; + } + + length = sizeof(KEY_BASIC_INFORMATION); + + do { + if (keyBasicInfo) { + + DsmpFreePool(keyBasicInfo); + } + + keyBasicInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, + length, + DSM_TAG_REG_KEY_RELATED); + + if (!keyBasicInfo) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to allocate resources for key basic info.\n", + DsmContext)); + + status = STATUS_INSUFFICIENT_RESOURCES; + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + // + // Enumerate the index'th subkey + // + status = ZwEnumerateKey(targetsLBSettingKey, + index, + KeyBasicInformation, + keyBasicInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + // + // Ignore errors - this is a best case effort. + // + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to enumerate sub key's info. Status %x.\n", + DsmContext, + status)); + + status = STATUS_SUCCESS; + continue; + } + + RtlZeroMemory(vidPid, sizeof(vidPid)); + RtlStringCbCopyNW(vidPid, sizeof(vidPid), keyBasicInfo->Name, keyBasicInfo->NameLength); + RtlInitUnicodeString(&targetName, vidPid); + + // + // Open a handle to the the target subkey. + // + InitializeObjectAttributes(&objectAttributes, + &targetName, + (OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE), + targetsLBSettingKey, + (PSECURITY_DESCRIPTOR) NULL); + + status = ZwOpenKey(&targetKey, + KEY_ALL_ACCESS, + &objectAttributes); + + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to open reg key %ws. Status %x.\n", + DsmContext, + vidPid, + status)); + + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + RtlZeroMemory(queryTable, sizeof(queryTable)); + + queryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_TYPECHECK; + queryTable[0].Name = DSM_LOAD_BALANCE_POLICY; + queryTable[0].EntryContext = &loadBalanceType; + queryTable[0].DefaultType = (REG_DWORD << RTL_QUERY_REGISTRY_TYPECHECK_SHIFT) | REG_NONE; + + status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, + targetKey, + queryTable, + targetKey, + NULL); + if (!NT_SUCCESS(status)) { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to query LB Policy for %ws - error %x.\n", + DsmContext, + vidPid, + status)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): LB Policy for %ws is %d.\n", + DsmContext, + vidPid, + loadBalanceType)); + + RtlInitUnicodeString(&keyValueName, DSM_PREFERRED_PATH); + + length = sizeof(KEY_VALUE_PARTIAL_INFORMATION); + + do { + DsmpFreePool(keyValueInfo); + keyValueInfo = DsmpAllocatePool(NonPagedPoolNxCacheAligned, length, DSM_TAG_REG_KEY_RELATED); + if (!keyValueInfo) { + + status = STATUS_INSUFFICIENT_RESOURCES; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to allocate resources for keyValueInfo (PP). Status %x.\n", + DsmContext, + status)); + + goto __Exit_DsmpQueryTargetsDefaultPolicy; + } + + status = ZwQueryValueKey(targetKey, + &keyValueName, + KeyValuePartialInformation, + keyValueInfo, + length, + &length); + + } while (status == STATUS_BUFFER_TOO_SMALL || status == STATUS_BUFFER_OVERFLOW); + + if (NT_SUCCESS(status)) { + + NT_ASSERT(keyValueInfo->DataLength == sizeof(ULONGLONG)); + + preferredPath = *((ULONGLONG UNALIGNED *)keyValueInfo->Data); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): PreferredPath for %ws is %I64x.\n", + DsmContext, + vidPid, + preferredPath)); + + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Failed to query PreferredPath for %ws. Status %x.\n", + DsmContext, + vidPid, + status)); + } + + // + // Copy over this target's policy info. + // + policyInfoIndex = targetPolicyInfo->HardwareId; + *((PUSHORT)policyInfoIndex) = MSDSM_MAX_DEVICE_ID_SIZE; + policyInfoIndex++; + RtlStringCchCopyW((PWSTR)policyInfoIndex, MSDSM_MAX_DEVICE_ID_LENGTH - 1, vidPid); + targetPolicyInfo->LoadBalancePolicy = loadBalanceType; + targetPolicyInfo->PreferredPath = preferredPath; + + targetPolicyInfo++; + } + } + +__Exit_DsmpQueryTargetsDefaultPolicy: + + if (targetKey) { + ZwClose(targetKey); + } + + if (targetsLBSettingKey) { + ZwClose(targetsLBSettingKey); + } + + if (keyBasicInfo) { + DsmpFreePool(keyBasicInfo); + } + + if (keyValueInfo) { + DsmpFreePool(keyValueInfo); + } + + if (keyFullInfo) { + DsmpFreePool(keyFullInfo); + } + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryTargetsDefaultPolicy (Context %p): Exiting function with status %x.\n", + DsmContext, + status)); + + return status; +} + + +NTSTATUS +DsmpQueryDsmDefaultPolicy( + _In_ PDSM_CONTEXT DsmContext, + _In_ ULONG InBufferSize, + _Inout_ PULONG OutBufferSize, + _Out_writes_to_(*OutBufferSize, *OutBufferSize) PUCHAR Buffer + ) +/*++ + +Routine Description: + + This routine is used to return the override MSDSM-wide default LB policy + if it was explicitly set, by querying the services key at "msdsm\Parameters" + +Arguements: + + Context - The DSM Context value. It contains storage for the target hardware ids and their + default policy info. + InBufferSize - Size of the input buffer + OutBufferSize - Size of the output buffer + Buffer - Buffer in which the current MSDSM-wide default policy is returned, if the buffer + is big enough + +Return Value: + + STATUS_SUCCESS on success + Appropriate error code on error. + +--*/ +{ + PMSDSM_DEFAULT_LOAD_BALANCE_POLICY dsmPolicyInfo = (PMSDSM_DEFAULT_LOAD_BALANCE_POLICY)Buffer; + NTSTATUS status; + DSM_LOAD_BALANCE_TYPE loadBalanceType; + ULONGLONG preferredPath = (ULONGLONG)((ULONG_PTR)MAXULONG); + + UNREFERENCED_PARAMETER(InBufferSize); + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryDsmDefaultPolicy (Context %p): Entering function.\n", + DsmContext)); + + if (*OutBufferSize < sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY)) { + + *OutBufferSize = sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY); + status = STATUS_BUFFER_TOO_SMALL; + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryDsmDefaultPolicy (Context %p): Buffer insufficient. Status %x.\n", + DsmContext, + status)); + + goto __Exit_DsmpQueryDsmDefaultPolicy; + } + + *OutBufferSize = sizeof(MSDSM_DEFAULT_LOAD_BALANCE_POLICY); + RtlZeroMemory(Buffer, *OutBufferSize); + + status = DsmpQueryDsmLBPolicyFromRegistry(&loadBalanceType, &preferredPath); + + if (NT_SUCCESS(status)) { + + dsmPolicyInfo->LoadBalancePolicy = loadBalanceType; + dsmPolicyInfo->PreferredPath = (ULONGLONG)((ULONG_PTR)preferredPath); + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryDsmDefaultPolicy (Context %p): LB policy = %u, Preferred path = %I64x.\n", + DsmContext, + dsmPolicyInfo->LoadBalancePolicy, + dsmPolicyInfo->PreferredPath)); + } else { + + TracePrint((TRACE_LEVEL_ERROR, + TRACE_FLAG_WMI, + "DsmpQueryDsmDefaultPolicy (Context %p): Query for MSDSM-wide policy, status %x.\n", + DsmContext, + status)); + } + +__Exit_DsmpQueryDsmDefaultPolicy: + + TracePrint((TRACE_LEVEL_VERBOSE, + TRACE_FLAG_WMI, + "DsmpQueryDsmDefaultPolicy (Context %p): Exiting function with status %x.\n", + DsmContext, + status)); + + return status; +} + diff --git a/tests/projects/windows/driver/wdm/msdsm/xmake.lua b/tests/projects/windows/driver/wdm/msdsm/xmake.lua new file mode 100644 index 000000000..3c68aa1b8 --- /dev/null +++ b/tests/projects/windows/driver/wdm/msdsm/xmake.lua @@ -0,0 +1,15 @@ +add_rules("mode.debug", "mode.release") + +target("sampledsm") + add_rules("wdk.env.wdm", "wdk.driver") + add_values("wdk.tracewpp.flags", "-func:TracePrint((LEVEL,FLAGS,MSG,...))") + add_files("*.c", {rule = "wdk.tracewpp"}) + add_files("*.rc", "*.inf") + add_files("*.mof|msdsm.mof") + + -- add file msdsm.mof and modify default wdk.mof.header for this file + add_files("msdsm.mof", {values = {wdk_mof_header = "msdsmwmi.h"}}) + + set_pcheader("precomp.h") + add_links("mpio") + diff --git a/tests/projects/windows/driver/wdm/perfcounters/kcs.c b/tests/projects/windows/driver/wdm/perfcounters/kcs.c new file mode 100644 index 000000000..9996addcb --- /dev/null +++ b/tests/projects/windows/driver/wdm/perfcounters/kcs.c @@ -0,0 +1,407 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + kcs.c + +Abstract: + + This module contains sample code to demonstrate how to provide + counter data from a kernel driver. + +Environment: + + Kernel mode only. + +--*/ + + +#include +#include "kcs.h" +#include "kcsCounters.h" + +#pragma code_seg("PAGE") + +DRIVER_INITIALIZE DriverEntry; +DRIVER_UNLOAD KcsUnload; + +NTSTATUS +KcsAddGeometricInstance ( + _In_ PPCW_BUFFER Buffer, + _In_ PCWSTR Name, + _In_ ULONG MinimalValue, + _In_ ULONG Amplitude + ) + +/*++ + +Routine Description: + + This utility function adds instance to the callback buffer. + +Arguments: + + Buffer - Data will be returned in this buffer. + + Name - Name of instances to be added. + + MinimalValue - Minimum value of the wave. + + Amplitude - Amplitude of the wave. + +Return Value: + + NTSTATUS indicating if the function succeeded. + +--*/ + +{ + ULONG Index; + LARGE_INTEGER Timestamp; + UNICODE_STRING UnicodeName; + GEOMETRIC_WAVE_VALUES Values; + + PAGED_CODE(); + + KeQuerySystemTime(&Timestamp); + + Index = (Timestamp.QuadPart / 10000000) % 10; + + Values.Triangle = MinimalValue + Amplitude * abs(5 - Index) / 5; + Values.Square = MinimalValue + Amplitude * (Index < 5); + + RtlInitUnicodeString(&UnicodeName, Name); + + return KcsAddGeometricWave(Buffer, &UnicodeName, 0, &Values); +} + +NTSTATUS NTAPI +KcsGeometricWaveCallback ( + _In_ PCW_CALLBACK_TYPE Type, + _In_ PPCW_CALLBACK_INFORMATION Info, + _In_opt_ PVOID Context + ) + +/*++ + +Routine Description: + + This function returns the list of counter instances and counter data. + +Arguments: + + Type - Request type. + + Info - Buffer for returned data. + + Context - Not used. + +Return Value: + + NTSTATUS indicating if the function succeeded. + +--*/ + +{ + NTSTATUS Status; + UNICODE_STRING UnicodeName; + + UNREFERENCED_PARAMETER(Context); + + PAGED_CODE(); + + switch (Type) { + case PcwCallbackEnumerateInstances: + + // + // Instances are being enumerated, so we add them without values. + // + + RtlInitUnicodeString(&UnicodeName, L"Small Wave"); + Status = KcsAddGeometricWave(Info->EnumerateInstances.Buffer, + &UnicodeName, + 0, + NULL); + if (!NT_SUCCESS(Status)) { + return Status; + } + + RtlInitUnicodeString(&UnicodeName, L"Medium Wave"); + Status = KcsAddGeometricWave(Info->EnumerateInstances.Buffer, + &UnicodeName, + 0, + NULL); + if (!NT_SUCCESS(Status)) { + return Status; + } + + RtlInitUnicodeString(&UnicodeName, L"Large Wave"); + Status = KcsAddGeometricWave(Info->EnumerateInstances.Buffer, + &UnicodeName, + 0, + NULL); + if (!NT_SUCCESS(Status)) { + return Status; + } + + break; + + case PcwCallbackCollectData: + + // + // Add values for 3 instances of Geometric Wave Counter Set. + // + + Status = KcsAddGeometricInstance(Info->CollectData.Buffer, + L"Small Wave", + 40, + 20); + if (!NT_SUCCESS(Status)) { + return Status; + } + + Status = KcsAddGeometricInstance(Info->CollectData.Buffer, + L"Medium Wave", + 30, + 40); + if (!NT_SUCCESS(Status)) { + return Status; + } + + Status = KcsAddGeometricInstance(Info->CollectData.Buffer, + L"Large Wave", + 20, + 60); + if (!NT_SUCCESS(Status)) { + return Status; + } + + break; + } + + return STATUS_SUCCESS; +} + +NTSTATUS +KcsAddTrignometricInstance ( + _In_ PPCW_BUFFER Buffer, + _In_ PCWSTR Name, + _In_ ULONG MinimalValue, + _In_ ULONG Amplitude + ) + +/*++ + +Routine Description: + + This utility function adds instance to the callback buffer. + +Arguments: + + Buffer - Data will be returned in this buffer. + + Name - Name of instances to be added. + + MinimalValue - Minimum value of the wave. + + Amplitude - Amplitude of the wave. + +Return Value: + + NTSTATUS indicating if the function succeeded. + +--*/ + +{ + double Angle; + KFLOATING_SAVE FloatSave; + NTSTATUS Status; + LARGE_INTEGER Timestamp; + UNICODE_STRING UnicodeName; + TRIGNOMETRIC_WAVE_VALUES Values; + + PAGED_CODE(); + + Status = KeSaveFloatingPointState(&FloatSave); + if (!NT_SUCCESS(Status)) { + return Status; + } + + KeQuerySystemTime(&Timestamp); + + Angle = (double)(Timestamp.QuadPart / 400000) * (22/7) / 180; + + Values.Constant = MinimalValue; + Values.Cosine = (ULONG)(MinimalValue + Amplitude * cos(Angle)); + Values.Sine = (ULONG)(MinimalValue + Amplitude * sin(Angle)); + + KeRestoreFloatingPointState(&FloatSave); + + // + // Add instance name & values to the caller's buffer. + // + + RtlInitUnicodeString(&UnicodeName, Name); + + return KcsAddTrignometricWave(Buffer, &UnicodeName, 0, &Values); +} + +NTSTATUS NTAPI +KcsTrignometricWaveCallback ( + _In_ PCW_CALLBACK_TYPE Type, + _In_ PPCW_CALLBACK_INFORMATION Info, + _In_opt_ PVOID Context + ) + +/*++ + +Routine Description: + + This function returns the list of counter instances and counter data. + +Arguments: + + Type - Request type. + + Info - Buffer for returned data. + + Context - Not used. + +Return Value: + + NTSTATUS indicating if the function succeeded. + +--*/ + +{ + NTSTATUS Status; + UNICODE_STRING UnicodeName; + + UNREFERENCED_PARAMETER(Context); + + PAGED_CODE(); + + switch (Type) { + case PcwCallbackEnumerateInstances: + RtlInitUnicodeString(&UnicodeName, L"default"); + Status = KcsAddTrignometricWave(Info->EnumerateInstances.Buffer, + &UnicodeName, + 0, + NULL); + if (!NT_SUCCESS(Status)) { + return Status; + } + + break; + + case PcwCallbackCollectData: + + // + // Add values for Single Instance of Trignometirc Wave Counter Set. + // + + return KcsAddTrignometricInstance(Info->CollectData.Buffer, + L"default", + 50, + 30); + } + + return STATUS_SUCCESS; +} + +VOID +KcsUnload ( + _In_ PDRIVER_OBJECT DriverObject + ) + +/*++ + +Routine Description: + + This function unregisters countersets + +Arguments: + + DriverObject - Not used. + +Return Value: + + None. + +--*/ + +{ + UNREFERENCED_PARAMETER(DriverObject); + + PAGED_CODE(); + + // + // Unregister Countersets. + // + + KcsUnregisterGeometricWave(); + KcsUnregisterTrignometricWave(); +} + +NTSTATUS +DriverEntry ( + _In_ PDRIVER_OBJECT DriverObject, + _In_ PUNICODE_STRING RegistryPath + ) + +/*++ + +Routine Description: + + This function registers countersets on initial loading of the driver. + +Arguments: + + DriverObject - Supplies the driver object of the driver being loaded. + + RegistryPath - Not used. + +Return Value: + + NTSTATUS indicating if driver was properly loaded. + +--*/ + +{ + NTSTATUS Status; + + UNREFERENCED_PARAMETER(RegistryPath); + + PAGED_CODE(); + + // + // Register Countersets. + // + + Status = KcsRegisterGeometricWave(KcsGeometricWaveCallback, NULL); + if (!NT_SUCCESS(Status)) { + return Status; + } + + Status = KcsRegisterTrignometricWave(KcsTrignometricWaveCallback, NULL); + if (!NT_SUCCESS(Status)) { + KcsUnregisterTrignometricWave(); + return Status; + } + + // + // Success path - set up unload routine and return success. + // + + DriverObject->DriverUnload = KcsUnload; + + return STATUS_SUCCESS; +} + diff --git a/tests/projects/windows/driver/wdm/perfcounters/kcs.h b/tests/projects/windows/driver/wdm/perfcounters/kcs.h new file mode 100644 index 000000000..f575b816d --- /dev/null +++ b/tests/projects/windows/driver/wdm/perfcounters/kcs.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR + PURPOSE. + +Module Name: + + kcs.h + +Abstract: + + This module contains sample code to demonstrate how to provide + counter data from a kernel driver. + +Environment: + + Kernel mode only. + +--*/ + +typedef struct _GEOMETRIC_WAVE_VALUES { + ULONG Square; + ULONG Triangle; +} GEOMETRIC_WAVE_VALUES, *PGEOMETRIC_WAVE_VALUES; + +typedef struct _TRIGNOMETRIC_WAVE_VALUES { + ULONG Constant; + ULONG Cosine; + ULONG Sine; +} TRIGNOMETRIC_WAVE_VALUES, *PTRIGNOMETRIC_WAVE_VALUES; \ No newline at end of file diff --git a/tests/projects/windows/driver/wdm/perfcounters/kcs.man b/tests/projects/windows/driver/wdm/perfcounters/kcs.man new file mode 100644 index 000000000..a5a16ffbd --- /dev/null +++ b/tests/projects/windows/driver/wdm/perfcounters/kcs.man @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/projects/windows/driver/wdm/perfcounters/kcs.rc b/tests/projects/windows/driver/wdm/perfcounters/kcs.rc new file mode 100644 index 000000000..7ebb6b97b --- /dev/null +++ b/tests/projects/windows/driver/wdm/perfcounters/kcs.rc @@ -0,0 +1 @@ +#include "kcsCounters.rc" diff --git a/tests/projects/windows/driver/wdm/perfcounters/xmake.lua b/tests/projects/windows/driver/wdm/perfcounters/xmake.lua new file mode 100644 index 000000000..83e4e4d9b --- /dev/null +++ b/tests/projects/windows/driver/wdm/perfcounters/xmake.lua @@ -0,0 +1,10 @@ +add_rules("mode.debug", "mode.release") + +target("kcs") + add_rules("wdk.env.wdm", "wdk.driver") + add_values("wdk.man.prefix", "Kcs") + add_values("wdk.man.resource", "kcsCounters.rc") + add_values("wdk.man.header", "kcsCounters.h") + add_values("wdk.man.counter_header", "kcsCounters_counters.h") + add_files("*.c", "*.rc", "*.man") + diff --git a/tests/projects/windows/winsdk/usbview/app.config b/tests/projects/windows/winsdk/usbview/app.config new file mode 100644 index 000000000..fe947d6fd --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/app.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/projects/windows/winsdk/usbview/bang.ico b/tests/projects/windows/winsdk/usbview/bang.ico new file mode 100644 index 000000000..90fe0f220 Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/bang.ico differ diff --git a/tests/projects/windows/winsdk/usbview/codeanalysis.h b/tests/projects/windows/winsdk/usbview/codeanalysis.h new file mode 100644 index 000000000..56fa54a1a --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/codeanalysis.h @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) 1997-2011 Microsoft Corporation + +Module Name: + + CODEANALYSIS.H + +Abstract: + + This header file is used for supressing fxcop errors which are not applicable + +Environment: + + user mode + +Revision History: + + 08-11-11 : created + +--*/ + +#pragma once + +#if CODE_ANALYSIS + +/***************************************************************************** + C O D E A N A L Y S I S S U P P R E S S I O N S + *****************************************************************************/ + +using namespace System::Diagnostics::CodeAnalysis; + +namespace Microsoft +{ + namespace Kits + { + namespace Samples + { + namespace Usb + { + // Justification : C++ Compiler cannot enforce ClsCompliant + [module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant")] + + // Justification : The naming of the following types are based on native USB types + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType", MessageId="Bos")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.Hub30DescriptorType.#HubHdrDecLat", MessageId="Hdr")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMajorSpecVersion", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMinorSpecVersion", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMinorVersion", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMajorVersion", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceClassDetailsType.#UvcVersion", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#BNumDeviceCaps", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbDispContIdCapExtDescriptor", MessageId="Disp")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#BosDescriptor", MessageId="Bos")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExType.#IProductStringDescEn", MessageId="Desc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#OtgDescriptor", MessageId="Otg")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#OtgError", MessageId="Otg")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#IadError", MessageId="Iad")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#IadDescriptor", MessageId="Iad")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceIADDescriptorType.#StringDesc", MessageId="Desc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceInterfaceDescriptorType.#BNumEndpoints", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceInterfaceDescriptorType.#StringDesc", MessageId="Desc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceInterfaceDescriptorType.#WNumClasses", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExStructType.#NumOfOpenPipes", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExStructType.#SpeedStr", MessageId="Str")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#ConfStringDesc", MessageId="Desc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#AttributesStr", MessageId="Str")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#ConfigDescError", MessageId="Desc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#BNumInterfaces", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UvcViewAll", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UvcViewAll.#UvcView", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbDispContIdCapExtDescriptorType", MessageId="Disp")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDispContIdCapExtDescriptorType.#ContainerIdStr", MessageId="Str")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConnectionStatusType.#DeviceCausedOvercurrent", MessageId="Overcurrent")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceQualifierDescriptorType.#NumConfigurations", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceQualifierDescriptorType.#DeviceNumConfigError", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#NumConfigurations", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceType.#BosDescriptor", MessageId="Bos")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UvcViewType", MessageId="Uvc")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceHidDescriptorType.#BNumDescriptors", MessageId="Num")]; + [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#HubInformationEx")]; + [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#HubInformationEx")]; + [module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#PreReleaseError", MessageId="PreRelease")]; + [module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbHCPowerStateType.#CanWakeUp", MessageId="WakeUp")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbSuperSpeedExtensionDescriptorType.#BmAttributes", MessageId="Bm")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbUsb20ExtensionDescriptorType.#BmAttributes", MessageId="Bm")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubNodeType.#UsbMiParent", MessageId="Mi")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#HwId", MessageId="Hw")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HostControllerType.#HwId", MessageId="Hw")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbDeviceOTGDescriptorType", MessageId="OTG")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceOTGDescriptorType.#BmAttributes", MessageId="Bm")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubNodeInformationType.#MiParentNumberOfInterfaces", MessageId="Mi")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExType.#IProductStringDescEn", MessageId="En")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbDeviceIADDescriptorType", MessageId="IAD")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#BmAttributes", MessageId="Bm")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#HwId", MessageId="Hw")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceQualifierDescriptorType.#BcdUSB", MessageId="USB")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#CdDevice", MessageId="Cd")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#CdUSB", MessageId="USB")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#CdUSB", MessageId="Cd")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceType.#HwId", MessageId="Hw")]; + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceHidDescriptorType.#BcdHID", MessageId="HID")]; + [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#HubCapabilityEx")] + [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#HubCapabilityEx")] + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubCapabilitiesExType.#HubIsMultiTt", MessageId="Multi")] + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubCapabilitiesExType.#HubIsMultiTtCapable", MessageId="Multi")] + + [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId="usbview")]; + [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="usbview")]; + + // Justification: The version of XSD which is used to generate the objects does not support Collections. + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbSuperSpeedExtensionDescriptor")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbUsb20ExtensionDescriptor")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UnknownDescriptor")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbDispContIdCapExtDescriptor")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#UsbDevice")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#DeviceConfiguration")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#NoDevice")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#ExternalHub")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExStructType.#Pipe")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbHCPowerStateMappingType.#PowerMap")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#NoDevice")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#ExternalHub")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#UsbDevice")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceType.#DeviceConfiguration")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UvcViewType.#UsbTree")]; + [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceHidDescriptorType.#OptionalDescriptor")]; + }; + }; + }; +}; + +#endif diff --git a/tests/projects/windows/winsdk/usbview/debug.c b/tests/projects/windows/winsdk/usbview/debug.c new file mode 100644 index 000000000..b73d727d5 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/debug.c @@ -0,0 +1,210 @@ +/*++ + +Copyright (c) 1997-2008 Microsoft Corporation + +Module Name: + + DEBUG.C + +Abstract: + + This source file contains debug routines. + +Environment: + + user mode + +Revision History: + + 07-08-97 : created + +--*/ + +/***************************************************************************** + I N C L U D E S +*****************************************************************************/ + +#include "uvcview.h" + +#if DBG + +/***************************************************************************** + T Y P E D E F S +*****************************************************************************/ + +typedef struct _ALLOCHEADER +{ + LIST_ENTRY ListEntry; + + PCHAR File; + + ULONG Line; + +} ALLOCHEADER, *PALLOCHEADER; + + +/***************************************************************************** + G L O B A L S +*****************************************************************************/ + +LIST_ENTRY AllocListHead = +{ + &AllocListHead, + &AllocListHead +}; + + +/***************************************************************************** + + MyAlloc() + +*****************************************************************************/ +_Success_(return != NULL) +_Post_writable_byte_size_(dwBytes) +HGLOBAL +MyAlloc ( + _In_ PCHAR File, + ULONG Line, + DWORD dwBytes +) +{ + PALLOCHEADER header; + DWORD dwRequest = dwBytes; + + if (0 == dwBytes) + { + return NULL; + } + + dwBytes += sizeof(ALLOCHEADER); + // check for integer overflow + if (dwBytes > dwRequest) + { + header = (PALLOCHEADER)GlobalAlloc(GPTR, dwBytes); + + if (header != NULL) + { + InsertTailList(&AllocListHead, &header->ListEntry); + + header->File = File; + header->Line = Line; + + return (HGLOBAL)(header + 1); + } + } + return NULL; +} + +/***************************************************************************** + + MyReAlloc() + +*****************************************************************************/ + +_Success_(return != NULL) +_Post_writable_byte_size_(dwBytes) +HGLOBAL +MyReAlloc ( + HGLOBAL hMem, + DWORD dwBytes +) +{ + PALLOCHEADER header; + PALLOCHEADER headerNew; + + if ((NULL == hMem) || (0 == dwBytes)) + { + return NULL; + } + + header = (PALLOCHEADER)hMem; + header--; + + // Remove the old address from the allocation list + // + RemoveEntryList(&header->ListEntry); + + if (dwBytes < (dwBytes + (DWORD) sizeof(ALLOCHEADER))) + { + dwBytes += sizeof(ALLOCHEADER); + headerNew = GlobalReAlloc((HGLOBAL)header, dwBytes, GMEM_MOVEABLE|GMEM_ZEROINIT); + + if (NULL == headerNew) + { + // If GlobalReAlloc fails, the original memory is not freed, + // and the original handle and pointer are still valid. + // Add the old address back to the allocation list. + // + #pragma prefast(suppress:__WARNING_USING_UNINIT_VAR, "SAL noise") + InsertTailList(&AllocListHead, &header->ListEntry); + } + else + { + // Add the new address to the allocation list + // + InsertTailList(&AllocListHead, &headerNew->ListEntry); + + return (HGLOBAL)(headerNew + 1); + } + } + return NULL; +} + + +/***************************************************************************** + + MyFree() + +*****************************************************************************/ + +HGLOBAL +MyFree ( + HGLOBAL hMem +) +{ + PALLOCHEADER header; + + if (hMem) + { + header = (PALLOCHEADER)hMem; + + header--; + + RemoveEntryList(&header->ListEntry); + + return GlobalFree((HGLOBAL)header); + } + + return GlobalFree(hMem); +} + +/***************************************************************************** + + MyCheckForLeaks() + +*****************************************************************************/ + +VOID +MyCheckForLeaks ( + VOID +) +{ + PALLOCHEADER header; + CHAR buf[128]; + + memset(buf, 0, sizeof(buf)); + + while (!IsListEmpty(&AllocListHead)) + { + header = (PALLOCHEADER)RemoveHeadList(&AllocListHead); + + StringCbPrintf(buf, sizeof(buf), + "File: %s, Line: %d\r\n", + header->File, + header->Line); + + OutputDebugString(buf); + } +} + +#endif diff --git a/tests/projects/windows/winsdk/usbview/devnode.c b/tests/projects/windows/winsdk/usbview/devnode.c new file mode 100644 index 000000000..d9a3b8ecc --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/devnode.c @@ -0,0 +1,336 @@ +/*++ + + Copyright (c) 1998-2011 Microsoft Corporation + + Module Name: + + DEVNODE.C + + --*/ + +/***************************************************************************** + I N C L U D E S + *****************************************************************************/ + +#include "uvcview.h" + +/***************************************************************************** + + DriverNameToDeviceInst() + + Finds the Device instance of the DevNode with the matching DriverName. + Returns FALSE if the matching DevNode is not found and TRUE if found + + *****************************************************************************/ +BOOL +DriverNameToDeviceInst( + _In_reads_bytes_(cbDriverName) PCHAR DriverName, + _In_ size_t cbDriverName, + _Out_ HDEVINFO *pDevInfo, + _Out_writes_bytes_(sizeof(SP_DEVINFO_DATA)) PSP_DEVINFO_DATA pDevInfoData + ) +{ + HDEVINFO deviceInfo = INVALID_HANDLE_VALUE; + BOOL status = TRUE; + ULONG deviceIndex; + SP_DEVINFO_DATA deviceInfoData; + BOOL bResult = FALSE; + PCHAR pDriverName = NULL; + PSTR buf = NULL; + BOOL done = FALSE; + + if (pDevInfo == NULL) + { + return FALSE; + } + + if (pDevInfoData == NULL) + { + return FALSE; + } + + memset(pDevInfoData, 0, sizeof(SP_DEVINFO_DATA)); + + *pDevInfo = INVALID_HANDLE_VALUE; + + // Use local string to guarantee zero termination + pDriverName = (PCHAR) ALLOC((DWORD) cbDriverName + 1); + if (NULL == pDriverName) + { + status = FALSE; + goto Done; + } + StringCbCopyN(pDriverName, cbDriverName + 1, DriverName, cbDriverName); + + // + // We cannot walk the device tree with CM_Get_Sibling etc. unless we assume + // the device tree will stabilize. Any devnode removal (even outside of USB) + // would force us to retry. Instead we use Setup API to snapshot all + // devices. + // + + // Examine all present devices to see if any match the given DriverName + // + deviceInfo = SetupDiGetClassDevs(NULL, + NULL, + NULL, + DIGCF_ALLCLASSES | DIGCF_PRESENT); + + if (deviceInfo == INVALID_HANDLE_VALUE) + { + status = FALSE; + goto Done; + } + + deviceIndex = 0; + deviceInfoData.cbSize = sizeof(deviceInfoData); + + while (done == FALSE) + { + // + // Get devinst of the next device + // + + status = SetupDiEnumDeviceInfo(deviceInfo, + deviceIndex, + &deviceInfoData); + + deviceIndex++; + + if (!status) + { + // + // This could be an error, or indication that all devices have been + // processed. Either way the desired device was not found. + // + + done = TRUE; + break; + } + + // + // Get the DriverName value + // + + bResult = GetDeviceProperty(deviceInfo, + &deviceInfoData, + SPDRP_DRIVER, + &buf); + + // If the DriverName value matches, return the DeviceInstance + // + if (bResult == TRUE && buf != NULL && _stricmp(pDriverName, buf) == 0) + { + done = TRUE; + *pDevInfo = deviceInfo; + CopyMemory(pDevInfoData, &deviceInfoData, sizeof(deviceInfoData)); + FREE(buf); + break; + } + + if(buf != NULL) + { + FREE(buf); + buf = NULL; + } + } + +Done: + + if (bResult == FALSE) + { + if (deviceInfo != INVALID_HANDLE_VALUE) + { + SetupDiDestroyDeviceInfoList(deviceInfo); + } + } + + if (pDriverName != NULL) + { + FREE(pDriverName); + } + + return status; +} + +/***************************************************************************** + + DriverNameToDeviceProperties() + + Returns the Device properties of the DevNode with the matching DriverName. + Returns NULL if the matching DevNode is not found. + + The caller should free the returned structure using FREE() macro + + *****************************************************************************/ +PUSB_DEVICE_PNP_STRINGS +DriverNameToDeviceProperties( + _In_reads_bytes_(cbDriverName) PCHAR DriverName, + _In_ size_t cbDriverName + ) +{ + HDEVINFO deviceInfo = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA deviceInfoData = {0}; + ULONG len; + BOOL status; + PUSB_DEVICE_PNP_STRINGS DevProps = NULL; + DWORD lastError; + + // Allocate device propeties structure + DevProps = (PUSB_DEVICE_PNP_STRINGS) ALLOC(sizeof(USB_DEVICE_PNP_STRINGS)); + + if(NULL == DevProps) + { + status = FALSE; + goto Done; + } + + // Get device instance + status = DriverNameToDeviceInst(DriverName, cbDriverName, &deviceInfo, &deviceInfoData); + if (status == FALSE) + { + goto Done; + } + + len = 0; + status = SetupDiGetDeviceInstanceId(deviceInfo, + &deviceInfoData, + NULL, + 0, + &len); + lastError = GetLastError(); + + + if (status != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER) + { + status = FALSE; + goto Done; + } + + // + // An extra byte is required for the terminating character + // + + len++; + DevProps->DeviceId = ALLOC(len); + + if (DevProps->DeviceId == NULL) + { + status = FALSE; + goto Done; + } + + status = SetupDiGetDeviceInstanceId(deviceInfo, + &deviceInfoData, + DevProps->DeviceId, + len, + &len); + if (status == FALSE) + { + goto Done; + } + + status = GetDeviceProperty(deviceInfo, + &deviceInfoData, + SPDRP_DEVICEDESC, + &DevProps->DeviceDesc); + + if (status == FALSE) + { + goto Done; + } + + + // + // We don't fail if the following registry query fails as these fields are additional information only + // + + GetDeviceProperty(deviceInfo, + &deviceInfoData, + SPDRP_HARDWAREID, + &DevProps->HwId); + + GetDeviceProperty(deviceInfo, + &deviceInfoData, + SPDRP_SERVICE, + &DevProps->Service); + + GetDeviceProperty(deviceInfo, + &deviceInfoData, + SPDRP_CLASS, + &DevProps->DeviceClass); +Done: + + if (deviceInfo != INVALID_HANDLE_VALUE) + { + SetupDiDestroyDeviceInfoList(deviceInfo); + } + + if (status == FALSE) + { + if (DevProps != NULL) + { + FreeDeviceProperties(&DevProps); + } + } + return DevProps; +} + +/***************************************************************************** + + FreeDeviceProperties() + + Free the device properties structure + + *****************************************************************************/ +VOID FreeDeviceProperties(_In_ PUSB_DEVICE_PNP_STRINGS *ppDevProps) +{ + if(ppDevProps == NULL) + { + return; + } + + if(*ppDevProps == NULL) + { + return; + } + + if ((*ppDevProps)->DeviceId != NULL) + { + FREE((*ppDevProps)->DeviceId); + } + + if ((*ppDevProps)->DeviceDesc != NULL) + { + FREE((*ppDevProps)->DeviceDesc); + } + + // + // The following are not necessary, but left in case + // in the future there is a later failure where these + // pointer fields would be allocated. + // + + if ((*ppDevProps)->HwId != NULL) + { + FREE((*ppDevProps)->HwId); + } + + if ((*ppDevProps)->Service != NULL) + { + FREE((*ppDevProps)->Service); + } + + if ((*ppDevProps)->DeviceClass != NULL) + { + FREE((*ppDevProps)->DeviceClass); + } + + if ((*ppDevProps)->PowerState != NULL) + { + FREE((*ppDevProps)->PowerState); + } + + FREE(*ppDevProps); + *ppDevProps = NULL; +} diff --git a/tests/projects/windows/winsdk/usbview/dispaud.c b/tests/projects/windows/winsdk/usbview/dispaud.c new file mode 100644 index 000000000..bbc16a912 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/dispaud.c @@ -0,0 +1,1164 @@ +/*++ + +Copyright (c) 1997-2008 Microsoft Corporation + +Module Name: + +DISPAUD.C + +Abstract: + +This source file contains routines which update the edit control +to display information about USB Audio descriptors. + +Environment: + +user mode + +Revision History: + +03-07-1998 : created + +--*/ + +/***************************************************************************** + I N C L U D E S +*****************************************************************************/ + +#include "uvcview.h" + +/***************************************************************************** + G L O B A L S P R I V A T E T O T H I S F I L E +*****************************************************************************/ + +// +// USB Device Class Definition for Terminal Types 0.9 Draft Revision +// +STRINGLIST slAudioTerminalTypes [] = +{ + // + // 2.1 USB Terminal Types + // + {0x0100, "USB Undefined", ""}, + {0x0101, "USB streaming", ""}, + {0x01FF, "USB vendor specific", ""}, + // + // 2.2 Input Terminal Types + // + {0x0200, "Input Undefined", ""}, + {0x0201, "Microphone", ""}, + {0x0202, "Desktop microphone", ""}, + {0x0203, "Personal microphone", ""}, + {0x0204, "Omni-directional microphone", ""}, + {0x0205, "Microphone array", ""}, + {0x0206, "Processing microphone array", ""}, + // + // 2.3 Output Terminal Types + // + {0x0300, "Output Undefined", ""}, + {0x0301, "Speaker", ""}, + {0x0302, "Headphones", ""}, + {0x0303, "Head Mounted Display Audio", ""}, + {0x0304, "Desktop speaker", ""}, + {0x0305, "Room speaker", ""}, + {0x0306, "Communication speaker", ""}, + {0x0307, "Low frequency effects speaker", ""}, + // + // 2.4 Bi-directional Terminal Types + // + {0x0400, "Bi-directional Undefined", ""}, + {0x0401, "Handset", ""}, + {0x0402, "Headset", ""}, + {0x0403, "Speakerphone, no echo reduction", ""}, + {0x0404, "Echo-suppressing speakerphone", ""}, + {0x0405, "Echo-canceling speakerphone", ""}, + // + // 2.5 Telephony Terminal Types + // + {0x0500, "Telephony Undefined", ""}, + {0x0501, "Phone line", ""}, + {0x0502, "Telephone", ""}, + {0x0503, "Down Line Phone", ""}, + // + // 2.6 External Terminal Types + // + {0x0600, "External Undefined", ""}, + {0x0601, "Analog connector", ""}, + {0x0602, "Digital audio interface", ""}, + {0x0603, "Line connector", ""}, + {0x0604, "Legacy audio connector", ""}, + {0x0605, "S/PDIF interface", ""}, + {0x0606, "1394 DA stream", ""}, + {0x0607, "1394 DV stream soundtrack", ""}, + // + // Embedded Function Terminal Types + // + {0x0700, "Embedded Undefined", ""}, + {0x0701, "Level Calibration Noise Source", ""}, + {0x0702, "Equalization Noise", ""}, + {0x0703, "CD player", ""}, + {0x0704, "DAT", ""}, + {0x0705, "DCC", ""}, + {0x0706, "MiniDisk", ""}, + {0x0707, "Analog Tape", ""}, + {0x0708, "Phonograph", ""}, + {0x0709, "VCR Audio", ""}, + {0x070A, "Video Disc Audio", ""}, + {0x070B, "DVD Audio", ""}, + {0x070C, "TV Tuner Audio", ""}, + {0x070D, "Satellite Receiver Audio", ""}, + {0x070E, "Cable Tuner Audio", ""}, + {0x070F, "DSS Audio", ""}, + {0x0710, "Radio Receiver", ""}, + {0x0711, "Radio Transmitter", ""}, + {0x0712, "Multi-track Recorder", ""}, + {0x0713, "Synthesizer", ""}, +}; +STRINGLIST slAudioFormatTypes [] = +{ + // + // A.1.1 Audio Data Format Type I Codes + // + {0x0000, "TYPE_I_UNDEFINED", ""}, + {0x0001, "PCM", ""}, + {0x0002, "PCM8", ""}, + {0x0003, "IEEE_FLOAT", ""}, + {0x0004, "ALAW", ""}, + {0x0005, "MULAW", ""}, + // + // A.1.2 Audio Data Format Type II Codes + // + {0x1000, "TYPE_II_UNDEFINED", ""}, + {0x1001, "MPEG", ""}, + {0x1002, "AC-3", ""}, + // + // A.1.3 Audio Data Format Type III Codes + // + {0x2000, "TYPE_III_UNDEFINED", ""}, + {0x2001, "IEC1937_AC-3", ""}, + {0x2002, "IEC1937_MPEG-1_Layer1", ""}, + {0x2003, "IEC1937_MPEG-1_Layer2/3 or IEC1937_MPEG-2_NOEXT", ""}, + {0x2004, "IEC1937_MPEG-2_EXT", ""}, + {0x2005, "IEC1937_MPEG-2_Layer1_LS", ""}, + {0x2006, "IEC1937_MPEG-2_Layer2/3_LS", ""}, +}; + + + +/***************************************************************************** + L O C A L F U N C T I O N P R O T O T Y P E S +*****************************************************************************/ + +BOOL +DisplayACHeader ( + PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR HeaderDesc +); + +BOOL +DisplayACInputTerminal ( + PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR ITDesc +); + +BOOL +DisplayACOutputTerminal ( + PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR OTDesc +); + +BOOL +DisplayACMixerUnit ( + PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR MixerDesc +); + +BOOL +DisplayACSelectorUnit ( + PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR SelectorDesc +); + +BOOL +DisplayACFeatureUnit ( + PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR FeatureDesc +); + +BOOL +DisplayACProcessingUnit ( + PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR ProcessingDesc +); + +BOOL +DisplayACExtensionUnit ( + PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR ExtensionDesc +); + +BOOL +DisplayASGeneral ( + PUSB_AUDIO_GENERAL_DESCRIPTOR GeneralDesc +); + +BOOL +DisplayCSEndpoint ( + PUSB_AUDIO_ENDPOINT_DESCRIPTOR EndpointDesc +); + +BOOL +DisplayASFormatType ( + PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR FormatDesc +); + +BOOL +DisplayASFormatSpecific ( + PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc +); + +VOID +DisplayBytes ( + PUCHAR Data, + USHORT Len +); + +/***************************************************************************** + L O C A L F U N C T I O N S +*****************************************************************************/ + +/***************************************************************************** + + DisplayAudioDescriptor() + + CommonDesc - An Audio Class Descriptor + + bInterfaceSubClass - The SubClass of the Interface containing the descriptor + +*****************************************************************************/ + +BOOL +DisplayAudioDescriptor ( + PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc, + UCHAR bInterfaceSubClass +) +{ + switch (CommonDesc->bDescriptorType) + { + case USB_AUDIO_CS_INTERFACE: + switch (bInterfaceSubClass) + { + case USB_AUDIO_SUBCLASS_AUDIOCONTROL: + switch (CommonDesc->bDescriptorSubtype) + { + case USB_AUDIO_AC_HEADER: + return DisplayACHeader((PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_INPUT_TERMINAL: + return DisplayACInputTerminal((PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_OUTPUT_TERMINAL: + return DisplayACOutputTerminal((PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_MIXER_UNIT: + return DisplayACMixerUnit((PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_SELECTOR_UNIT: + return DisplayACSelectorUnit((PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_FEATURE_UNIT: + return DisplayACFeatureUnit((PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_PROCESSING_UNIT: + return DisplayACProcessingUnit((PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AC_EXTENSION_UNIT: + return DisplayACExtensionUnit((PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR)CommonDesc); + + default: + break; + } + break; + + case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: + switch (CommonDesc->bDescriptorSubtype) + { + case USB_AUDIO_AS_GENERAL: + return DisplayASGeneral((PUSB_AUDIO_GENERAL_DESCRIPTOR)CommonDesc); + + case USB_AUDIO_AS_FORMAT_TYPE: + return DisplayASFormatType((PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR)CommonDesc); + break; + + case USB_AUDIO_AS_FORMAT_SPECIFIC: + return DisplayASFormatSpecific(CommonDesc); + + default: + break; + } + break; + + default: + break; + } + break; + + case USB_AUDIO_CS_ENDPOINT: + return DisplayCSEndpoint((PUSB_AUDIO_ENDPOINT_DESCRIPTOR)CommonDesc); + + default: + break; + } + + return FALSE; +} + + +/***************************************************************************** + + DisplayACHeader() + +*****************************************************************************/ + +BOOL +DisplayACHeader ( + PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR HeaderDesc +) +{ + UINT i = 0; + + if (HeaderDesc->bLength < sizeof(USB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Interface Header Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + HeaderDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + HeaderDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + HeaderDesc->bDescriptorSubtype); + + AppendTextBuffer("bcdADC: 0x%04X\r\n", + HeaderDesc->bcdADC); + + AppendTextBuffer("wTotalLength: 0x%04X\r\n", + HeaderDesc->wTotalLength); + + AppendTextBuffer("bInCollection: 0x%02X\r\n", + HeaderDesc->bInCollection); + + for (i=0; ibInCollection; i++) + { + AppendTextBuffer("baInterfaceNr[%d]: 0x%02X\r\n", + i+1, + HeaderDesc->baInterfaceNr[i]); + } + + return TRUE; +} + + +/***************************************************************************** + + DisplayACInputTerminal() + +*****************************************************************************/ + +BOOL +DisplayACInputTerminal ( + PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR ITDesc +) +{ + PCHAR pStr = NULL; + + if (ITDesc->bLength != sizeof(USB_AUDIO_INPUT_TERMINAL_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Input Terminal Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + ITDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + ITDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + ITDesc->bDescriptorSubtype); + + AppendTextBuffer("bTerminalID: 0x%02X\r\n", + ITDesc->bTerminalID); + + AppendTextBuffer("wTerminalType: 0x%04X", + ITDesc->wTerminalType); + pStr = GetStringFromList(slAudioTerminalTypes, + sizeof(slAudioTerminalTypes) / sizeof(STRINGLIST), + ITDesc->wTerminalType, + "Invalid AC Input Terminal Type"); + AppendTextBuffer(" (%s)\r\n", pStr); + + AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", + ITDesc->bAssocTerminal); + + AppendTextBuffer("bNrChannels: 0x%02X\r\n", + ITDesc->bNrChannels); + + AppendTextBuffer("wChannelConfig: 0x%04X\r\n", + ITDesc->wChannelConfig); + + AppendTextBuffer("iChannelNames: 0x%02X\r\n", + ITDesc->iChannelNames); + + AppendTextBuffer("iTerminal: 0x%02X\r\n", + ITDesc->iTerminal); + + + return TRUE; +} + + +/***************************************************************************** + + DisplayACOutputTerminal() + +*****************************************************************************/ + +BOOL +DisplayACOutputTerminal ( + PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR OTDesc +) +{ + PCHAR pStr = NULL; + + if (OTDesc->bLength != sizeof(USB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Output Terminal Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + OTDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + OTDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + OTDesc->bDescriptorSubtype); + + AppendTextBuffer("bTerminalID: 0x%02X\r\n", + OTDesc->bTerminalID); + + AppendTextBuffer("wTerminalType: 0x%04X", + OTDesc->wTerminalType); + + pStr = GetStringFromList(slAudioTerminalTypes, + sizeof(slAudioTerminalTypes) / sizeof(STRINGLIST), + OTDesc->wTerminalType, + "Invalid AC Output Terminal Type"); + AppendTextBuffer(" (%s)\r\n", pStr); + + AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", + OTDesc->bAssocTerminal); + + AppendTextBuffer("bSourceID: 0x%02X\r\n", + OTDesc->bSourceID); + + AppendTextBuffer("iTerminal: 0x%02X\r\n", + OTDesc->iTerminal); + + + return TRUE; +} + + +/***************************************************************************** + + DisplayACMixerUnit() + +*****************************************************************************/ + +BOOL +DisplayACMixerUnit ( + PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR MixerDesc +) +{ + UCHAR i = 0; + PUCHAR data = NULL; + + if (MixerDesc->bLength < 10) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Mixer Unit Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + MixerDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + MixerDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + MixerDesc->bDescriptorSubtype); + + AppendTextBuffer("bUnitID: 0x%02X\r\n", + MixerDesc->bUnitID); + + AppendTextBuffer("bNrInPins: 0x%02X\r\n", + MixerDesc->bNrInPins); + + for (i=0; ibNrInPins; i++) + { + AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", + i+1, + MixerDesc->baSourceID[i]); + } + + data = &MixerDesc->baSourceID[MixerDesc->bNrInPins]; + + AppendTextBuffer("bNrChannels: 0x%02X\r\n", + *data++); + + AppendTextBuffer("wChannelConfig: 0x%04X\r\n", + *(PUSHORT)data); + + data = (PUCHAR) ((PUSHORT) data + 1); + + AppendTextBuffer("iChannelNames: 0x%02X\r\n", + *data++); + + AppendTextBuffer("bmControls:\r\n"); + + i = MixerDesc->bLength - 10 - MixerDesc->bNrInPins; + + DisplayBytes(data, i); + + data += i; + + AppendTextBuffer("iMixer: 0x%02X\r\n", + *data); + + return TRUE; +} + + +/***************************************************************************** + + DisplayACSelectorUnit() + +*****************************************************************************/ + +BOOL +DisplayACSelectorUnit ( + PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR SelectorDesc +) +{ + UCHAR i = 0; + PUCHAR data = NULL; + + if (SelectorDesc->bLength < 6) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Selector Unit Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + SelectorDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + SelectorDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + SelectorDesc->bDescriptorSubtype); + + AppendTextBuffer("bUnitID: 0x%02X\r\n", + SelectorDesc->bUnitID); + + AppendTextBuffer("bNrInPins: 0x%02X\r\n", + SelectorDesc->bNrInPins); + + for (i=0; ibNrInPins; i++) + { + AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", + i+1, + SelectorDesc->baSourceID[i]); + } + + data = &SelectorDesc->baSourceID[SelectorDesc->bNrInPins]; + + AppendTextBuffer("iSelector: 0x%02X\r\n", + *data); + + return TRUE; +} + + +/***************************************************************************** + + DisplayACFeatureUnit() + +*****************************************************************************/ + +BOOL +DisplayACFeatureUnit ( + PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR FeatureDesc +) +{ + UCHAR i = 0; + UCHAR n = 0; + UCHAR ch = 0; + PUCHAR data = NULL; + + AppendTextBuffer("\r\n ===>Audio Control Feature Unit Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + FeatureDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + FeatureDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + FeatureDesc->bDescriptorSubtype); + + AppendTextBuffer("bUnitID: 0x%02X\r\n", + FeatureDesc->bUnitID); + + AppendTextBuffer("bSourceID: 0x%02X\r\n", + FeatureDesc->bSourceID); + + AppendTextBuffer("bControlSize: 0x%02X\r\n", + FeatureDesc->bControlSize); + + + if (FeatureDesc->bLength < 7) + { + AppendTextBuffer("*!*WARNING: bLength is invalid (< 7)\r\n"); + OOPS(); + return FALSE; + } + else if(FeatureDesc->bLength == 7) + { + AppendTextBuffer("Audio controls are not available (bLength = 7)\r\n"); + return TRUE; + } + + n = FeatureDesc->bControlSize; + + if(n == 0) + { + AppendTextBuffer("Audio controls are not available (bControlSize = 0)\r\n"); + return TRUE; + } + + ch = ((FeatureDesc->bLength - 7) / n) - 1; + + // Check if there are extra bytes in descriptor based on formula in Spec + if (FeatureDesc->bLength != (7 + (ch + 1) * n)) + { + // The descriptor length is greater than number of bmaControls + AppendTextBuffer("*!*WARNING: bLength is greater than number of bmaControls (bLength > ( 7 + (ch + 1) * n)\r\n"); + } + + data = &FeatureDesc->bmaControls[0]; + + if (ch == (UCHAR) -1) + { + // This should not happen, but this check is put in place so we don't loop for a long time below + AppendTextBuffer("*!*WARNING: Either bLength or bControlSize are invalid. The calculated logical channel count is -1. ((bLength - 7)/ n) - 1\r\n"); + OOPS(); + return FALSE; + } + + for (i=0; i<=ch; i++) + { + AppendTextBuffer("bmaControls[%d]: ", i); + DisplayBytes(data, n); + + data += n; + } + + + AppendTextBuffer("iFeature: 0x%02X\r\n", + *data); + + return TRUE; +} + + +/***************************************************************************** + + DisplayACProcessingUnit() + +*****************************************************************************/ + +BOOL +DisplayACProcessingUnit ( + PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR ProcessingDesc +) +{ + UCHAR i = 0; + PUCHAR data = NULL; + + if (ProcessingDesc->bLength < sizeof(USB_AUDIO_PROCESSING_UNIT_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Processing Unit Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + ProcessingDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + ProcessingDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + ProcessingDesc->bDescriptorSubtype); + + AppendTextBuffer("bUnitID: 0x%02X\r\n", + ProcessingDesc->bUnitID); + + AppendTextBuffer("wProcessType: 0x%04X", + ProcessingDesc->wProcessType); + + switch (ProcessingDesc->wProcessType) + { + case USB_AUDIO_PROCESS_UNDEFINED: + AppendTextBuffer("(Undefined Process)\r\n"); + break; + + case USB_AUDIO_PROCESS_UPDOWNMIX: + AppendTextBuffer("(Up / Down Mix Process)\r\n"); + break; + + case USB_AUDIO_PROCESS_DOLBYPROLOGIC: + AppendTextBuffer("(Dolby Prologic Process)\r\n"); + break; + + case USB_AUDIO_PROCESS_3DSTEREOEXTENDER: + AppendTextBuffer("(3D-Stereo Extender Process)\r\n"); + break; + + case USB_AUDIO_PROCESS_REVERBERATION: + AppendTextBuffer("(Reverberation Process)\r\n"); + break; + + case USB_AUDIO_PROCESS_CHORUS: + AppendTextBuffer("(Chorus Process)\r\n"); + break; + + case USB_AUDIO_PROCESS_DYNRANGECOMP: + AppendTextBuffer("(Dynamic Range Compressor Process)\r\n"); + break; + + default: + AppendTextBuffer("\r\n"); + break; + } + + AppendTextBuffer("bNrInPins: 0x%02X\r\n", + ProcessingDesc->bNrInPins); + + for (i=0; ibNrInPins; i++) + { + AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", + i+1, + ProcessingDesc->baSourceID[i]); + } + + data = &ProcessingDesc->baSourceID[ProcessingDesc->bNrInPins]; + + AppendTextBuffer("bNrChannels: 0x%02X\r\n", + *data++); + + AppendTextBuffer("wChannelConfig: 0x%04X\r\n", + *(PUSHORT)data); + + data = (PUCHAR) ((PUSHORT) data + 1); + + AppendTextBuffer("iChannelNames: 0x%02X\r\n", + *data++); + + i = *data++; + + AppendTextBuffer("bControlSize: 0x%02X\r\n", + i); + + AppendTextBuffer("bmControls:\r\n"); + + DisplayBytes(data, i); + + data += i; + + AppendTextBuffer("iProcessing: 0x%02X\r\n", + *data++); + + + i = ProcessingDesc->bLength - 13 - ProcessingDesc->bNrInPins - i; + + if (i) + { + AppendTextBuffer("Process Specific:\r\n"); + + DisplayBytes(data, i); + } + + return TRUE; +} + + +/***************************************************************************** + + DisplayACExtensionUnit() + +*****************************************************************************/ + +BOOL +DisplayACExtensionUnit ( + PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR ExtensionDesc +) +{ + UCHAR i = 0; + PUCHAR data = NULL; + + if (ExtensionDesc->bLength < 13) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Control Extension Unit Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + ExtensionDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + ExtensionDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + ExtensionDesc->bDescriptorSubtype); + + AppendTextBuffer("bUnitID: 0x%02X\r\n", + ExtensionDesc->bUnitID); + + AppendTextBuffer("wExtensionCode: 0x%04X\r\n", + ExtensionDesc->wExtensionCode); + + + AppendTextBuffer("bNrInPins: 0x%02X\r\n", + ExtensionDesc->bNrInPins); + + for (i=0; ibNrInPins; i++) + { + AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", + i+1, + ExtensionDesc->baSourceID[i]); + } + + data = &ExtensionDesc->baSourceID[ExtensionDesc->bNrInPins]; + + AppendTextBuffer("bNrChannels: 0x%02X\r\n", + *data++); + + AppendTextBuffer("wChannelConfig: 0x%04X\r\n", + *(PUSHORT)data); + + data = (PUCHAR) ((PUSHORT) data + 1); + + AppendTextBuffer("iChannelNames: 0x%02X\r\n", + *data++); + + i = *data++; + + AppendTextBuffer("bControlSize: 0x%02X\r\n", + i); + + AppendTextBuffer("bmControls:\r\n"); + + DisplayBytes(data, i); + + data += i; + + AppendTextBuffer("iExtension: 0x%02X\r\n", + *data); + return TRUE; +} + + +/***************************************************************************** + + DisplayASGeneral() + +*****************************************************************************/ + +BOOL +DisplayASGeneral ( + PUSB_AUDIO_GENERAL_DESCRIPTOR GeneralDesc +) +{ + PCHAR pStr = NULL; + + if (GeneralDesc->bLength != sizeof(USB_AUDIO_GENERAL_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Streaming Class Specific Interface Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + GeneralDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + GeneralDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + GeneralDesc->bDescriptorSubtype); + + AppendTextBuffer("bTerminalLink: 0x%02X\r\n", + GeneralDesc->bTerminalLink); + + AppendTextBuffer("bDelay: 0x%02X\r\n", + GeneralDesc->bDelay); + + AppendTextBuffer("wFormatTag: 0x%04X", + GeneralDesc->wFormatTag); + + pStr = GetStringFromList(slAudioFormatTypes, + sizeof(slAudioFormatTypes) / sizeof(STRINGLIST), + GeneralDesc->wFormatTag, + "Invalid AC Format Type"); + AppendTextBuffer(" (%s)\r\n", pStr); + + return TRUE; +} + + +/***************************************************************************** + + DisplayCSEndpoint() + +*****************************************************************************/ + +BOOL +DisplayCSEndpoint ( + PUSB_AUDIO_ENDPOINT_DESCRIPTOR EndpointDesc +) +{ + if (EndpointDesc->bLength != sizeof(USB_AUDIO_ENDPOINT_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Streaming Class Specific Audio Data Endpoint Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + EndpointDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + EndpointDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + EndpointDesc->bDescriptorSubtype); + + AppendTextBuffer("bmAttributes: 0x%02X\r\n", + EndpointDesc->bmAttributes); + + AppendTextBuffer("bLockDelayUnits: 0x%02X\r\n", + EndpointDesc->bLockDelayUnits); + + AppendTextBuffer("wLockDelay: 0x%04X\r\n", + EndpointDesc->wLockDelay); + + return TRUE; +} + + +/***************************************************************************** + + DisplayASFormatType() + +*****************************************************************************/ + +BOOL +DisplayASFormatType ( + PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR FormatDesc +) +{ + UCHAR i = 0; + UCHAR n = 0; + ULONG freq = 0; + PUCHAR data = NULL; + + if (FormatDesc->bLength < sizeof(USB_AUDIO_COMMON_FORMAT_DESCRIPTOR)) + { + OOPS(); + return FALSE; + } + + AppendTextBuffer("\r\n ===>Audio Streaming Format Type Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + FormatDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + FormatDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + FormatDesc->bDescriptorSubtype); + + AppendTextBuffer("bFormatType: 0x%02X\r\n", + FormatDesc->bFormatType); + + + if (FormatDesc->bFormatType == 0x01 || + FormatDesc->bFormatType == 0x03) + { + PUSB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR FormatI_IIIDesc; + + FormatI_IIIDesc = (PUSB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR)FormatDesc; + + AppendTextBuffer("bNrChannels: 0x%02X\r\n", + FormatI_IIIDesc->bNrChannels); + + AppendTextBuffer("bSubframeSize: 0x%02X\r\n", + FormatI_IIIDesc->bSubframeSize); + + AppendTextBuffer("bBitResolution: 0x%02X\r\n", + FormatI_IIIDesc->bBitResolution); + + AppendTextBuffer("bSamFreqType: 0x%02X\r\n", + FormatI_IIIDesc->bSamFreqType); + + data = (PUCHAR)(FormatI_IIIDesc + 1); + + n = FormatI_IIIDesc->bSamFreqType; + + } + else if (FormatDesc->bFormatType == 0x02) + { + PUSB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR FormatIIDesc; + + FormatIIDesc = (PUSB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR)FormatDesc; + + AppendTextBuffer("wMaxBitRate: 0x%04X\r\n", + FormatIIDesc->wMaxBitRate); + + AppendTextBuffer("wSamplesPerFrame: 0x%04X\r\n", + FormatIIDesc->wSamplesPerFrame); + + AppendTextBuffer("bSamFreqType: 0x%02X\r\n", + FormatIIDesc->bSamFreqType); + + data = (PUCHAR)(FormatIIDesc + 1); + + n = FormatIIDesc->bSamFreqType; + } + else + { + data = NULL; + } + + if (data != NULL) + { + if (n == 0) + { + freq = (data[0]) + (data[1] << 8) + (data[2] << 16); + data += 3; + + AppendTextBuffer("tLowerSamFreq: 0x%06X (%d Hz)\r\n", + freq, + freq); + + freq = (data[0]) + (data[1] << 8) + (data[2] << 16); + data += 3; + + AppendTextBuffer("tUpperSamFreq: 0x%06X (%d Hz)\r\n", + freq, + freq); + } + else + { + for (i=0; iAudio Streaming Format Specific Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + CommonDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + CommonDesc->bDescriptorType); + + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", + CommonDesc->bDescriptorSubtype); + + DisplayBytes((PUCHAR)(CommonDesc + 1), + CommonDesc->bLength); + + return TRUE; +} + +/***************************************************************************** + + DisplayBytes() + +*****************************************************************************/ + +VOID +DisplayBytes ( + PUCHAR Data, + USHORT Len +) +{ + USHORT i; + + for (i = 0; i < Len; i++) + { + AppendTextBuffer("%02X ", Data[i]); + + if (i % 16 == 15) + { + AppendTextBuffer("\r\n"); + } + } + + if (i % 16 != 0) + { + AppendTextBuffer("\r\n"); + } +} + + diff --git a/tests/projects/windows/winsdk/usbview/display.c b/tests/projects/windows/winsdk/usbview/display.c new file mode 100644 index 000000000..beead6d93 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/display.c @@ -0,0 +1,5242 @@ +/*++ + +Copyright (c) 1997-2011 Microsoft Corporation + +Module Name: + +DISPLAY.C + +Abstract: + +This source file contains the routines which update the edit control +to display information about the selected USB device. + +Environment: + +user mode + +Revision History: + +04-25-97 : created +03-28-03 : extensive changes to support new USBVCD +03-28-08 : extensive changes to support new USB Video Class 1.1 + +--*/ + +/***************************************************************************** +I N C L U D E S +*****************************************************************************/ + +#include "uvcview.h" +#include "h264.h" +#include + +#include "vndrlist.h" +#include "langidlist.h" + +/***************************************************************************** +D E F I N E S +*****************************************************************************/ + +#define BUFFERALLOCINCREMENT 0x10000 +#define BUFFERMINFREESPACE 0x1000 + +/***************************************************************************** +T Y P E D E F S +*****************************************************************************/ + +// +// Hardcoded information about specific EHCI controllers +// +typedef struct _EHCI_CONTROLLER_DATA +{ + USHORT VendorID; + USHORT DeviceID; + UCHAR DebugPortNumber; +} EHCI_CONTROLLER_DATA, *PEHCI_CONTROLLER_DATA; + + +/***************************************************************************** +G L O B A L S P R I V A T E T O T H I S F I L E +*****************************************************************************/ + +// Workspace for text info which is used to update the edit control +// +CHAR *TextBuffer = NULL; +UINT TextBufferLen = 0; +UINT TextBufferPos = 0; + +STRINGLIST slPowerState [] = +{ + {WdmUsbPowerNotMapped, "S? (unmapped) ", ""}, + + {WdmUsbPowerSystemUnspecified, "S? (unspecified)", ""}, + {WdmUsbPowerSystemWorking, "S0 (working) ", ""}, + {WdmUsbPowerSystemSleeping1, "S1 (sleep) ", ""}, + {WdmUsbPowerSystemSleeping2, "S2 (sleep) ", ""}, + {WdmUsbPowerSystemSleeping3, "S3 (sleep) ", ""}, + {WdmUsbPowerSystemHibernate, "S4 (Hibernate) ", ""}, + {WdmUsbPowerSystemShutdown, "S5 (shutdown) ", ""}, + + {WdmUsbPowerDeviceUnspecified, "D? (unspecified)", ""}, + {WdmUsbPowerDeviceD0, "D0 ", ""}, + {WdmUsbPowerDeviceD1, "D1 ", ""}, + {WdmUsbPowerDeviceD2, "D2 ", ""}, + {WdmUsbPowerDeviceD3, "D3 ", ""}, +}; + +STRINGLIST slControllerFlavor[] = +{ + { USB_HcGeneric, "USB_HcGeneric", "" }, + { OHCI_Generic, "OHCI_Generic", "" }, + { OHCI_Hydra, "OHCI_Hydra", "" }, + { OHCI_NEC, "OHCI_NEC", "" }, + { UHCI_Generic, "UHCI_Generic", "" }, + { UHCI_Piix4, "UHCI_Piix4", "" }, + { UHCI_Piix3, "UHCI_Piix3", "" }, + { UHCI_Ich2, "UHCI_Ich2", "" }, + { UHCI_Reserved204, "UHCI_Reserved204", "" }, + { UHCI_Ich1, "UHCI_Ich1", "" }, + { UHCI_Ich3m, "UHCI_Ich3m", "" }, + { UHCI_Ich4, "UHCI_Ich4", "" }, + { UHCI_Ich5, "UHCI_Ich5", "" }, + { UHCI_Ich6, "UHCI_Ich6", "" }, + { UHCI_Intel, "UHCI_Intel", "" }, + { UHCI_VIA, "UHCI_VIA", "" }, + { UHCI_VIA_x01, "UHCI_VIA_x01", "" }, + { UHCI_VIA_x02, "UHCI_VIA_x02", "" }, + { UHCI_VIA_x03, "UHCI_VIA_x03", "" }, + { UHCI_VIA_x04, "UHCI_VIA_x04", "" }, + { UHCI_VIA_x0E_FIFO, "UHCI_VIA_x0E_FIFO", "" }, + { EHCI_Generic, "EHCI_Generic", "" }, + { EHCI_NEC, "EHCI_NEC", "" }, + { EHCI_Lucent, "EHCI_Lucent", "" }, + { EHCI_NVIDIA_Tegra2, "EHCI_NVIDIA_Tegra2", "" }, + { EHCI_NVIDIA_Tegra3, "EHCI_NVIDIA_Tegra3", "" }, + { EHCI_Intel_Medfield, "EHCI_Intel_Medfield", "" } +}; + +// +// For supporting pre Win8 versions of Windows, a hardcoded list is maintained for determining +// debug port numbers. As usbport.inf is augmented with new host controllers, this list should +// be updated. +// +// The following entries do not have a debug port: +// PCI\VEN_8086&DEV_0806 - "Intel(R) SM35 Express Chipset USB2 Enhanced Host Controller MPH - 0806" +// PCI\VEN_8086&DEV_0811 - "Intel(R) SM35 Express Chipset USB2 Enhanced Host Controller SPM - 0811" +// + +EHCI_CONTROLLER_DATA EhciControllerData[] = +{ + {0x8086, 0x24CD, 1}, // ICH4 - Intel(R) 82801DB/DBM USB 2.0 Enhanced Host Controller - 24CD + {0x8086, 0x24DD, 1}, // ICH5 - Intel(R) 82801EB USB2 Enhanced Host Controller - 24DD + {0x8086, 0x25AD, 1}, // ICH5 - Intel(R) 6300ESB USB2 Enhanced Host Controller - 25AD + {0x8086, 0x265C, 1}, // ICH6 - Intel(R) 82801FB/FBM USB2 Enhanced Host Controller - 265C + {0x8086, 0x268C, 1}, // Intel(R) 631xESB/6321ESB/3100 Chipset USB2 Enhanced Host Controller - 268C + {0x8086, 0x27CC, 1}, // ICH7 - Intel(R) 82801G (ICH7 Family) USB2 Enhanced Host Controller - 27CC + {0x8086, 0x2836, 1}, // ICH8 - Intel(R) ICH8 Family USB2 Enhanced Host Controller - 2836 + {0x8086, 0x283A, 1}, // ICH8 - Intel(R) ICH8 Family USB2 Enhanced Host Controller - 283A + {0x8086, 0x293A, 1}, // ICH9 - Intel(R) ICH9 Family USB2 Enhanced Host Controller - 293A + {0x8086, 0x293C, 1}, // ICH9 - Intel(R) ICH9 Family USB2 Enhanced Host Controller - 293C + {0x8086, 0x3A3A, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A3A + {0x8086, 0x3A3C, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A3C + {0x8086, 0x3A6A, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A6A + {0x8086, 0x3A6C, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A6C + {0x8086, 0x3B34, 2}, // 5 series - Intel(R) 5 Series/3400 Series Chipset Family USB Enhanced Host Controller - 3B34 + {0x8086, 0x3B36, 2}, // 5 series - Intel(R) 5 Series/3400 Series Chipset Family USB Universal Host Controller - 3B36 + {0x8086, 0x1C26, 2}, // 6 series - Intel(R) 6 Series/C200 Series Chipset Family USB Enhanced Host Controller - 1C26 + {0x8086, 0x1C2D, 2}, // 6 series - Intel(R) 6 Series/C200 Series Chipset Family USB Enhanced Host Controller - 1C2D + {0x8086, 0x1D26, 2}, // Intel(R) C600/X79 series chipset USB2 Enhanced Host Controller #1 - 1D26 + {0x8086, 0x1D2D, 2}, // Intel(R) C600/X79 series chipset USB2 Enhanced Host Controller #2 - 1D2D + {0x8086, 0x268C, 1}, // Intel(R) 631xESB/6321ESB/3100 Chipset USB2 Enhanced Host Controller - 268C + {0x10DE, 0x00D8, 1}, + {0,0,0}, +}; + + +/***************************************************************************** +L O C A L F U N C T I O N P R O T O T Y P E S +*****************************************************************************/ + +VOID +DisplayPortConnectorProperties ( + _In_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 + ); + +void +DisplayDevicePowerState ( + _In_ PDEVICE_INFO_NODE DeviceInfoNode + ); + +VOID +DisplayHubInfo ( + PUSB_HUB_INFORMATION HubInfo, + BOOL DisplayDescriptor + ); + +VOID +DisplayHubInfoEx ( + PUSB_HUB_INFORMATION_EX HubInfoEx + ); + +VOID +DisplayHubCapabilityEx ( + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx + ); + +VOID +DisplayPowerState( + PUSB_POWER_INFO pUPI + ); + +VOID +DisplayConnectionInfo ( + _In_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, + _In_ PUSBDEVICEINFO info, + _In_ PSTRING_DESCRIPTOR_NODE StringDescs, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 + ); + +VOID +DisplayPipeInfo ( + ULONG NumPipes, + USB_PIPE_INFO *PipeInfo + ); + +VOID +DisplayConfigDesc ( + PUSBDEVICEINFO info, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ); + +VOID +DisplayBosDescriptor ( + PUSBDEVICEINFO info, + PUSB_BOS_DESCRIPTOR BosDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ); + +VOID +DisplayBillboardCapabilityDescriptor ( + PUSBDEVICEINFO info, + PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR billboardCapDesc, + PSTRING_DESCRIPTOR_NODE StringDescs +); + +VOID +DisplayDeviceQualifierDescriptor ( + PUSB_DEVICE_QUALIFIER_DESCRIPTOR DevQualDesc + ); + +VOID +DisplayConfigurationDescriptor ( + PUSBDEVICEINFO info, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ); + +VOID +DisplayInterfaceDescriptor ( + PUSB_INTERFACE_DESCRIPTOR InterfaceDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +VOID +DisplayEndpointDescriptor ( + _In_ PUSB_ENDPOINT_DESCRIPTOR + EndpointDesc, + _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR + EpCompDesc, + _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR + SspIsochCompDesc, + _In_ UCHAR InterfaceClass, + _In_ BOOLEAN EpCompDescAvail + ); + +VOID +DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor( + _In_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR SspIsochEpCompDesc + ); + +VOID +DisplayEndointCompanionDescriptor ( + _In_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR EpCompDesc, + _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR + SspIsochEpCompDesc, + _In_ UCHAR DescType + ); + + +VOID +DisplayHidDescriptor ( + PUSB_HID_DESCRIPTOR HidDesc + ); + +VOID +DisplayOTGDescriptor ( + PUSB_OTG_DESCRIPTOR OTGDesc + ); + +void +InitializePerDeviceSettings ( + PUSBDEVICEINFO info + ); + +UINT +IsUVCDevice ( + PUSBDEVICEINFO info + ); + +VOID +DisplayIADDescriptor ( + PUSB_IAD_DESCRIPTOR IADDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + int nInterfaces, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +VOID +DisplayUSEnglishStringDescriptor ( + UCHAR Index, + PSTRING_DESCRIPTOR_NODE USStringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +VOID +DisplayUnknownDescriptor ( + PUSB_COMMON_DESCRIPTOR CommonDesc + ); + +VOID +DisplayRemainingUnknownDescriptor( + PUCHAR DescriptorData, + ULONG Start, + ULONG Stop + ); + +PCHAR +GetVendorString ( + USHORT idVendor + ); + +PCHAR +GetLangIDString ( + USHORT idLang + ); + +UINT +GetConfigurationSize ( + PUSBDEVICEINFO info + ); + +UINT +GetInterfaceCount ( + PUSBDEVICEINFO info + ); + + +/***************************************************************************** +L O C A L F U N C T I O N S +*****************************************************************************/ + +/***************************************************************************** + +NextDescriptor() + +*****************************************************************************/ +//__forceinline +PUSB_COMMON_DESCRIPTOR +NextDescriptor( + _In_ PUSB_COMMON_DESCRIPTOR Descriptor + ) +{ + if (Descriptor->bLength == 0) + { + return NULL; + } + return (PUSB_COMMON_DESCRIPTOR)((PUCHAR)Descriptor + Descriptor->bLength); +} + +/***************************************************************************** + +GetNextDescriptor() + +*****************************************************************************/ +PUSB_COMMON_DESCRIPTOR +GetNextDescriptor( + _In_reads_bytes_(TotalLength) + PUSB_COMMON_DESCRIPTOR FirstDescriptor, + _In_ + ULONG TotalLength, + _In_ + PUSB_COMMON_DESCRIPTOR StartDescriptor, + _In_ long + DescriptorType + ) +{ + PUSB_COMMON_DESCRIPTOR currentDescriptor = NULL; + PUSB_COMMON_DESCRIPTOR endDescriptor = NULL; + + endDescriptor = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)FirstDescriptor + TotalLength); + + if (StartDescriptor >= endDescriptor || + NextDescriptor(StartDescriptor)>= endDescriptor) + { + return NULL; + } + + if (DescriptorType == -1) // -1 means any type + { + return NextDescriptor(StartDescriptor); + } + + currentDescriptor = StartDescriptor; + + while (((currentDescriptor = NextDescriptor(currentDescriptor)) < endDescriptor) + && currentDescriptor != NULL) + { + if (currentDescriptor->bDescriptorType == (UCHAR)DescriptorType) + { + return currentDescriptor; + } + } + return NULL; +} + + + +/***************************************************************************** + +CreateTextBuffer() + +*****************************************************************************/ + +BOOL +CreateTextBuffer ( + ) +{ + // Allocate the buffer + // + TextBuffer = ALLOC(BUFFERALLOCINCREMENT); + + if (TextBuffer == NULL) + { + OOPS(); + + return FALSE; + } + + TextBufferLen = BUFFERALLOCINCREMENT; + + // Reset the buffer position and terminate the buffer + // + memset(TextBuffer, 0, BUFFERALLOCINCREMENT); + TextBufferPos = 0; + + return TRUE; +} + + +/***************************************************************************** + +DestroyTextBuffer() + +*****************************************************************************/ + +VOID +DestroyTextBuffer ( + ) +{ + if (TextBuffer != NULL) + { + FREE(TextBuffer); + + TextBuffer = NULL; + } +} + + +/***************************************************************************** + +ResetTextBuffer() + +*****************************************************************************/ + +BOOL +ResetTextBuffer ( + ) +{ + // Fail if the text buffer has not been allocated + // + if (TextBuffer == NULL) + { + OOPS(); + + return FALSE; + } + + // Reset the buffer position and terminate the buffer + // + *TextBuffer = 0; + TextBufferPos = 0; + + return TRUE; +} + + +/***************************************************************************** + +GetTextBufferPos() + +*****************************************************************************/ + +UINT +GetTextBufferPos ( + ) +{ + return TextBufferPos; +} + + +/***************************************************************************** + +AppendTextBuffer() + +*****************************************************************************/ + +VOID __cdecl +AppendTextBuffer ( + LPCTSTR lpFormat, + ... + ) +{ + va_list arglist; + HRESULT hr = S_OK; + int nPos = TextBufferPos; + char LocalTextBuffer[512]; + + va_start(arglist, lpFormat); + + // Make sure we have a healthy amount of space free in the buffer, + // reallocating the buffer if necessary. + // + + if (TextBufferLen - TextBufferPos < BUFFERMINFREESPACE) + { + CHAR *TextBufferTmp; + UINT uNewTextBufferLen = 0; + hr = UIntAdd(TextBufferLen, BUFFERALLOCINCREMENT, &uNewTextBufferLen); + + if (hr != S_OK) + { + // we've exceeded DWORD length of (2^32)-1 for buffer + OOPS(); + + return; + } + + TextBufferTmp = REALLOC(TextBuffer, uNewTextBufferLen); + + if (TextBufferTmp != NULL) + { + TextBuffer = TextBufferTmp; + TextBufferLen += BUFFERALLOCINCREMENT; // update TextBufferLen to reflect the new, bigger size of the text buffer + } + else + { + // If GlobalReAlloc fails, the original memory is not freed, + // and the original handle and pointer are still valid. + // + + OOPS(); + + return; + } + } + + // Add the text to the end of the buffer + // + hr = StringCchVPrintf(LocalTextBuffer, sizeof(LocalTextBuffer), lpFormat, arglist); + if (SUCCEEDED(hr)) + { + size_t cbMax = 512; + size_t pcb = 0; + + // Ensure TextBuffer is zero terminated + // The text buffer size is specified by TextBufferLen. + // the text buffer size will be bigger than BUFFERALLOCINCREMENT if the buffer has been reallocated more than + // once (which would happen if it had to be made bigger to hold more text) + hr = StringCbLength((LPCTSTR) TextBuffer, + TextBufferLen, // the maximum number of bytes allowed in TextBuffer. + &pcb); + + if (FAILED(hr)) // buffer is not null-terminated, go ahead and do that + { + TextBuffer[TextBufferLen-1] = 0; + } + hr = StringCbLength((LPCTSTR) LocalTextBuffer, cbMax, &pcb); + if (SUCCEEDED(hr)) + { + StringCbCatN(TextBuffer, TextBufferLen, LocalTextBuffer, pcb); + + // Increment the text position by the number of charcters we just added to it. + TextBufferPos += (UINT) pcb; + } + + // If DebugLog flag set, send output to the debugger + // + if (gLogDebug) + { + OutputDebugString(TextBuffer + nPos); // print the string just added to the text buffer + } + } +} + +//***************************************************************************** +// +// GetTextBuffer +// +// Returns the display text buffer +// +//***************************************************************************** +PCHAR GetTextBuffer(void) +{ + return (TextBuffer); +} + + +//***************************************************************************** +// +// GetEhciDebugPort +// +// Returns debug port value if present for EHCI controller. 0 if its not present +// +//***************************************************************************** +ULONG GetEhciDebugPort(ULONG vendorId, ULONG deviceId) +{ + int i = 0; + ULONG debugPort = 0; + + for (i = 0; EhciControllerData[i].VendorID != 0; i++) + { + if (vendorId == EhciControllerData[i].VendorID && + deviceId == EhciControllerData[i].DeviceID) + { + debugPort = EhciControllerData[i].DebugPortNumber; + break; + } + } + + return debugPort; +} + +//***************************************************************************** +// +// UpdateTreeItemDeviceInfo +// +// hTreeItem - Handle of selected TreeView item for which information should +// be added to the TextBuffer global +// +// The functions returns error status if AppendTextBuffer() used in Display*() functions +// fails. The display text would be missing or truncated in such cases. +//***************************************************************************** +HRESULT +UpdateTreeItemDeviceInfo( + HWND hTreeWnd, + HTREEITEM hTreeItem + ) +{ + TV_ITEM tvi; + PVOID info; + ULONG i; + HRESULT hr = S_OK; + PCHAR tviName = NULL; + + SetLastError(0); + +#ifndef H264_SUPPORT + UNREFERENCED_PARAMETER(bShowVersion) +#endif + +#ifdef H264_SUPPORT + ResetErrorCounts(); +#endif + + tviName = ALLOC(256); + + if(NULL == tviName) + { + OOPS(); + hr = E_OUTOFMEMORY; + return hr; + } + + // + // Get the name of the TreeView item, along with the a pointer to the + // info we stored about the item in the item's lParam. + // + + tvi.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM; + tvi.hItem = hTreeItem; + tvi.pszText = (LPSTR) tviName; + tvi.cchTextMax = 256; + + TreeView_GetItem(hTreeWnd, + &tvi); + + info = (PVOID)tvi.lParam; + + AppendTextBuffer(tviName); + AppendTextBuffer("\r\n"); + + // + // If we didn't store any info for the item, just display the item's + // name, else display the info we stored for the item. + // + if (NULL != info) + { + PUSB_NODE_INFORMATION HubInfo = NULL; + PCHAR HubName = NULL; + PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo = NULL; + PUSB_DESCRIPTOR_REQUEST ConfigDesc = NULL; + PSTRING_DESCRIPTOR_NODE StringDescs = NULL; + PUSB_HUB_INFORMATION_EX HubInfoEx = NULL; + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx = NULL; + PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps = NULL; + PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 = NULL; + PUSB_DESCRIPTOR_REQUEST BosDesc = NULL; + PDEVICE_INFO_NODE DeviceInfoNode = NULL; + + // The TextBuffer has the TreeView name; add 2 lines for display + AppendTextBuffer("\r\n\r\n"); + + switch (*(PUSBDEVICEINFOTYPE)info) + { + case HostControllerInfo: + { + HTREEITEM rootHubItem = NULL; + BOOL dbgPortFound = FALSE; + + AppendTextBuffer("DriverKey: %s\r\n", + ((PUSBHOSTCONTROLLERINFO)info)->DriverKey); + + AppendTextBuffer("VendorID: %04X\r\n", + ((PUSBHOSTCONTROLLERINFO)info)->VendorID); + + AppendTextBuffer("DeviceID: %04X\r\n", + ((PUSBHOSTCONTROLLERINFO)info)->DeviceID); + + AppendTextBuffer("SubSysID: %08X\r\n", + ((PUSBHOSTCONTROLLERINFO)info)->SubSysID); + + AppendTextBuffer("Revision: %02X\r\n", + ((PUSBHOSTCONTROLLERINFO)info)->Revision); + + // + // Search for the debug port number. If running on Win8 or later, + // the USB_PORT_CONNECTOR_PROPERTIES structure will contain the + // port number. If that fails, the list of known host controllers + // with debug ports will be searched. + // + + AppendTextBuffer("\r\nDebug Port Number: "); + + rootHubItem = TreeView_GetChild(hTreeWnd, hTreeItem); + + if (rootHubItem != NULL) + { + HTREEITEM portItem = NULL; + PVOID portInfo; + + portItem = TreeView_GetChild(hTreeWnd, rootHubItem); + + while (portItem != NULL) + { + tvi.mask = TVIF_PARAM; + tvi.hItem = portItem; + tvi.pszText = NULL; + tvi.cchTextMax = 0; + + TreeView_GetItem(hTreeWnd, &tvi); + + portInfo = (PVOID)tvi.lParam; + + // + // Note that an empty port is a port without a device attached + // is still a DeviceInfo instance. + // + + if ((*(PUSBDEVICEINFOTYPE)portInfo) == DeviceInfo) + { + ConnectionInfo = ((PUSBDEVICEINFO)portInfo)->ConnectionInfo; + PortConnectorProps = ((PUSBDEVICEINFO)portInfo)->PortConnectorProps; + } + else if ((*(PUSBDEVICEINFOTYPE)portInfo) == ExternalHubInfo) + { + ConnectionInfo = ((PUSBEXTERNALHUBINFO)portInfo)->ConnectionInfo; + PortConnectorProps = ((PUSBEXTERNALHUBINFO)portInfo)->PortConnectorProps; + + } + + if (ConnectionInfo != NULL && + PortConnectorProps != NULL && + PortConnectorProps->UsbPortProperties.PortIsDebugCapable) + { + dbgPortFound = TRUE; + AppendTextBuffer("%d\r\n", ((PUSBDEVICEINFO)portInfo)->ConnectionInfo->ConnectionIndex); + break; + } + portItem = TreeView_GetNextSibling(hTreeWnd, portItem); + } + + // + // Resetting ConnectionInfo and PortConnectorProps to NULL so that they won't be erroneously + // be displayed below. + // + + ConnectionInfo = NULL; + PortConnectorProps = NULL; + } + if (dbgPortFound == FALSE) + { + for (i = 0; EhciControllerData[i].VendorID; i++) + { + if (((PUSBHOSTCONTROLLERINFO)info)->VendorID == + EhciControllerData[i].VendorID && + ((PUSBHOSTCONTROLLERINFO)info)->DeviceID == + EhciControllerData[i].DeviceID) + { + dbgPortFound = TRUE; + AppendTextBuffer("%d\r\n", EhciControllerData[i].DebugPortNumber); + break; + } + } + } + if (dbgPortFound == FALSE) + { + AppendTextBuffer("None\r\n"); + } + + // + // Display bus/device/function to help with setting debug + // settings. + // + if (((PUSBHOSTCONTROLLERINFO)info)->BusDeviceFunctionValid) + { + AppendTextBuffer("Bus.Device.Function (in decimal): %d.%d.%d\r\n", + ((PUSBHOSTCONTROLLERINFO)info)->BusNumber, + ((PUSBHOSTCONTROLLERINFO)info)->BusDevice, + ((PUSBHOSTCONTROLLERINFO)info)->BusFunction); + } + + // Display the USB Host Controller Power State Info + { + PUSB_POWER_INFO pUPI = (PUSB_POWER_INFO) &((PUSBHOSTCONTROLLERINFO)info)->USBPowerInfo[0]; + int nIndex = 0; + int nPowerState = WdmUsbPowerSystemWorking; + + AppendTextBuffer("\r\nHost Controller Power State Mappings\r\n"); + AppendTextBuffer("System State\t\tHost Controller\t\tRoot Hub\tUSB wakeup\tPowered\r\n"); + for ( ; nPowerState < WdmUsbPowerSystemShutdown; nIndex++, nPowerState++, pUPI++) + { + DisplayPowerState(pUPI); + } + + AppendTextBuffer("%s\t%s\r\n", + "Last Sleep State", + GetPowerStateString(pUPI->LastSystemSleepState) + ); + } + + break; + } + + case RootHubInfo: + HubInfo = ((PUSBROOTHUBINFO)info)->HubInfo; + HubName = ((PUSBROOTHUBINFO)info)->HubName; + HubCapabilityEx = ((PUSBROOTHUBINFO)info)->HubCapabilityEx; + + AppendTextBuffer("Root Hub: %s\r\n", + HubName); + + break; + + case ExternalHubInfo: + HubInfo = ((PUSBEXTERNALHUBINFO)info)->HubInfo; + HubName = ((PUSBEXTERNALHUBINFO)info)->HubName; + HubInfoEx = ((PUSBEXTERNALHUBINFO)info)->HubInfoEx; + HubCapabilityEx = ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx; + ConnectionInfo = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo; + ConnectionInfoV2 = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2; + PortConnectorProps = ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps; + ConfigDesc = ((PUSBEXTERNALHUBINFO)info)->ConfigDesc; + StringDescs = ((PUSBEXTERNALHUBINFO)info)->StringDescs; + BosDesc = ((PUSBEXTERNALHUBINFO)info)->BosDesc; + DeviceInfoNode = ((PUSBEXTERNALHUBINFO)info)->DeviceInfoNode; + + AppendTextBuffer("External Hub: %s\r\n", + HubName); + break; + + case DeviceInfo: + ConnectionInfo = ((PUSBDEVICEINFO)info)->ConnectionInfo; + ConnectionInfoV2 = ((PUSBDEVICEINFO)info)->ConnectionInfoV2; + PortConnectorProps = ((PUSBDEVICEINFO)info)->PortConnectorProps; + ConfigDesc = ((PUSBDEVICEINFO)info)->ConfigDesc; + StringDescs = ((PUSBDEVICEINFO)info)->StringDescs; + BosDesc = ((PUSBDEVICEINFO)info)->BosDesc; + DeviceInfoNode = ((PUSBDEVICEINFO)info)->DeviceInfoNode; + break; + } + + if (PortConnectorProps) + { + DisplayPortConnectorProperties(PortConnectorProps, ConnectionInfoV2); + } + + if (DeviceInfoNode) + { + DisplayDevicePowerState(DeviceInfoNode); + } + + if (HubInfo) + { + DisplayHubInfo(&HubInfo->u.HubInformation, + (HubInfoEx == NULL)); + } + + if (HubInfoEx) + { + DisplayHubInfoEx(HubInfoEx); + } + + if(HubCapabilityEx) + { + DisplayHubCapabilityEx(HubCapabilityEx); + } + + if (ConnectionInfo) + { + DisplayConnectionInfo(ConnectionInfo, + (PUSBDEVICEINFO)info, + StringDescs, + ConnectionInfoV2); + } + + if (ConfigDesc) + { + DisplayConfigDesc((PUSBDEVICEINFO)info, + (PUSB_CONFIGURATION_DESCRIPTOR)(ConfigDesc + 1), + StringDescs); + } + + if (BosDesc) + { + DisplayBosDescriptor((PUSBDEVICEINFO) info, + (PUSB_BOS_DESCRIPTOR) (BosDesc + 1), + StringDescs); + } + } + + if(tviName != NULL) + { + FREE(tviName); + } + + // AppendTextBuffer() which is used in Display*() functions uses GlobalRealloc() which can fail if realloc fails. + // Obtain last error code from GetLastError() and propagate the error to caller. + hr = HRESULT_FROM_WIN32(GetLastError()); + + return hr; +} + +//***************************************************************************** +// +// UpdateEditControl() +// +// hTreeItem - Handle of selected TreeView item for which information should +// be displayed in the edit control. +// +//***************************************************************************** + +VOID +UpdateEditControl ( + HWND hEditWnd, + HWND hTreeWnd, + HTREEITEM hTreeItem +) +{ + HRESULT hr = S_OK; + + // Start with an empty text buffer. + // + if (!ResetTextBuffer()) + { + return; + } + + // Get the item information in global TextBuffer + hr = UpdateTreeItemDeviceInfo(hTreeWnd, hTreeItem); + + if(FAILED(hr)) + { + OOPS(); + } + + // All done formatting text buffer with info, now update the edit + // control with the contents of the text buffer + // + SetWindowText(hEditWnd, TextBuffer); + +} + +/***************************************************************************** + +DisplayPortConnectorProperties() + +PortConnectorProps - Info about the port connector properties. + +*****************************************************************************/ + +void +DisplayPortConnectorProperties ( + _In_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 + ) +{ + AppendTextBuffer("Is Port User Connectable: %s\r\n", + PortConnectorProps->UsbPortProperties.PortIsUserConnectable + ? "yes" : "no"); + + AppendTextBuffer("Is Port Debug Capable: %s\r\n", + PortConnectorProps->UsbPortProperties.PortIsDebugCapable + ? "yes" : "no"); + AppendTextBuffer("Companion Port Number: %d\r\n", + PortConnectorProps->CompanionPortNumber); + AppendTextBuffer("Companion Hub Symbolic Link Name: %ws\r\n", + PortConnectorProps->CompanionHubSymbolicLinkName); + if (ConnectionInfoV2 != NULL) + { + AppendTextBuffer("Protocols Supported:\r\n"); + AppendTextBuffer(" USB 1.1: %s\r\n", + ConnectionInfoV2->SupportedUsbProtocols.Usb110 + ? "yes" : "no"); + AppendTextBuffer(" USB 2.0: %s\r\n", + ConnectionInfoV2->SupportedUsbProtocols.Usb200 + ? "yes" : "no"); + AppendTextBuffer(" USB 3.0: %s\r\n", + ConnectionInfoV2->SupportedUsbProtocols.Usb300 + ? "yes" : "no"); + } + + AppendTextBuffer("\r\n"); +} + +/***************************************************************************** + +DisplayDevicePowerState() + +DeviceInfoNode - Structure containing info used to acquire device state + +*****************************************************************************/ + +void +DisplayDevicePowerState ( + _In_ PDEVICE_INFO_NODE DeviceInfoNode + ) +{ + + DEVICE_POWER_STATE powerState; + + powerState = AcquireDevicePowerState(DeviceInfoNode); + + AppendTextBuffer("Device Power State: "); + if (powerState >= PowerDeviceD0 && powerState <= PowerDeviceD3) + { + AppendTextBuffer("PowerDeviceD%d\r\n", powerState-1); + } + else + { + AppendTextBuffer("Invalid Device Power State Value %d\r\n", powerState); + } + + AppendTextBuffer("\r\n"); +} + + +/***************************************************************************** + +DisplayHubDescriptorBase() + +HubDescriptor - hub descriptor, could also be PUSB_30_HUB_DESCRIPTOR which has + these field in common at the beginning of the data structure: + + - UCHAR bLength; + - UCHAR bDescriptorType; + - UCHAR bNumberOfPorts; + - USHORT wHubCharacteristics; + - UCHAR bPowerOnToPowerGood; + - UCHAR bHubControlCurrent; + +*****************************************************************************/ +VOID +DisplayHubDescriptorBase( + PUSB_HUB_DESCRIPTOR HubDescriptor + ) +{ + USHORT wHubChar = 0; + + AppendTextBuffer("Number of Ports: %d\r\n", + HubDescriptor->bNumberOfPorts); + + wHubChar = HubDescriptor->wHubCharacteristics; + + switch (wHubChar & 0x0003) + { + case 0x0000: + AppendTextBuffer("Power switching: Ganged\r\n"); + break; + + case 0x0001: + AppendTextBuffer("Power switching: Individual\r\n"); + break; + + case 0x0002: + case 0x0003: + AppendTextBuffer("Power switching: None\r\n"); + break; + } + + switch (wHubChar & 0x0004) + { + case 0x0000: + AppendTextBuffer("Compound device: No\r\n"); + break; + + case 0x0004: + AppendTextBuffer("Compound device: Yes\r\n"); + break; + } + + switch (wHubChar & 0x0018) + { + case 0x0000: + AppendTextBuffer("Over-current Protection: Global\r\n"); + break; + + case 0x0008: + AppendTextBuffer("Over-current Protection: Individual\r\n"); + break; + + case 0x0010: + case 0x0018: + AppendTextBuffer("No Over-current Protection (Bus Power Only)\r\n"); + break; + } +} + + + +/***************************************************************************** + +DisplayHubInfo() + +HubInfo - Info about the hub. + +*****************************************************************************/ + +VOID +DisplayHubInfo ( + PUSB_HUB_INFORMATION HubInfo, + BOOL DisplayDescriptor + ) +{ + AppendTextBuffer("Hub Power: %s\r\n", + HubInfo->HubIsBusPowered ? + "Bus Power" : "Self Power"); + + if (DisplayDescriptor == TRUE) + { + DisplayHubDescriptorBase(&HubInfo->HubDescriptor); + } +} + +/***************************************************************************** + +DisplayHubInfoEx() + +HubInfo - Extended info about the hub. + +*****************************************************************************/ + + +VOID +DisplayHubInfoEx ( + PUSB_HUB_INFORMATION_EX HubInfoEx + ) +{ + AppendTextBuffer("Hub type: "); + + switch (HubInfoEx->HubType) { + + case UsbRootHub: + AppendTextBuffer("USB Root Hub\r\n"); + break; + + case Usb20Hub: + AppendTextBuffer("USB 2.0 Hub\r\n"); + DisplayHubDescriptorBase((PUSB_HUB_DESCRIPTOR)&HubInfoEx->u.UsbHubDescriptor); + break; + + case Usb30Hub: + AppendTextBuffer("USB 3.0 Hub\r\n"); + + // + // Note that the DisplayHubDescriptorBase will display the fields of either + // the legacy hub descriptor and the USB 3.0 descriptor which have the same + // offset + // + + DisplayHubDescriptorBase((PUSB_HUB_DESCRIPTOR)&HubInfoEx->u.UsbHubDescriptor); + AppendTextBuffer("Packet Header Decode Latency: 0x%x\r\n", HubInfoEx->u.Usb30HubDescriptor.bHubHdrDecLat); + AppendTextBuffer("Delay: 0x%x ns\r\n", HubInfoEx->u.Usb30HubDescriptor.wHubDelay); + + break; + + default: + AppendTextBuffer("ERROR: Unknown hub type %d\r\n", HubInfoEx->HubType); + break; + } + + AppendTextBuffer("\r\n"); +} + + + +/***************************************************************************** + +DisplayHubCapabilityEx() + +HubCapabilityInfo - Hub capability information + +*****************************************************************************/ + +VOID +DisplayHubCapabilityEx ( + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx + ) +{ + if(HubCapabilityEx != NULL) + { + AppendTextBuffer("High speed capable: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsHighSpeedCapable + ? "Yes" : "No"); + AppendTextBuffer("High speed: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsHighSpeed + ? "Yes" : "No"); + AppendTextBuffer("Multiple transaction translations capable: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsMultiTtCapable + ? "Yes" : "No"); + AppendTextBuffer("Performs multiple transaction translations simultaneously: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsMultiTt + ? "Yes" : "No"); + AppendTextBuffer("Hub wakes when device is connected: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsArmedWakeOnConnect + ? "Yes" : "No"); + AppendTextBuffer("Hub is bus powered: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsBusPowered + ? "Yes" : "No"); + AppendTextBuffer("Hub is root: %s\r\n", + HubCapabilityEx->CapabilityFlags.HubIsRoot + ? "Yes" : "No"); + } +} + +/***************************************************************************** + +DisplayConnectionInfo() + +ConnectInfo - Info about the connection. + +PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, +PSTRING_DESCRIPTOR_NODE StringDescs + +DisplayConnectionInfo(info->ConnectionInfo, +info->StringDescs); + +DisplayConnectionInfo ( +PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, +PSTRING_DESCRIPTOR_NODE StringDescs +) + +*****************************************************************************/ + +VOID +DisplayConnectionInfo ( + _In_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, + _In_ PUSBDEVICEINFO info, + _In_ PSTRING_DESCRIPTOR_NODE StringDescs, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 +) +{ + + //@@DisplayConnectionInfo - Device Information + PCHAR VendorString = NULL; + UINT tog = 1; + UINT uIADcount = 0; + + // No device connected + if (ConnectInfo->ConnectionStatus == NoDeviceConnected) + { + AppendTextBuffer("ConnectionStatus: NoDeviceConnected\r\n"); + return; + } + + // This is the entry point to the device display functions. + // First, save this device's PUSBDEVICEINFO address + // In a future version of this test, we will keep track of the the + // descriptor that we're parsing (# of bytes from beginning of info->configuration descriptor) + // Then we can linked descriptors by reading forward through the remaining descriptors + // while still keeping our place in this main DisplayConnectionInfo() and called + // functions. + // + // We also initialize some global flags in uvcview.h that are used to + // verify items in MJPEG, Uncompressed and Vendor Frame descriptors + // + InitializePerDeviceSettings(info); + + if(gDoAnnotation) + { + + AppendTextBuffer(" ---===>Device Information<===---\r\n"); + + if (ConnectInfo->DeviceDescriptor.iProduct) + { + DisplayUSEnglishStringDescriptor(ConnectInfo->DeviceDescriptor.iProduct, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + } + + AppendTextBuffer("\r\nConnectionStatus: %s\r\n", + ConnectionStatuses[ConnectInfo->ConnectionStatus]); + + AppendTextBuffer("Current Config Value: 0x%02X", + ConnectInfo->CurrentConfigurationValue); + } + + switch (ConnectInfo->Speed){ + case UsbLowSpeed: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Device Bus Speed: Low\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + gDeviceSpeed = UsbLowSpeed; + break; + + case UsbFullSpeed: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Device Bus Speed: Full"); + if (ConnectionInfoV2 != NULL) + { + if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedPlusCapableOrHigher) + { + AppendTextBuffer(" (is SuperSpeedPlus or higher capable)\r\n"); + } + else if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedCapableOrHigher) + { + AppendTextBuffer(" (is SuperSpeed or higher capable)\r\n"); + } + else + { + AppendTextBuffer(" (is not SuperSpeed or higher capable)\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + gDeviceSpeed = UsbFullSpeed; + break; + case UsbHighSpeed: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Device Bus Speed: High"); + if (ConnectionInfoV2 != NULL) + { + if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedPlusCapableOrHigher) + { + AppendTextBuffer(" (is SuperSpeedPlus or higher capable)\r\n"); + } + else if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedCapableOrHigher) + { + AppendTextBuffer(" (is SuperSpeed or higher capable)\r\n"); + } + else + { + AppendTextBuffer(" (is not SuperSpeed or higher capable)\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + gDeviceSpeed = UsbHighSpeed; + break; + + case UsbSuperSpeed: + if(gDoAnnotation) + { + if (ConnectionInfoV2 != NULL) + { + AppendTextBuffer(" -> Device Bus Speed: Super%s\r\n", + ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher + ? "SpeedPlus" + : "Speed"); + } + else + { + AppendTextBuffer(" -> Device Bus Speed: Super Speed\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + gDeviceSpeed = UsbSuperSpeed; + break; + + default: + if(gDoAnnotation){AppendTextBuffer(" -> Device Bus Speed: Unknown\r\n");} + else {AppendTextBuffer("\r\n");} + } + + if(gDoAnnotation){ + AppendTextBuffer("Device Address: 0x%02X\r\n", + ConnectInfo->DeviceAddress); + + AppendTextBuffer("Open Pipes: %2d\r\n", + ConnectInfo->NumberOfOpenPipes); + } + + // No open pipes means the USB stack has not loaded the device + if (ConnectInfo->NumberOfOpenPipes == 0) + { + AppendTextBuffer("*!*ERROR: No open pipes!\r\n"); + } + + AppendTextBuffer("\r\n ===>Device Descriptor<===\r\n"); + //@@DisplayConnectionInfo - Device Descriptor + + if (ConnectInfo->DeviceDescriptor.bLength != 18) + { + //@@TestCase A1.1 + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@ required length in the USB Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + ConnectInfo->DeviceDescriptor.bLength, + 18); + OOPS(); + } + + AppendTextBuffer("bLength: 0x%02X\r\n", + ConnectInfo->DeviceDescriptor.bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + ConnectInfo->DeviceDescriptor.bDescriptorType); + + //@@TestCase A1.2 + //@@Not implemented - Priority 1 + //@@Descriptor Field - bcdUSB + //@@Need to check that any UVC device is set to 0x0200 or later. + AppendTextBuffer("bcdUSB: 0x%04X\r\n", + ConnectInfo->DeviceDescriptor.bcdUSB); + + AppendTextBuffer("bDeviceClass: 0x%02X", + ConnectInfo->DeviceDescriptor.bDeviceClass); + + // Quit on these device failures + if ((ConnectInfo->ConnectionStatus == DeviceFailedEnumeration) || + (ConnectInfo->ConnectionStatus == DeviceGeneralFailure)) + { + AppendTextBuffer("\r\n*!*ERROR: Device enumeration failure\r\n"); + return; + } + + // Is this an IAD device? + uIADcount = IsIADDevice((PUSBDEVICEINFO) info); + + if (uIADcount) + { + // this device configuration has 1 or more IAD descriptors + if (ConnectInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE) + { + tog = 0; + if (gDoAnnotation) + { + AppendTextBuffer(" -> This is a Multi-interface Function Code Device\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + } else { + AppendTextBuffer("\r\n*!*ERROR: device class should be Multi-interface Function 0x%02X\r\n"\ + " When IAD descriptor is used\r\n", + USB_MISCELLANEOUS_DEVICE); + } + // Is this a UVC device? + g_chUVCversion = IsUVCDevice((PUSBDEVICEINFO) info); + } + else + { + // this is not an IAD device + switch (ConnectInfo->DeviceDescriptor.bDeviceClass) + { + case USB_INTERFACE_CLASS_DEVICE: + if(gDoAnnotation) + {AppendTextBuffer(" -> This is an Interface Class Defined Device\r\n");} + else {AppendTextBuffer("\r\n");} + break; + + case USB_COMMUNICATION_DEVICE: + tog = 0; + if(gDoAnnotation) + {AppendTextBuffer(" -> This is a Communication Device\r\n");} + else {AppendTextBuffer("\r\n");} + break; + + case USB_HUB_DEVICE: + tog = 0; + if(gDoAnnotation) + {AppendTextBuffer(" -> This is a HUB Device\r\n");} + else {AppendTextBuffer("\r\n");} + break; + + case USB_DIAGNOSTIC_DEVICE: + tog = 0; + if(gDoAnnotation) + {AppendTextBuffer(" -> This is a Diagnostic Device\r\n");} + else {AppendTextBuffer("\r\n");} + break; + + case USB_WIRELESS_CONTROLLER_DEVICE: + tog = 0; + if(gDoAnnotation) + {AppendTextBuffer(" -> This is a Wireless Controller(Bluetooth) Device\r\n");} + else {AppendTextBuffer("\r\n");} + break; + + case USB_VENDOR_SPECIFIC_DEVICE: + tog = 0; + if(gDoAnnotation) + {AppendTextBuffer(" -> This is a Vendor Specific Device\r\n");} + else {AppendTextBuffer("\r\n");} + break; + + case USB_DEVICE_CLASS_BILLBOARD: + tog = 0; + if (gDoAnnotation) + { + AppendTextBuffer(" -> This is a billboard class device\r\n"); + } + else { AppendTextBuffer("\r\n"); } + break; + + case USB_MISCELLANEOUS_DEVICE: + tog = 0; + //@@TestCase A1.3 + //@@ERROR + //@@Descriptor Field - bDeviceClass + //@@Multi-interface Function code used for non-IAD device + AppendTextBuffer("\r\n*!*ERROR: Multi-interface Function code %d used for "\ + "device with no IAD descriptors\r\n", + ConnectInfo->DeviceDescriptor.bDeviceClass); + break; + + default: + //@@TestCase A1.4 + //@@ERROR + //@@Descriptor Field - bDeviceClass + //@@An unknown device class has been defined + AppendTextBuffer("\r\n*!*ERROR: unknown bDeviceClass %d\r\n", + ConnectInfo->DeviceDescriptor.bDeviceClass); + OOPS(); + break; + } + } + + AppendTextBuffer("bDeviceSubClass: 0x%02X", + ConnectInfo->DeviceDescriptor.bDeviceSubClass); + + // check the subclass + if (uIADcount) + { + // this device configuration has 1 or more IAD descriptors + if (ConnectInfo->DeviceDescriptor.bDeviceSubClass == USB_COMMON_SUB_CLASS) + { + if (gDoAnnotation) + { + AppendTextBuffer(" -> This is the Common Class Sub Class\r\n"); + } else + { + AppendTextBuffer("\r\n"); + } + } + else + { + //@@TestCase A1.5 + //@@ERROR + //@@Descriptor Field - bDeviceSubClass + //@@An invalid device sub class used for Multi-interface Function (IAD) device + AppendTextBuffer("\r\n*!*ERROR: device SubClass should be USB Common Sub Class %d\r\n"\ + " When IAD descriptor is used\r\n", + USB_COMMON_SUB_CLASS); + OOPS(); + } + } + else + { + // Not an IAD device, so all subclass values are invalid + if(ConnectInfo->DeviceDescriptor.bDeviceSubClass > 0x00 && + ConnectInfo->DeviceDescriptor.bDeviceSubClass < 0xFF) + { + //@@TestCase A1.6 + //@@ERROR + //@@Descriptor Field - bDeviceSubClass + //@@An invalid device sub class has been defined + AppendTextBuffer("\r\n*!*ERROR: bDeviceSubClass of %d is invalid\r\n", + ConnectInfo->DeviceDescriptor.bDeviceSubClass); + OOPS(); + } else + { + AppendTextBuffer("\r\n"); + } + } + + AppendTextBuffer("bDeviceProtocol: 0x%02X", + ConnectInfo->DeviceDescriptor.bDeviceProtocol); + + // check the protocol + if (uIADcount) + { + // this device configuration has 1 or more IAD descriptors + if (ConnectInfo->DeviceDescriptor.bDeviceProtocol == USB_IAD_PROTOCOL) + { + if (gDoAnnotation) + { + AppendTextBuffer(" -> This is the Interface Association Descriptor protocol\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + } + else + { + //@@TestCase A1.7 + //@@ERROR + //@@Descriptor Field - bDeviceSubClass + //@@An invalid device sub class used for Multi-interface Function (IAD) device + AppendTextBuffer("\r\n*!*ERROR: device Protocol should be USB IAD Protocol %d\r\n"\ + " When IAD descriptor is used\r\n", + USB_IAD_PROTOCOL); + OOPS(); + } + } + else + { + // Not an IAD device, so all subclass values are invalid + if(ConnectInfo->DeviceDescriptor.bDeviceProtocol > 0x00 && + ConnectInfo->DeviceDescriptor.bDeviceProtocol < 0xFF && tog==1) + { + //@@TestCase A1.8 + //@@ERROR + //@@Descriptor Field - bDeviceProtocol + //@@An invalid device protocol has been defined + AppendTextBuffer("\r\n*!*ERROR: bDeviceProtocol of %d is invalid\r\n", + ConnectInfo->DeviceDescriptor.bDeviceProtocol); + OOPS(); + } + else + { + AppendTextBuffer("\r\n"); + } + } + + AppendTextBuffer("bMaxPacketSize0: 0x%02X", + ConnectInfo->DeviceDescriptor.bMaxPacketSize0); + + if(gDoAnnotation) + { + AppendTextBuffer(" = (%d) Bytes\r\n", + ConnectInfo->DeviceDescriptor.bMaxPacketSize0); + } + else + { + AppendTextBuffer("\r\n"); + } + + switch (gDeviceSpeed){ + case UsbLowSpeed: + if(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 != 8) + { + //@@TestCase A1.9 + //@@ERROR + //@@Descriptor Field - bMaxPacketSize0 + //@@An invalid bMaxPacketSize0 has been defined for a low speed device + AppendTextBuffer("*!*ERROR: Low Speed Devices require bMaxPacketSize0 = 8\r\n"); + OOPS(); + } + break; + case UsbFullSpeed: + if(!(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 8 || + ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 16 || + ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 32 || + ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 64)) + { + //@@TestCase A1.10 + //@@ERROR + //@@Descriptor Field - bMaxPacketSize0 + //@@An invalid bMaxPacketSize0 has been defined for a full speed device + AppendTextBuffer("*!*ERROR: Full Speed Devices require bMaxPacketSize0 = 8, 16, 32, or 64\r\n"); + OOPS(); + } + break; + case UsbHighSpeed: + if(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 != 64) + { + //@@TestCase A1.11 + //@@ERROR + //@@Descriptor Field - bMaxPacketSize0 + //@@An invalid bMaxPacketSize0 has been defined for a high speed device + AppendTextBuffer("*!*ERROR: High Speed Devices require bMaxPacketSize0 = 64\r\n"); + OOPS(); + } + break; + case UsbSuperSpeed: + if(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 != 9) + { + AppendTextBuffer("*!*ERROR: SuperSpeed Devices require bMaxPacketSize0 = 9 (512)\r\n"); + OOPS(); + } + break; + } + + AppendTextBuffer("idVendor: 0x%04X", + ConnectInfo->DeviceDescriptor.idVendor); + + if (gDoAnnotation) + { + VendorString = GetVendorString(ConnectInfo->DeviceDescriptor.idVendor); + if (VendorString != NULL) + { + AppendTextBuffer(" = %s\r\n", + VendorString); + } + } + else {AppendTextBuffer("\r\n");} + + AppendTextBuffer("idProduct: 0x%04X\r\n", + ConnectInfo->DeviceDescriptor.idProduct); + + AppendTextBuffer("bcdDevice: 0x%04X\r\n", + ConnectInfo->DeviceDescriptor.bcdDevice); + + AppendTextBuffer("iManufacturer: 0x%02X\r\n", + ConnectInfo->DeviceDescriptor.iManufacturer); + + if (ConnectInfo->DeviceDescriptor.iManufacturer && gDoAnnotation) + { + DisplayStringDescriptor(ConnectInfo->DeviceDescriptor.iManufacturer, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + } + + AppendTextBuffer("iProduct: 0x%02X\r\n", + ConnectInfo->DeviceDescriptor.iProduct); + + if (ConnectInfo->DeviceDescriptor.iProduct && gDoAnnotation) + { + DisplayStringDescriptor(ConnectInfo->DeviceDescriptor.iProduct, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + } + + AppendTextBuffer("iSerialNumber: 0x%02X\r\n", + ConnectInfo->DeviceDescriptor.iSerialNumber); + + if (ConnectInfo->DeviceDescriptor.iSerialNumber && gDoAnnotation) + { + DisplayStringDescriptor(ConnectInfo->DeviceDescriptor.iSerialNumber, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + } + + AppendTextBuffer("bNumConfigurations: 0x%02X\r\n", + ConnectInfo->DeviceDescriptor.bNumConfigurations); + + if(ConnectInfo->DeviceDescriptor.bNumConfigurations != 1) + { + //@@TestCase A1.12 + //@@CAUTION + //@@Descriptor Field - bNumConfigurations + //@@Most host controllers do not handle more than one configuration + AppendTextBuffer("*!*CAUTION: Most host controllers will only work with "\ + "one configuration per speed\r\n"); + OOPS(); + } + + if (ConnectInfo->NumberOfOpenPipes) + { + AppendTextBuffer("\r\n ---===>Open Pipes<===---\r\n"); + DisplayPipeInfo(ConnectInfo->NumberOfOpenPipes, + ConnectInfo->PipeList); + } + + return; +} + +/***************************************************************************** + +DisplayPipeInfo() + +NumPipes - Number of pipe for we info should be displayed. + +PipeInfo - Info about the pipes. + +*****************************************************************************/ + +VOID +DisplayPipeInfo ( + ULONG NumPipes, + USB_PIPE_INFO *PipeInfo + ) +{ + ULONG i = 0; + + for (i = 0; i < NumPipes; i++) + { + DisplayEndpointDescriptor(&PipeInfo[i].EndpointDescriptor, NULL, NULL, 0, FALSE); + } + +} + +/***************************************************************************** + +GetControllerFlavorString() + +Returns the text for given controller flavor + +*****************************************************************************/ +PCHAR GetControllerFlavorString(USB_CONTROLLER_FLAVOR flavor) +{ + return(GetStringFromList(slControllerFlavor, + sizeof(slControllerFlavor) / sizeof(STRINGLIST), + flavor, + STR_UNKNOWN_CONTROLLER_FLAVOR)); +} + + + +/***************************************************************************** + +GetPowerStateString() + +Returns the descriptive string for given power state + +*****************************************************************************/ +PCHAR GetPowerStateString(WDMUSB_POWER_STATE powerState) +{ + return(GetStringFromList(slPowerState, + sizeof(slPowerState) / sizeof(STRINGLIST), + powerState, + STR_INVALID_POWER_STATE)); +} + +/***************************************************************************** + +DisplayPowerState() + +PUSB_POWER_INFO pUPI - USBUSER.H USB_Power_Info data + +*****************************************************************************/ + +VOID +DisplayPowerState( + PUSB_POWER_INFO pUPI + ) +{ + AppendTextBuffer("%s\t%s\t%s%s\t\t%s\r\n", + GetPowerStateString(pUPI->SystemState), + GetPowerStateString(pUPI->HcDevicePowerState), + GetPowerStateString(pUPI->RhDevicePowerState), + pUPI->CanWakeup ? "Yes" : "", + pUPI->IsPowered ? "Yes" : "" + ); + return; +} + + + +/***************************************************************************** + +ValidateDescAddress() + +Given a descriptor address and the Configuration Descriptor length + (saved in DisplayConfigDesc(), and initialized for each new device) +return TRUE if the descriptor is within the Configuration length +else FALSE + +*****************************************************************************/ + +BOOL +ValidateDescAddress ( + PUSB_COMMON_DESCRIPTOR commonDesc + ) +{ + if ((PUCHAR) commonDesc + commonDesc->bLength <= g_descEnd) + { + return TRUE; + } + return FALSE; +} + +/***************************************************************************** + +DisplayConfigDesc() + +ConfigDesc - The Configuration Descriptor, and associated Interface and +Endpoint Descriptors + +*****************************************************************************/ + +VOID +DisplayConfigDesc ( + PUSBDEVICEINFO info, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ) +{ + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + UCHAR bInterfaceClass = 0; + UCHAR bInterfaceSubClass = 0; + UCHAR bInterfaceProtocol = 0; + BOOL displayUnknown = FALSE; + + BOOL isSS; + + isSS = info->ConnectionInfoV2 + && info->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher + ? TRUE + : FALSE; + + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + + // initialize global Configuration start/end address and string desc address + g_pConfigDesc = ConfigDesc; + g_pStringDescs = StringDescs; + g_descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + + AppendTextBuffer("\r\n ---===>Full Configuration Descriptor<===---\r\n"); + + do + { + displayUnknown = FALSE; + + switch (commonDesc->bDescriptorType) + { + case USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE: + //@@DisplayConfigDesc - Device Qualifier Descriptor + if (commonDesc->bLength != sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) + { + //@@TestCase A2.1 + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@ required length in the USB Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d for Device Qualifier incorrect, "\ + "should be %d\r\n", + commonDesc->bLength, + sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)); + OOPS(); + displayUnknown = TRUE; + break; + } + DisplayDeviceQualifierDescriptor((PUSB_DEVICE_QUALIFIER_DESCRIPTOR)commonDesc); + break; + + case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE: + //@@DisplayConfigDesc - Other Speed Configuration Descriptor + if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + //@@TestCase A2.2 + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@ required length in the USB Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d for Other Speed Configuration "\ + "incorrect, should be %d\r\n", + commonDesc->bLength, + sizeof(USB_CONFIGURATION_DESCRIPTOR)); + OOPS(); + displayUnknown = TRUE; + } + DisplayConfigurationDescriptor( + (PUSBDEVICEINFO) info, + (PUSB_CONFIGURATION_DESCRIPTOR)commonDesc, + StringDescs); + break; + + case USB_CONFIGURATION_DESCRIPTOR_TYPE: + //@@DisplayConfigDesc - Configuration Descriptor + if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + //@@TestCase A2.3 + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@required length in the USB Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d for Configuration incorrect, "\ + "should be %d\r\n", + commonDesc->bLength, + sizeof(USB_CONFIGURATION_DESCRIPTOR)); + OOPS(); + displayUnknown = TRUE; + break; + } + DisplayConfigurationDescriptor((PUSBDEVICEINFO)info, + (PUSB_CONFIGURATION_DESCRIPTOR)commonDesc, + StringDescs); + break; + + case USB_INTERFACE_DESCRIPTOR_TYPE: + //@@DisplayConfigDesc - Interface Descriptor + if ((commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR)) && + (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))) + { + //@@TestCase A2.4 + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@required length in the USB Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d for Interface incorrect, "\ + "should be %d or %d\r\n", + commonDesc->bLength, + sizeof(USB_INTERFACE_DESCRIPTOR), + sizeof(USB_INTERFACE_DESCRIPTOR2)); + OOPS(); + displayUnknown = TRUE; + break; + } + bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass; + bInterfaceSubClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceSubClass; + bInterfaceProtocol = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceProtocol; + + DisplayInterfaceDescriptor( + (PUSB_INTERFACE_DESCRIPTOR)commonDesc, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + + break; + + case USB_ENDPOINT_DESCRIPTOR_TYPE: + { + PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR epCompDesc = NULL; + PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR + sspIsochCompDesc = NULL; + + + //@@DisplayConfigDesc - Endpoint Descriptor + if ((commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR)) && + (commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR2))) + { + //@@TestCase A2.5 + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to + //@@ the required length in the USB Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d for Endpoint incorrect, "\ + "should be %d or %d\r\n", + commonDesc->bLength, + sizeof(USB_ENDPOINT_DESCRIPTOR), + sizeof(USB_ENDPOINT_DESCRIPTOR2)); + OOPS(); + displayUnknown = TRUE; + break; + } + + if (isSS) + { + epCompDesc = (PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR) + GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)ConfigDesc, ConfigDesc->wTotalLength, commonDesc, -1); + } + + if (epCompDesc != NULL && + epCompDesc->bmAttributes.Isochronous.SspCompanion == 1) + { + sspIsochCompDesc = (PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR) + GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)ConfigDesc, + ConfigDesc->wTotalLength, + (PUSB_COMMON_DESCRIPTOR)epCompDesc, + -1); + } + + DisplayEndpointDescriptor((PUSB_ENDPOINT_DESCRIPTOR)commonDesc, + epCompDesc, + sspIsochCompDesc, + bInterfaceClass, + TRUE); + + if (sspIsochCompDesc != NULL) + { + commonDesc = (PUSB_COMMON_DESCRIPTOR)sspIsochCompDesc; + } + else if (epCompDesc != NULL) + { + commonDesc = (PUSB_COMMON_DESCRIPTOR)epCompDesc; + } + } + + break; + + case USB_HID_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_HID_DESCRIPTOR)) + { + OOPS(); + displayUnknown = TRUE; + break; + } + DisplayHidDescriptor((PUSB_HID_DESCRIPTOR)commonDesc); + break; + + case USB_OTG_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_OTG_DESCRIPTOR)) + { + OOPS(); + displayUnknown = TRUE; + break; + } + DisplayOTGDescriptor((PUSB_OTG_DESCRIPTOR)commonDesc); + break; + + case USB_IAD_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR)) + { + OOPS(); + displayUnknown = TRUE; + break; + } + DisplayIADDescriptor((PUSB_IAD_DESCRIPTOR)commonDesc, StringDescs, + ConfigDesc->bNumInterfaces, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + break; + + default: + //@@DisplayConfigDesc - Interface Class Device + // TODO: BUG: bInterfaceClass is initialized before this code + switch (bInterfaceClass) + { + case USB_DEVICE_CLASS_AUDIO: + displayUnknown = ! DisplayAudioDescriptor( + (PUSB_AUDIO_COMMON_DESCRIPTOR)commonDesc, + bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_VIDEO: + displayUnknown = ! DisplayVideoDescriptor( + (PVIDEO_SPECIFIC)commonDesc, + bInterfaceSubClass, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + break; + + case USB_DEVICE_CLASS_RESERVED: + //@@TestCase A2.6 + //@@ERROR + //@@Descriptor Field - bInterfaceClass + //@@An unknown interface class has been defined + AppendTextBuffer("*!*ERROR: %d is a Reserved USB Device Interface Class\r\n", + USB_DEVICE_CLASS_RESERVED); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_COMMUNICATIONS: + AppendTextBuffer(" -> This is a Communications (CDC Control) USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_HUMAN_INTERFACE: + AppendTextBuffer(" -> This is a HID USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_MONITOR: + AppendTextBuffer(" -> This is a Monitor USB Device Interface Class (This may be obsolete)\r\n"); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: + AppendTextBuffer(" -> This is a Physical Interface USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_POWER: + if(bInterfaceSubClass == 1 && bInterfaceProtocol == 1) + { + AppendTextBuffer(" -> This is an Image USB Device Interface Class\r\n"); + } + else + { + AppendTextBuffer(" -> This is a Power USB Device Interface Class (This may be obsolete)\r\n"); + } + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_PRINTER: + AppendTextBuffer(" -> This is a Printer USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_STORAGE: + AppendTextBuffer(" -> This is a Mass Storage USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_DEVICE_CLASS_HUB: + AppendTextBuffer(" -> This is a HUB USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_CDC_DATA_INTERFACE: + AppendTextBuffer(" -> This is a CDC Data USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_CHIP_SMART_CARD_INTERFACE: + AppendTextBuffer(" -> This is a Chip/Smart Card USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_CONTENT_SECURITY_INTERFACE: + AppendTextBuffer(" -> This is a Content Security USB Device Interface Class\r\n"); + displayUnknown = TRUE; + break; + + case USB_DIAGNOSTIC_DEVICE_INTERFACE: + if(bInterfaceSubClass == 1 && bInterfaceProtocol == 1) + { + AppendTextBuffer(" -> This is a Reprogrammable USB2 Compliance Diagnostic Device USB Device\r\n"); + } + else + { + //@@TestCase A2.7 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@An unknown diagnostic interface class device has been defined + AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + displayUnknown = TRUE; + break; + + case USB_WIRELESS_CONTROLLER_INTERFACE: + if(bInterfaceSubClass == 1 && bInterfaceProtocol == 1) + { + AppendTextBuffer(" -> This is a Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface\r\n"); + } + else + { + //@@TestCase A2.8 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@An unknown wireless controller interface class device has been defined + AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + displayUnknown = TRUE; + break; + + case USB_APPLICATION_SPECIFIC_INTERFACE: + AppendTextBuffer(" -> This is an Application Specific USB Device Interface Class\r\n"); + + switch(bInterfaceSubClass) + { + case 1: + AppendTextBuffer(" -> This is a Device Firmware Application Specific USB Device Interface Class\r\n"); + break; + case 2: + AppendTextBuffer(" -> This is an IrDA Bridge Application Specific USB Device Interface Class\r\n"); + break; + case 3: + AppendTextBuffer(" -> This is a Test & Measurement Class (USBTMC) Application Specific USB Device Interface Class\r\n"); + break; + default: + //@@TestCase A2.9 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@A possibly invalid interface class has been defined + AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + displayUnknown = TRUE; + break; + + default: + if (bInterfaceClass == USB_DEVICE_CLASS_VENDOR_SPECIFIC) + { + AppendTextBuffer(" -> This is a Vendor Specific USB Device Interface Class\r\n"); + } + else + { + //@@TestCase A2.10 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@An unknown interface class has been defined + AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + displayUnknown = TRUE; + break; + } + break; + } + + if (displayUnknown) + { + DisplayUnknownDescriptor(commonDesc); + } + } while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)ConfigDesc, + ConfigDesc->wTotalLength, + commonDesc, + -1)) != NULL); + +#ifdef H264_SUPPORT + DoAdditionalErrorChecks(); +#endif +} + + +/***************************************************************************** + +DisplayDeviceQualifierDescriptor() + +*****************************************************************************/ + +VOID +DisplayDeviceQualifierDescriptor ( + PUSB_DEVICE_QUALIFIER_DESCRIPTOR DevQualDesc + ) +{ + //@@DisplayDeviceQualifierDescriptor - Device Qualifier Descriptor + + AppendTextBuffer("\r\n ===>Device Qualifier Descriptor<===\r\n"); + + //length checked in DisplayConfigDesc() + + AppendTextBuffer("bLength: 0x%02X\r\n", + DevQualDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + DevQualDesc->bDescriptorType); + + AppendTextBuffer("bcdUSB: 0x%04X\r\n", + DevQualDesc->bcdUSB); + + AppendTextBuffer("bDeviceClass: 0x%02X", + DevQualDesc->bDeviceClass); + + switch (DevQualDesc->bDeviceClass) + { + case USB_INTERFACE_CLASS_DEVICE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> This is an Interface Class Defined Device\r\n"); + } + break; + + case USB_COMMUNICATION_DEVICE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> This is a Communication Device\r\n"); + } + break; + + case USB_HUB_DEVICE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> This is a HUB Device\r\n"); + } + break; + + case USB_DIAGNOSTIC_DEVICE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> This is a Diagnostic Device\r\n"); + } + break; + + case USB_WIRELESS_CONTROLLER_DEVICE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> This is a Wireless Controller(Bluetooth) Device\r\n"); + } + break; + + case USB_VENDOR_SPECIFIC_DEVICE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> This is a Vendor Specific Device\r\n"); + } + break; + case USB_DEVICE_CLASS_BILLBOARD: + if (gDoAnnotation) + { + AppendTextBuffer(" -> This is a billboard class device\r\n"); + } + break; + default: + //@@TestCase A3.1 + //@@ERROR + //@@Descriptor Field - bDeviceClass + //@@An unknown device class has been defined + AppendTextBuffer("*!*ERROR: bDeviceClass of %d is invalid\r\n", + DevQualDesc->bDeviceClass); + OOPS(); + break; + } + + AppendTextBuffer("bDeviceSubClass: 0x%02X\r\n", + DevQualDesc->bDeviceSubClass); + + if(DevQualDesc->bDeviceSubClass > 0x00 && DevQualDesc->bDeviceSubClass < 0xFF) + { + //@@TestCase A3.2 + //@@ERROR + //@@Descriptor Field - bDeviceSubClass + //@@An unknown device sub class has been defined + AppendTextBuffer("*!*ERROR: bDeviceSubClass of %d is invalid\r\n", + DevQualDesc->bDeviceSubClass); + OOPS(); + } + + AppendTextBuffer("bDeviceProtocol: 0x%02X\r\n", + DevQualDesc->bDeviceProtocol); + + if(DevQualDesc->bDeviceProtocol > 0x00 && DevQualDesc->bDeviceProtocol < 0xFF) + { + //@@TestCase A3.4 + //@@ERROR + //@@Descriptor Field - bDeviceProtocol + //@@An invalid device protocol has been defined + AppendTextBuffer("*!*ERROR: bDeviceProtocol of %d is invalid", + DevQualDesc->bDeviceProtocol); + OOPS(); + } + + //@@TestCase A3.5 + //@@Priority 1 + //@@Descriptor Field - bcdDevice + //@@We should test to verify a valid bMaxPacketSize0 based on speed + AppendTextBuffer("bMaxPacketSize0: 0x%02X", + DevQualDesc->bMaxPacketSize0); + + if(gDoAnnotation) + { + AppendTextBuffer(" = (%d) Bytes\r\n", + DevQualDesc->bMaxPacketSize0); + } + else {AppendTextBuffer("\r\n");} + + AppendTextBuffer("bNumConfigurations: 0x%02X\r\n", + DevQualDesc->bNumConfigurations); + + if(DevQualDesc->bNumConfigurations != 1) + { + //@@TestCase A3.6 + //@@CAUTION + //@@Descriptor Field - bNumConfigurations + //@@Most host controllers do not handle more than one configuration + AppendTextBuffer("*!*CAUTION: Most host controllers will only work with one configuration per speed\r\n"); + OOPS(); + } + + AppendTextBuffer("bReserved: 0x%02X\r\n", + DevQualDesc->bReserved); + + if(DevQualDesc->bReserved != 0) + { + AppendTextBuffer("*!*WARNING: bReserved needs to be set to 0 to be valid\r\n"); + OOPS(); + } + + +} + +VOID +DisplayUsb20ExtensionCapabilityDescriptor ( + PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR extCapDesc + ) +{ + AppendTextBuffer("\r\n ===>USB 2.0 Extension Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + extCapDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + extCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + extCapDesc->bDevCapabilityType); + AppendTextBuffer("bmAttributes: 0x%08X", + extCapDesc->bmAttributes); + if (extCapDesc->bmAttributes.AsUlong & USB_DEVICE_CAPABILITY_USB20_EXTENSION_BMATTRIBUTES_RESERVED_MASK) + { + if(gDoAnnotation) + { + AppendTextBuffer("\r\n*!*ERROR: bits 31..2 and bit 0 are reserved and must be 0\r\n"); + } + } + if (extCapDesc->bmAttributes.LPMCapable == 1) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Supports Link Power Management protocol\r\n"); + } + } + if (extCapDesc->bmAttributes.AsUlong == 0) + { + AppendTextBuffer("\r\n"); + } +} + +VOID +DisplaySuperSpeedCapabilityDescriptor ( + PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR ssCapDesc + ) +{ + AppendTextBuffer("\r\n ===>SuperSpeed USB Device Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + ssCapDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + ssCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + ssCapDesc->bDevCapabilityType); + AppendTextBuffer("bmAttributes: 0x%02X\r\n", + ssCapDesc->bmAttributes); + if (ssCapDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_RESERVED_MASK) + { + if(gDoAnnotation) + { + AppendTextBuffer("\r\n*!*ERROR: bits 7:2 and bit 0 are reserved\r\n"); + } + } + if (ssCapDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_LTM_CAPABLE) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> capable of generating Latency Tolerance Messages\r\n"); + } + } + AppendTextBuffer("wSpeedsSupported: 0x%02X\r\n", + ssCapDesc->wSpeedsSupported); + + if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_LOW) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Supports low-speed operation\r\n"); + } + } + if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_FULL) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Supports full-speed operation\r\n"); + } + } + if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_HIGH) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Supports high-speed operation\r\n"); + } + } + if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_SUPER) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Supports SuperSpeed operation\r\n"); + } + } + if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_RESERVED_MASK) + { + if(gDoAnnotation) + { + AppendTextBuffer("\r\n*!*ERROR: bits 15:4 are reserved\r\n"); + } + } + if (!gDoAnnotation) + { + AppendTextBuffer("\r\n"); + } + AppendTextBuffer("bFunctionalitySupport: 0x%02X", + ssCapDesc->bFunctionalitySupport); + if(gDoAnnotation) + { + switch (ssCapDesc->bFunctionalitySupport) + { + case UsbLowSpeed: + AppendTextBuffer(" -> lowest speed = low-speed\r\n"); + break; + case UsbFullSpeed: + AppendTextBuffer(" -> lowest speed = full-speed\r\n"); + break; + case UsbHighSpeed: + AppendTextBuffer(" -> lowest speed = high-speed\r\n"); + break; + case UsbSuperSpeed: + AppendTextBuffer(" -> lowest speed = SuperSpeed\r\n"); + break; + default: + AppendTextBuffer("\r\n*!*ERROR: Invalid value\r\n"); + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + + AppendTextBuffer("bU1DevExitLat: 0x%02X", + ssCapDesc->bU1DevExitLat); + if(gDoAnnotation) + { + if (ssCapDesc->bU1DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U1_DEVICE_EXIT_MAX_VALUE) + { + AppendTextBuffer(" -> less than %d micro-seconds\r\n", + ssCapDesc->bU1DevExitLat); + } + else + { + AppendTextBuffer("\r\n*!*ERROR: Invalid value\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + + AppendTextBuffer("wU2DevExitLat: 0x%04X", + ssCapDesc->wU2DevExitLat); + if(gDoAnnotation) + { + if (ssCapDesc->wU2DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U2_DEVICE_EXIT_MAX_VALUE) + { + AppendTextBuffer(" -> less than %d micro-seconds\r\n", + ssCapDesc->wU2DevExitLat); + } + else + { + AppendTextBuffer("\r\n*!*ERROR: Invalid value\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } +} + + +VOID +DisplaySuperSpeedPlusCapabilityDescriptor ( + PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_USB_DESCRIPTOR sspCapDesc + ) +{ + UCHAR i; + + AppendTextBuffer("\r\n ===>SuperSpeed USB Device Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + sspCapDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + sspCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + sspCapDesc->bDevCapabilityType); + AppendTextBuffer("bReserved: 0x%02X\r\n", + sspCapDesc->bReserved); + if (sspCapDesc->bReserved != 0) + { + if(gDoAnnotation) + { + AppendTextBuffer("*!*ERROR: field is reserved\r\n"); + } + } + + AppendTextBuffer("bmAttributes: 0x%08X\r\n", + sspCapDesc->bmAttributes.AsUlong); + AppendTextBuffer(" SublinkSpeedAttrCount: 0x%02X\r\n", + sspCapDesc->bmAttributes.SublinkSpeedAttrCount); + AppendTextBuffer(" SublinkSpeedIDCount: 0x%02X\r\n", + sspCapDesc->bmAttributes.SublinkSpeedIDCount); + + AppendTextBuffer("wFunctionalitySupport: 0x%04X\r\n", + sspCapDesc->wFunctionalitySupport.AsUshort); + AppendTextBuffer(" SublinkSpeedAttrID: 0x%02X\r\n", + sspCapDesc->wFunctionalitySupport.SublinkSpeedAttrID); + AppendTextBuffer(" Reserved: 0x%02X\r\n", + sspCapDesc->wFunctionalitySupport.Reserved); + if (sspCapDesc->wFunctionalitySupport.Reserved != 0) + { + if(gDoAnnotation) + { + AppendTextBuffer("*!*ERROR: field is reserved\r\n"); + } + } + AppendTextBuffer(" MinRxLaneCount: 0x%02X\r\n", + sspCapDesc->wFunctionalitySupport.MinRxLaneCount); + AppendTextBuffer(" MinTxLaneCount: 0x%02X\r\n", + sspCapDesc->wFunctionalitySupport.MinTxLaneCount); + + AppendTextBuffer("wReserved: 0x%04X\r\n", + sspCapDesc->wReserved); + if (sspCapDesc->wReserved != 0) + { + if(gDoAnnotation) + { + AppendTextBuffer("*!*ERROR: field is reserved\r\n"); + } + } + + // The array size = SublinkSpeedAttrCount + 1 + for (i = 0; i <= sspCapDesc->bmAttributes.SublinkSpeedAttrCount; i++) + { + PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED speed = &sspCapDesc->bmSublinkSpeedAttr[i]; + + AppendTextBuffer("bmSublinkSpeedAttr #: 0x%02X\r\n", + i); + AppendTextBuffer(" SublinkSpeedAttrID: 0x%02X\r\n", + speed->SublinkSpeedAttrID); + AppendTextBuffer(" LaneSpeedExponent: 0x%02X", + speed->LaneSpeedExponent); + if(gDoAnnotation) + { + switch (speed->LaneSpeedExponent) + { + case 0: + AppendTextBuffer(" -> Bits per second\r\n"); + break; + case 1: + AppendTextBuffer(" -> Kb/s\r\n"); + break; + case 2: + AppendTextBuffer(" -> Mb/s\r\n"); + break; + case 3: + AppendTextBuffer(" -> Gb/s\r\n"); + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + AppendTextBuffer(" SublinkTypeMode: 0x%02X", + speed->SublinkTypeMode); + if(gDoAnnotation) + { + switch (speed->SublinkTypeMode) + { + case 0: + AppendTextBuffer(" -> Symmetric\r\n"); + break; + case 1: + AppendTextBuffer(" -> Asymmetric\r\n"); + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + AppendTextBuffer(" SublinkTypeDir: 0x%02X", + speed->SublinkTypeDir); + if(gDoAnnotation) + { + switch (speed->SublinkTypeDir) + { + case 0: + AppendTextBuffer(" -> Receive mode\r\n"); + break; + case 1: + AppendTextBuffer(" -> Transmit mode\r\n"); + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + AppendTextBuffer(" Reserved: 0x%02X\r\n", + speed->Reserved); + AppendTextBuffer(" LinkProtocol: 0x%02X", + speed->LinkProtocol); + if(gDoAnnotation) + { + switch (speed->LinkProtocol) + { + case 0: + AppendTextBuffer(" -> SuperSpeed\r\n"); + break; + case 1: + AppendTextBuffer(" -> SuperSpeedPlus\r\n"); + break; + default: + AppendTextBuffer(" -> Reserved\r\n"); + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + AppendTextBuffer(" LaneSpeedMantissa: 0x%04X\r\n", + speed->LaneSpeedMantissa); + } +} + + +VOID +DisplayPlatformCapabilityDescriptor ( + PUSB_DEVICE_CAPABILITY_PLATFORM_DESCRIPTOR platformCapDesc + ) +{ + LPGUID pGuid; + + AppendTextBuffer("\r\n ===>Platform Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + platformCapDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + platformCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + platformCapDesc->bDevCapabilityType); + + AppendTextBuffer("bReserved: 0x%02X\r\n", + platformCapDesc->bReserved); + if (platformCapDesc->bReserved != 0) + { + if(gDoAnnotation) + { + AppendTextBuffer("*!*ERROR: field is reserved\r\n"); + } + } + + pGuid = (LPGUID)&platformCapDesc->PlatformCapabilityUuid; + AppendTextBuffer("Platform Capability UUID: "); + AppendTextBuffer("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\r\n", + pGuid->Data1, + pGuid->Data2, + pGuid->Data3, + pGuid->Data4[0], + pGuid->Data4[1], + pGuid->Data4[2], + pGuid->Data4[3], + pGuid->Data4[4], + pGuid->Data4[5], + pGuid->Data4[6], + pGuid->Data4[7]); + + DisplayRemainingUnknownDescriptor((PUCHAR)platformCapDesc, + (ULONG)offsetof(USB_DEVICE_CAPABILITY_PLATFORM_DESCRIPTOR, CapabililityData), + platformCapDesc->bLength); +} + + +VOID +DisplayContainerIdCapabilityDescriptor ( + PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR containerIdCapDesc + ) +{ + LPGUID pGuid; + + AppendTextBuffer("\r\n ===>Container ID Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + containerIdCapDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + containerIdCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + containerIdCapDesc->bDevCapabilityType); + AppendTextBuffer("bReserved: 0x%02X\r\n", + containerIdCapDesc->bReserved); + if (containerIdCapDesc->bReserved != 0) + { + if(gDoAnnotation) + { + AppendTextBuffer("*!*ERROR: field is reserved\r\n"); + } + } + + pGuid = (LPGUID)containerIdCapDesc->ContainerID; + AppendTextBuffer("Container ID: "); + AppendTextBuffer("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\r\n", + pGuid->Data1, + pGuid->Data2, + pGuid->Data3, + pGuid->Data4[0], + pGuid->Data4[1], + pGuid->Data4[2], + pGuid->Data4[3], + pGuid->Data4[4], + pGuid->Data4[5], + pGuid->Data4[6], + pGuid->Data4[7]); +} + +VOID +DisplayBillboardCapabilityDescriptor ( + PUSBDEVICEINFO info, + PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR billboardCapDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ) +{ + UCHAR i = 0; + UCHAR bNumAlternateModes = 0; + UCHAR alternateModeConfiguration = 0; + UCHAR adjustedBLength = 0; + + AppendTextBuffer("\r\n ===>Billboard Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X", + billboardCapDesc->bLength); + + adjustedBLength = sizeof(USB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) + + sizeof(billboardCapDesc->AlternateMode[0]) * (billboardCapDesc->bNumberOfAlternateModes - 1); + AppendTextBuffer(" -> Actual Length: 0x%02X\r\n", adjustedBLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + billboardCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X -> Billboard capability\r\n", + billboardCapDesc->bDevCapabilityType); + AppendTextBuffer("iAdditionalInfoURL: 0x%02X ->", + billboardCapDesc->iAddtionalInfoURL); + if (billboardCapDesc->iAddtionalInfoURL && gDoAnnotation) { + DisplayStringDescriptor(billboardCapDesc->iAddtionalInfoURL, + StringDescs, + info->DeviceInfoNode != NULL ? info->DeviceInfoNode->LatestDevicePowerState : PowerDeviceUnspecified); + } + AppendTextBuffer("bNumberOfAlternateModes: 0x%02X\r\n", + billboardCapDesc->bNumberOfAlternateModes); + + if (billboardCapDesc->bNumberOfAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) + { + AppendTextBuffer("*!*ERROR: Invalid bNumberofAlternateModes\r\n"); + } + AppendTextBuffer("bPreferredAlternateMode: 0x%02X\r\n", + billboardCapDesc->bPreferredAlternateMode); + + AppendTextBuffer("VCONN Power: 0x%04X", + billboardCapDesc->VconnPower); + + if (billboardCapDesc->VconnPower.NoVconnPowerRequired) + { + AppendTextBuffer(" -> The adapter does not require Vconn Power. Bits 2..0 ignored\r\n"); + } + else + { + switch (billboardCapDesc->VconnPower.VConnPowerNeededForFullFunctionality) + { + case 0: + AppendTextBuffer(" -> 1W needed by adapter for full functionality\r\n"); + break; + case 1: + AppendTextBuffer(" -> 1.5W needed by adapter for full functionality\r\n"); + break; + case 7: + AppendTextBuffer(" -> *!*ERROR: VConnPowerNeededForFullFunctionality - Reserved value being used\r\n"); + break; + default: + AppendTextBuffer(" -> %2XW needed by adapter for full functionality\r\n", billboardCapDesc->VconnPower.VConnPowerNeededForFullFunctionality); + } + } + + if (billboardCapDesc->VconnPower.Reserved) + { + AppendTextBuffer("*!*ERROR: Reserved bits in VCONN Power being used\r\n"); + } + if (billboardCapDesc->bReserved) + { + AppendTextBuffer("*!*ERROR: bReserved being used\r\n"); + } + + + bNumAlternateModes = billboardCapDesc->bNumberOfAlternateModes; + if (bNumAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) + { + bNumAlternateModes = BILLBOARD_MAX_NUM_ALT_MODE; + } + if (bNumAlternateModes > 0) + { + AppendTextBuffer("\r\nAlternate Modes Identified:\r\n"); + } + for (i = 0; i < bNumAlternateModes; i++) + { + alternateModeConfiguration = ((billboardCapDesc->bmConfigured[i / 4]) >> ((i % 4) * 2)) & 0x3; + AppendTextBuffer("wSVID - 0x%04X bAlternateMode - 0x%02X ->", + billboardCapDesc->AlternateMode[i].wSVID, + billboardCapDesc->AlternateMode[i].bAlternateMode, + billboardCapDesc->AlternateMode[i].iAlternateModeSetting); + + switch (alternateModeConfiguration) + { + case 0: + AppendTextBuffer("Unspecified Error\r\n"); + break; + case 1: + AppendTextBuffer("Alternate Mode configuration not attempted\r\n"); + break; + case 2: + AppendTextBuffer("Alternate Mode configuration attempted but unsuccessful\r\n"); + break; + case 3: + AppendTextBuffer("Alternate Mode configuration successful\r\n"); + break; + } + AppendTextBuffer("iAlternateModeString - 0x%02X ", billboardCapDesc->AlternateMode[i].iAlternateModeSetting); + if (billboardCapDesc->AlternateMode[i].iAlternateModeSetting && gDoAnnotation) + { + DisplayStringDescriptor(billboardCapDesc->AlternateMode[i].iAlternateModeSetting, + StringDescs, + info->DeviceInfoNode != NULL ? info->DeviceInfoNode->LatestDevicePowerState : PowerDeviceUnspecified); + } + else + { + AppendTextBuffer("\r\n"); + } + AppendTextBuffer("\r\n"); + } +} + + +#ifdef USB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY + +VOID +DisplayConfigurationSummaryCapabilityDescriptor ( + PUSB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY_DESCRIPTOR configSummaryCapDesc + ) +{ + UCHAR i; + AppendTextBuffer("\r\n ===>Configuration Summary Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + configSummaryCapDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + configSummaryCapDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + configSummaryCapDesc->bDevCapabilityType); + + AppendTextBuffer("bcdVersion: 0x%04X\r\n", + configSummaryCapDesc->bcdVersion); + AppendTextBuffer("bConfigurationValue: 0x%02X\r\n", + configSummaryCapDesc->bConfigurationValue); + AppendTextBuffer("bMaxPower: 0x%02X\r\n", + configSummaryCapDesc->bMaxPower); + AppendTextBuffer("bNumFunctions: 0x%02X\r\n", + configSummaryCapDesc->bNumFunctions); + + for (i = 0; i < configSummaryCapDesc->bNumFunctions; i++) + { + AppendTextBuffer("Function #: 0x%02X\r\n", + i); + AppendTextBuffer(" bClass: 0x%02X\r\n", + configSummaryCapDesc->Function[i].bClass); + AppendTextBuffer(" bSubClass: 0x%02X\r\n", + configSummaryCapDesc->Function[i].bSubClass); + AppendTextBuffer(" bProtocol: 0x%02X\r\n", + configSummaryCapDesc->Function[i].bProtocol); + } +} + +#endif + +/***************************************************************************** + +DisplayBosDescriptor() + +BosDesc - The Binary Object Store (BOS) Descriptor, and associated Descriptors + +*****************************************************************************/ + +VOID +DisplayBosDescriptor ( + PUSBDEVICEINFO info, + PUSB_BOS_DESCRIPTOR BosDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ) +{ + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + PUSB_DEVICE_CAPABILITY_DESCRIPTOR capDesc = NULL; + + AppendTextBuffer("\r\n ===>BOS Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + BosDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + BosDesc->bDescriptorType); + AppendTextBuffer("wTotalLength: 0x%04X\r\n", + BosDesc->wTotalLength); + AppendTextBuffer("bNumDeviceCaps: 0x%02X\r\n", + BosDesc->bNumDeviceCaps); + + commonDesc = (PUSB_COMMON_DESCRIPTOR)BosDesc; + + while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)BosDesc, + BosDesc->wTotalLength, + commonDesc, + -1)) != NULL) + { + switch (commonDesc->bDescriptorType) + { + case USB_DEVICE_CAPABILITY_DESCRIPTOR_TYPE: + + capDesc = (PUSB_DEVICE_CAPABILITY_DESCRIPTOR)commonDesc; + + switch (capDesc->bDevCapabilityType) + { + case USB_DEVICE_CAPABILITY_USB20_EXTENSION: + DisplayUsb20ExtensionCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR)capDesc); + break; + case USB_DEVICE_CAPABILITY_SUPERSPEED_USB: + DisplaySuperSpeedCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR)capDesc); + break; + case USB_DEVICE_CAPABILITY_CONTAINER_ID: + DisplayContainerIdCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR)capDesc); + break; + case USB_DEVICE_CAPABILITY_PLATFORM: + DisplayPlatformCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_PLATFORM_DESCRIPTOR)capDesc); + break; + case USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_USB: + DisplaySuperSpeedPlusCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_USB_DESCRIPTOR)capDesc); + break; + case USB_DEVICE_CAPABILITY_BILLBOARD: + DisplayBillboardCapabilityDescriptor((PUSBDEVICEINFO) info, (PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) capDesc, StringDescs); + break; +#ifdef USB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY + case USB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY: + DisplayConfigurationSummaryCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY_DESCRIPTOR)capDesc); + break; +#endif + default: + AppendTextBuffer("\r\n ===>Unknown Capability Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + capDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + capDesc->bDescriptorType); + AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", + capDesc->bDevCapabilityType); + + DisplayRemainingUnknownDescriptor((PUCHAR)commonDesc, + (ULONG)sizeof(USB_DEVICE_CAPABILITY_DESCRIPTOR), + commonDesc->bLength); + break; + } + break; + + default: + DisplayUnknownDescriptor(commonDesc); + break; + } + } +} + + +/***************************************************************************** + +DisplayConfigurationDescriptor() + +*****************************************************************************/ + +VOID +DisplayConfigurationDescriptor ( + PUSBDEVICEINFO info, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, + PSTRING_DESCRIPTOR_NODE StringDescs + ) +{ + UINT uCount = 0; + BOOL isSS; + + + isSS = info->ConnectionInfoV2 + && (info->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher || + info->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) + ? TRUE + : FALSE; + + AppendTextBuffer("\r\n ===>Configuration Descriptor<===\r\n"); + //@@DisplayConfigurationDescriptor - Configuration Descriptor + + //length checked in DisplayConfigDesc() + + AppendTextBuffer("bLength: 0x%02X\r\n", + ConfigDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + ConfigDesc->bDescriptorType); + + //@@TestCase A4.1 + //@@Priority 1 + //@@Descriptor Field - wTotalLength + //@@Verify Configuration length is valid + AppendTextBuffer("wTotalLength: 0x%04X", + ConfigDesc->wTotalLength); + uCount = GetConfigurationSize(info); + if (uCount != ConfigDesc->wTotalLength) { + AppendTextBuffer("\r\n*!*ERROR: Invalid total configuration size 0x%02X, should be 0x%02X\r\n", + ConfigDesc->wTotalLength, uCount); + } else { + AppendTextBuffer(" -> Validated\r\n"); + } + + //@@TestCase A4.2 + //@@Priority 1 + //@@Descriptor Field - bNumInterfaces + //@@Verify the number of interfaces is valid + AppendTextBuffer("bNumInterfaces: 0x%02X\r\n", + ConfigDesc->bNumInterfaces); + +/* Need to check spec vs composite devices + uCount = GetInterfaceCount(info); + if (uCount != ConfigDesc->bNumInterfaces) { + AppendTextBuffer("\r\n*!*ERROR: Invalid total Interfaces %d, should be %d\r\n", + ConfigDesc->bNumInterfaces, uCount); + } else { + AppendTextBuffer(" -> Validated\r\n"); + } +*/ + + AppendTextBuffer("bConfigurationValue: 0x%02X\r\n", + ConfigDesc->bConfigurationValue); + + if(ConfigDesc->bConfigurationValue != 1) + { + //@@TestCase A4.3 + //@@CAUTION + //@@Descriptor Field - bConfigurationValue + //@@Most host controllers do not handle more than one configuration + AppendTextBuffer("*!*CAUTION: Most host controllers will only work with one configuration per speed\r\n"); + OOPS(); + } + + AppendTextBuffer("iConfiguration: 0x%02X\r\n", + ConfigDesc->iConfiguration); + + if (ConfigDesc->iConfiguration && gDoAnnotation) + { + DisplayStringDescriptor(ConfigDesc->iConfiguration, + StringDescs, + info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); + } + + AppendTextBuffer("bmAttributes: 0x%02X", + ConfigDesc->bmAttributes); + + if (info->ConnectionInfo->DeviceDescriptor.bcdUSB == 0x0100) + { + if (ConfigDesc->bmAttributes & USB_CONFIG_SELF_POWERED) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Self Powered\r\n"); + } + } + if (ConfigDesc->bmAttributes & USB_CONFIG_BUS_POWERED) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Bus Powered\r\n"); + } + } + } + else + { + if (ConfigDesc->bmAttributes & USB_CONFIG_SELF_POWERED) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Self Powered\r\n"); + } + } + else + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Bus Powered\r\n"); + } + } + if ((ConfigDesc->bmAttributes & USB_CONFIG_BUS_POWERED) == 0) + { + AppendTextBuffer("\r\n*!*ERROR: Bit 7 is reserved and must be set\r\n"); + OOPS(); + } + } + + if (ConfigDesc->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Remote Wakeup\r\n"); + } + } + + if (ConfigDesc->bmAttributes & USB_CONFIG_RESERVED) + { + //@@TestCase A4.4 + //@@WARNING + //@@Descriptor Field - bmAttributes + //@@A bit has been set in reserved space + AppendTextBuffer("\r\n*!*ERROR: Bits 4...0 are reserved\r\n"); + OOPS(); + } + + AppendTextBuffer("MaxPower: 0x%02X", + ConfigDesc->MaxPower); + + if(gDoAnnotation) + { + AppendTextBuffer(" = %3d mA\r\n", + isSS ? ConfigDesc->MaxPower * 8 : ConfigDesc->MaxPower * 2); + } + else {AppendTextBuffer("\r\n");} + +} + +/***************************************************************************** + +DisplayInterfaceDescriptor() + +*****************************************************************************/ + +VOID +DisplayInterfaceDescriptor ( + PUSB_INTERFACE_DESCRIPTOR InterfaceDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayInterfaceDescriptor - Interface Descriptor + AppendTextBuffer("\r\n ===>Interface Descriptor<===\r\n"); + + //length checked in DisplayConfigDesc() + AppendTextBuffer("bLength: 0x%02X\r\n", + InterfaceDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + InterfaceDesc->bDescriptorType); + + //@@TestCase A5.1 + //@@Priority 1 + //@@Descriptor Field - bInterfaceNumber + //@@Question - Should we test to verify bInterfaceNumber is valid? + AppendTextBuffer("bInterfaceNumber: 0x%02X\r\n", + InterfaceDesc->bInterfaceNumber); + + //@@TestCase A5.2 + //@@Priority 1 + //@@Descriptor Field - bAlternateSetting + //@@Question - Should we test to verify bAlternateSetting is valid? + AppendTextBuffer("bAlternateSetting: 0x%02X\r\n", + InterfaceDesc->bAlternateSetting); + + //@@TestCase A5.3 + //@@Priority 1 + //@@Descriptor Field - bNumEndpoints + //@@Question - Should we test to verify bNumEndpoints is valid? + AppendTextBuffer("bNumEndpoints: 0x%02X\r\n", + InterfaceDesc->bNumEndpoints); + + AppendTextBuffer("bInterfaceClass: 0x%02X", + InterfaceDesc->bInterfaceClass); + + switch (InterfaceDesc->bInterfaceClass) + { + case USB_DEVICE_CLASS_AUDIO: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Audio Interface Class\r\n"); + } + + AppendTextBuffer("bInterfaceSubClass: 0x%02X", + InterfaceDesc->bInterfaceSubClass); + + if(gDoAnnotation) + { + switch (InterfaceDesc->bInterfaceSubClass) + { + case USB_AUDIO_SUBCLASS_AUDIOCONTROL: + AppendTextBuffer(" -> Audio Control Interface SubClass\r\n"); + break; + + case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: + AppendTextBuffer(" -> Audio Streaming Interface SubClass\r\n"); + break; + + case USB_AUDIO_SUBCLASS_MIDISTREAMING: + AppendTextBuffer(" -> MIDI Streaming Interface SubClass\r\n"); + break; + + default: + //@@TestCase A5.4 + //@@CAUTION + //@@Descriptor Field - bInterfaceSubClass + //@@Invalid bInterfaceSubClass + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bInterfaceSubClass\r\n"); + OOPS(); + break; + } + } + break; + + case USB_DEVICE_CLASS_VIDEO: + if(gDoAnnotation) + AppendTextBuffer(" -> Video Interface Class\r\n"); + + AppendTextBuffer("bInterfaceSubClass: 0x%02X", + InterfaceDesc->bInterfaceSubClass); + + switch(InterfaceDesc->bInterfaceSubClass) + { + case VIDEO_SUBCLASS_CONTROL: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Video Control Interface SubClass\r\n"); + } + break; + + case VIDEO_SUBCLASS_STREAMING: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Video Streaming Interface SubClass\r\n"); + } + break; + + default: + //@@TestCase A5.5 + //@@CAUTION + //@@Descriptor Field - bInterfaceSubClass + //@@Invalid bInterfaceSubClass + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bInterfaceSubClass\r\n"); + OOPS(); + break; + } + break; + + case USB_DEVICE_CLASS_HUMAN_INTERFACE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> HID Interface Class\r\n"); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_HUB: + if(gDoAnnotation) + { + AppendTextBuffer(" -> HUB Interface Class\r\n"); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_RESERVED: + //@@TestCase A5.6 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@A reserved USB Device Interface Class has been defined + AppendTextBuffer("\r\n*!*CAUTION: %d is a Reserved USB Device Interface Class\r\n", + USB_DEVICE_CLASS_RESERVED); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_COMMUNICATIONS: + AppendTextBuffer(" -> This is Communications (CDC Control) USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_MONITOR: + AppendTextBuffer(" -> This is a Monitor USB Device Interface Class*** (This may be obsolete)\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: + AppendTextBuffer(" -> This is a Physical Interface USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_POWER: + if(InterfaceDesc->bInterfaceSubClass == 1 && InterfaceDesc->bInterfaceProtocol == 1) + { + AppendTextBuffer(" -> This is an Image USB Device Interface Class\r\n"); + } + else + { + AppendTextBuffer(" -> This is a Power USB Device Interface Class (This may be obsolete)\r\n"); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_PRINTER: + AppendTextBuffer(" -> This is a Printer USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DEVICE_CLASS_STORAGE: + AppendTextBuffer(" -> This is a Mass Storage USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_CDC_DATA_INTERFACE: + AppendTextBuffer(" -> This is a CDC Data USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_CHIP_SMART_CARD_INTERFACE: + AppendTextBuffer(" -> This is a Chip/Smart Card USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_CONTENT_SECURITY_INTERFACE: + AppendTextBuffer(" -> This is a Content Security USB Device Interface Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_DIAGNOSTIC_DEVICE_INTERFACE: + if(InterfaceDesc->bInterfaceSubClass == 1 && InterfaceDesc->bInterfaceProtocol == 1) + { + AppendTextBuffer(" -> This is a Reprogrammable USB2 Compliance Diagnostic Device USB Device\r\n"); + } + else + { + //@@TestCase A5.7 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@Invalid Interface Class + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_WIRELESS_CONTROLLER_INTERFACE: + if(InterfaceDesc->bInterfaceSubClass == 1 && InterfaceDesc->bInterfaceProtocol == 1) + { + AppendTextBuffer(" -> This is a Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface\r\n"); + } + else + { + //@@TestCase A5.8 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@Invalid Interface Class + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + + case USB_APPLICATION_SPECIFIC_INTERFACE: + AppendTextBuffer(" -> This is an Application Specific USB Device Interface Class\r\n"); + + switch(InterfaceDesc->bInterfaceSubClass) + { + case 1: + AppendTextBuffer(" -> This is a Device Firmware Application Specific USB Device Interface Class\r\n"); + break; + case 2: + AppendTextBuffer(" -> This is an IrDA Bridge Application Specific USB Device Interface Class\r\n"); + break; + case 3: + AppendTextBuffer(" -> This is a Test & Measurement Class (USBTMC) Application Specific USB Device Interface Class\r\n"); + break; + default: + //@@TestCase A5.9 + //@@CAUTION + //@@Descriptor Field - bInterfaceClass + //@@Invalid Interface Class + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + case USB_DEVICE_CLASS_BILLBOARD: + AppendTextBuffer(" -> Billboard Class\r\n"); + AppendTextBuffer("bInterfaceSubClass: 0x%02X", InterfaceDesc->bInterfaceSubClass); + switch (InterfaceDesc->bInterfaceSubClass) + { + case 0: + AppendTextBuffer(" -> Billboard Subclass\r\n"); + break; + default: + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bInterfaceSubClass\r\n"); + break; + } + break; + + default: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Interface Class Unknown to USBView\r\n"); + } + AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", + InterfaceDesc->bInterfaceSubClass); + break; + } + + AppendTextBuffer("bInterfaceProtocol: 0x%02X\r\n", + InterfaceDesc->bInterfaceProtocol); + + //This is basically the check for PC_PROTOCOL_UNDEFINED + if ((InterfaceDesc->bInterfaceClass == USB_DEVICE_CLASS_VIDEO) || + (InterfaceDesc->bInterfaceClass == USB_DEVICE_CLASS_AUDIO)) + { + if(InterfaceDesc->bInterfaceProtocol != PC_PROTOCOL_UNDEFINED) + { + //@@TestCase A5.10 + //@@WARNING + //@@Descriptor Field - iInterface + //@@bInterfaceProtocol must be set to PC_PROTOCOL_UNDEFINED + AppendTextBuffer("*!*WARNING: must be set to PC_PROTOCOL_UNDEFINED %d for this class\r\n", + PC_PROTOCOL_UNDEFINED); + OOPS(); + } + } + + AppendTextBuffer("iInterface: 0x%02X\r\n", + InterfaceDesc->iInterface); + + if(gDoAnnotation) + { + if (InterfaceDesc->iInterface) + { + DisplayStringDescriptor(InterfaceDesc->iInterface, + StringDescs, + LatestDevicePowerState); + } + } + + if (InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR2)) + { + PUSB_INTERFACE_DESCRIPTOR2 interfaceDesc2; + + interfaceDesc2 = (PUSB_INTERFACE_DESCRIPTOR2)InterfaceDesc; + + AppendTextBuffer("wNumClasses: 0x%04X\r\n", + interfaceDesc2->wNumClasses); + } + +} + +/***************************************************************************** + +DisplayEndpointDescriptor() + +*****************************************************************************/ + +VOID +DisplayEndpointDescriptor ( + _In_ PUSB_ENDPOINT_DESCRIPTOR + EndpointDesc, + _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR + EpCompDesc, + _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR + SspIsochEpCompDesc, + _In_ UCHAR InterfaceClass, + _In_ BOOLEAN EpCompDescAvail + ) +{ + UCHAR epType = EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK; + PUSB_HIGH_SPEED_MAXPACKET hsMaxPacket; + + AppendTextBuffer("\r\n ===>Endpoint Descriptor<===\r\n"); + //@@DisplayEndpointDescriptor - Endpoint Descriptor + //length checked in DisplayConfigDesc() + + AppendTextBuffer("bLength: 0x%02X\r\n", + EndpointDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + EndpointDesc->bDescriptorType); + + AppendTextBuffer("bEndpointAddress: 0x%02X", + EndpointDesc->bEndpointAddress); + + if(gDoAnnotation) + { + if(USB_ENDPOINT_DIRECTION_OUT(EndpointDesc->bEndpointAddress)) + { + AppendTextBuffer(" -> Direction: OUT - EndpointID: %d\r\n", + (EndpointDesc->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)); + } + else if(USB_ENDPOINT_DIRECTION_IN(EndpointDesc->bEndpointAddress)) + { + AppendTextBuffer(" -> Direction: IN - EndpointID: %d\r\n", + (EndpointDesc->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)); + } + else + { + //@@TestCase A6.1 + //@@ERROR + //@@Descriptor Field - bEndpointAddress + //@@An invalid endpoint addressl has been defined + AppendTextBuffer("\r\n*!*ERROR: This appears to be an invalid bEndpointAddress\r\n"); + OOPS(); + } + } + else {AppendTextBuffer("\r\n");} + + AppendTextBuffer("bmAttributes: 0x%02X", + EndpointDesc->bmAttributes); + + if(gDoAnnotation) + { + AppendTextBuffer(" -> "); + + switch (epType) + { + case USB_ENDPOINT_TYPE_CONTROL: + AppendTextBuffer("Control Transfer Type\r\n"); + if (EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_CONTROL_RESERVED_MASK) + { + AppendTextBuffer("\r\n*!*ERROR: Bits 7..2 are reserved and must be set to 0\r\n"); + OOPS(); + } + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + AppendTextBuffer("Isochronous Transfer Type, Synchronization Type = "); + + switch (USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION(EndpointDesc->bmAttributes)) + { + case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_NO_SYNCHRONIZATION: + AppendTextBuffer("No Synchronization"); + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_ASYNCHRONOUS: + AppendTextBuffer("Asynchronous"); + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_ADAPTIVE: + AppendTextBuffer("Adaptive"); + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_SYNCHRONOUS: + AppendTextBuffer("Synchronous"); + break; + } + AppendTextBuffer(", Usage Type = "); + + switch (USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE(EndpointDesc->bmAttributes)) + { + case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_DATA_ENDOINT: + AppendTextBuffer("Data Endpoint\r\n"); + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_FEEDBACK_ENDPOINT: + AppendTextBuffer("Feedback Endpoint\r\n"); + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_IMPLICIT_FEEDBACK_DATA_ENDPOINT: + AppendTextBuffer("Implicit Feedback Data Endpoint\r\n"); + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_RESERVED: + //@@TestCase A6.2 + //@@ERROR + //@@Descriptor Field - bmAttributes + //@@A reserved bit has a value + AppendTextBuffer("\r\n*!*ERROR: This value is Reserved\r\n"); + OOPS(); + break; + } + if (EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_ISOCHRONOUS_RESERVED_MASK) + { + AppendTextBuffer("\r\n*!*ERROR: Bits 7..6 are reserved and must be set to 0\r\n"); + OOPS(); + } + break; + + case USB_ENDPOINT_TYPE_BULK: + AppendTextBuffer("Bulk Transfer Type\r\n"); + if (EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_BULK_RESERVED_MASK) + { + AppendTextBuffer("\r\n*!*ERROR: Bits 7..2 are reserved and must be set to 0\r\n"); + OOPS(); + } + break; + + case USB_ENDPOINT_TYPE_INTERRUPT: + + if (gDeviceSpeed != UsbSuperSpeed) + { + AppendTextBuffer("Interrupt Transfer Type\r\n"); + if (EndpointDesc->bmAttributes & USB_20_ENDPOINT_TYPE_INTERRUPT_RESERVED_MASK) + { + AppendTextBuffer("\r\n*!*ERROR: Bits 7..2 are reserved and must be set to 0\r\n"); + OOPS(); + } + } + else + { + AppendTextBuffer("Interrupt Transfer Type, Usage Type = "); + + switch (USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE(EndpointDesc->bmAttributes)) + { + case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_PERIODIC: + AppendTextBuffer("Periodic\r\n"); + break; + + case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_NOTIFICATION: + AppendTextBuffer("Notification\r\n"); + break; + + case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_RESERVED10: + case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_RESERVED11: + AppendTextBuffer("\r\n*!*ERROR: This value is Reserved\r\n"); + OOPS(); + break; + } + + if (EndpointDesc->bmAttributes & USB_30_ENDPOINT_TYPE_INTERRUPT_RESERVED_MASK) + { + AppendTextBuffer("\r\n*!*ERROR: Bits 7..6 and 3..2 are reserved and must be set to 0\r\n"); + OOPS(); + } + + if (EpCompDescAvail) + { + if (EpCompDesc == NULL) + { + AppendTextBuffer("\r\n*!*ERROR: Endpoint Companion Descriptor missing\r\n"); + OOPS(); + } + else if (EpCompDesc->bmAttributes.Isochronous.SspCompanion == 1 && + SspIsochEpCompDesc == NULL) + { + AppendTextBuffer("\r\n*!*ERROR: SuperSpeedPlus Isoch Endpoint Companion Descriptor missing\r\n"); + OOPS(); + } + } + } + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + + //@@TestCase A6.3 + //@@Priority 1 + //@@Descriptor Field - bInterfaceNumber + //@@Question - Should we test to verify bInterfaceNumber is valid? + AppendTextBuffer("wMaxPacketSize: 0x%04X", + EndpointDesc->wMaxPacketSize); + if(gDoAnnotation) + { + switch (gDeviceSpeed) + { + case UsbSuperSpeed: + switch (epType) + { + case USB_ENDPOINT_TYPE_BULK: + if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_BULK_MAX_PACKET_SIZE) + { + AppendTextBuffer("\r\n*!*ERROR: SuperSpeed Bulk endpoints must be %d bytes\r\n", + USB_ENDPOINT_SUPERSPEED_BULK_MAX_PACKET_SIZE); + } + else + { + AppendTextBuffer("\r\n"); + } + break; + + case USB_ENDPOINT_TYPE_CONTROL: + if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_CONTROL_MAX_PACKET_SIZE) + { + AppendTextBuffer("\r\n*!*ERROR: SuperSpeed Control endpoints must be %d bytes\r\n", + USB_ENDPOINT_SUPERSPEED_CONTROL_MAX_PACKET_SIZE); + } + else + { + AppendTextBuffer("\r\n"); + } + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + + if (EpCompDesc != NULL) + { + if (EpCompDesc->bMaxBurst > 0) + { + if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE) + { + AppendTextBuffer("\r\n*!*ERROR: SuperSpeed isochronous endpoints must have wMaxPacketSize value of %d bytes\r\n", + USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE); + AppendTextBuffer(" when the SuperSpeed endpoint companion descriptor bMaxBurst value is greater than 0\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + } + else if (EndpointDesc->wMaxPacketSize > USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE) + { + AppendTextBuffer("\r\n*!*ERROR: Invalid SuperSpeed isochronous maximum packet size\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + break; + + case USB_ENDPOINT_TYPE_INTERRUPT: + + if (EpCompDesc != NULL) + { + if (EpCompDesc->bMaxBurst > 0) + { + if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_INTERRUPT_MAX_PACKET_SIZE) + { + AppendTextBuffer("\r\n*!*ERROR: SuperSpeed interrupt endpoints must have wMaxPacketSize value of %d bytes\r\n", + USB_ENDPOINT_SUPERSPEED_INTERRUPT_MAX_PACKET_SIZE); + AppendTextBuffer(" when the SuperSpeed endpoint companion descriptor bMaxBurst value is greater than 0\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + } + else if (EndpointDesc->wMaxPacketSize > USB_ENDPOINT_SUPERSPEED_INTERRUPT_MAX_PACKET_SIZE) + { + AppendTextBuffer("\r\n*!*ERROR: Invalid SuperSpeed interrupt maximum packet size\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + } + else + { + AppendTextBuffer("\r\n"); + } + break; + } + break; + + case UsbHighSpeed: + hsMaxPacket = (PUSB_HIGH_SPEED_MAXPACKET)&EndpointDesc->wMaxPacketSize; + + switch (epType) + { + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + case USB_ENDPOINT_TYPE_INTERRUPT: + switch (hsMaxPacket->HSmux) { + case 0: + if ((hsMaxPacket->MaxPacket < 1) || (hsMaxPacket->MaxPacket >1024)) + { + AppendTextBuffer("*!*ERROR: Invalid maximum packet size, should be between 1 and 1024\r\n"); + } + break; + + case 1: + if ((hsMaxPacket->MaxPacket < 513) || (hsMaxPacket->MaxPacket >1024)) + { + AppendTextBuffer("*!*ERROR: Invalid maximum packet size, should be between 513 and 1024\r\n"); + } + break; + + case 2: + if ((hsMaxPacket->MaxPacket < 683) || (hsMaxPacket->MaxPacket >1024)) + { + AppendTextBuffer("*!*ERROR: Invalid maximum packet size, should be between 683 and 1024\r\n"); + } + break; + + case 3: + AppendTextBuffer("*!*ERROR: Bits 12-11 set to Reserved value in wMaxPacketSize\r\n"); + break; + } + + AppendTextBuffer(" = %d transactions per microframe, 0x%02X max bytes\r\n", hsMaxPacket->HSmux + 1, hsMaxPacket->MaxPacket); + break; + + case USB_ENDPOINT_TYPE_BULK: + case USB_ENDPOINT_TYPE_CONTROL: + AppendTextBuffer(" = 0x%02X max bytes\r\n", hsMaxPacket->MaxPacket); + break; + } + break; + + case UsbFullSpeed: + // full speed + AppendTextBuffer(" = 0x%02X bytes\r\n", + EndpointDesc->wMaxPacketSize & 0x7FF); + break; + default: + // low or invalid speed + if (InterfaceClass == USB_DEVICE_CLASS_VIDEO) + { + AppendTextBuffer(" = Invalid bus speed for USB Video Class\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + break; + } + } + else + { + AppendTextBuffer("\r\n"); + } + + if (EndpointDesc->wMaxPacketSize & 0xE000) + { + //@@TestCase A6.4 + //@@Priority 1 + //@@OTG Descriptor Field - wMaxPacketSize + //@@Attribute bits D7-2 reserved (reset to 0) + AppendTextBuffer("*!*ERROR: wMaxPacketSize bits 15-13 should be 0\r\n"); + } + + if (EndpointDesc->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) + { + //@@TestCase A6.5 + //@@Priority 1 + //@@Descriptor Field - bInterfaceNumber + //@@Question - Should we test to verify bInterfaceNumber is valid? + AppendTextBuffer("bInterval: 0x%02X\r\n", + EndpointDesc->bInterval); + } + else + { + PUSB_ENDPOINT_DESCRIPTOR2 endpointDesc2; + + endpointDesc2 = (PUSB_ENDPOINT_DESCRIPTOR2)EndpointDesc; + + AppendTextBuffer("wInterval: 0x%04X\r\n", + endpointDesc2->wInterval); + + AppendTextBuffer("bSyncAddress: 0x%02X\r\n", + endpointDesc2->bSyncAddress); + } + + if (EpCompDesc != NULL) + { + DisplayEndointCompanionDescriptor(EpCompDesc, SspIsochEpCompDesc, epType); + } + if (SspIsochEpCompDesc != NULL) + { + DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor(SspIsochEpCompDesc); + } + +} + +/***************************************************************************** + +DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor() + +*****************************************************************************/ +VOID +DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor( + _In_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR SspIsochEpCompDesc + ) + { + AppendTextBuffer("\r\n ===>SuperSpeedPlus Isochronous Endpoint Companion Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + SspIsochEpCompDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + SspIsochEpCompDesc->bDescriptorType); + + AppendTextBuffer("wReserved: 0x%02X\r\n", + SspIsochEpCompDesc->wReserved); + + if (gDoAnnotation) + { + if (SspIsochEpCompDesc->wReserved != 0) + { + AppendTextBuffer("*!*ERROR: field is reserved\r\n"); + } + } + + AppendTextBuffer("dwBytesPerInterval: 0x%04X\r\n", + SspIsochEpCompDesc->dwBytesPerInterval); +} + +/***************************************************************************** + +DisplayEndointCompanionDescriptor() + +*****************************************************************************/ +VOID +DisplayEndointCompanionDescriptor ( + _In_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR EpCompDesc, + _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR SspIsochEpCompDesc, + _In_ UCHAR DescType + ) +{ + AppendTextBuffer("\r\n ===>SuperSpeed Endpoint Companion Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + EpCompDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + EpCompDesc->bDescriptorType); + + AppendTextBuffer("bMaxBurst: 0x%02X\r\n", + EpCompDesc->bMaxBurst); + + AppendTextBuffer("bmAttributes: 0x%02X", + EpCompDesc->bmAttributes.AsUchar); + if(gDoAnnotation) + { + switch (DescType) + { + case USB_ENDPOINT_TYPE_CONTROL: + case USB_ENDPOINT_TYPE_INTERRUPT: + if (EpCompDesc->bmAttributes.AsUchar != 0) + { + AppendTextBuffer("*!*ERROR: Control/Interrupt SuperSpeed endpoints do not support streams\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + break; + case USB_ENDPOINT_TYPE_BULK: + if(EpCompDesc->bmAttributes.Bulk.MaxStreams == 0) + { + AppendTextBuffer("The bulk endpoint does not define streams (MaxStreams == 0)\r\n"); + } + else + { + AppendTextBuffer(" = %d streams supported\r\n", 1 << EpCompDesc->bmAttributes.Bulk.MaxStreams); + } + + if (EpCompDesc->bmAttributes.Bulk.Reserved1 != 0) + { + AppendTextBuffer("*!*ERROR: bmAttributes bits 7-5 should be 0\r\n"); + } + break; + + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + if (EpCompDesc->bmAttributes.Isochronous.SspCompanion == 0) + { + if (EpCompDesc->bMaxBurst == 0 && + EpCompDesc->bmAttributes.Isochronous.Mult != 0) + { + AppendTextBuffer("*!*ERROR: SuperSpeed isochronous endpoint multiplier value should be zero if bMaxBurst is zero\r\n"); + } + else + { + AppendTextBuffer(" = %d maximum number of packets within a service interval\r\n", + (EpCompDesc->bmAttributes.Isochronous.Mult + 1)*(EpCompDesc->bMaxBurst + 1)); + + if (EpCompDesc->bmAttributes.Isochronous.Mult > USB_SUPERSPEED_ISOCHRONOUS_MAX_MULTIPLIER) + { + AppendTextBuffer("*!*ERROR: Maximum SuperSpeed isochronous endpoint multiplier value exceeded\r\n"); + } + } + } + else + { + if (EpCompDesc->bMaxBurst != 0 && SspIsochEpCompDesc != NULL) + { + AppendTextBuffer(" = %d maximum number of packets within a service interval\r\n", + (SspIsochEpCompDesc->dwBytesPerInterval*USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE) / + EpCompDesc->bMaxBurst); + } + } + + if (EpCompDesc->bmAttributes.Isochronous.Reserved2 != 0) + { + AppendTextBuffer("*!*ERROR: bmAttributes bits 7-2 should be 0\r\n"); + } + else + { + AppendTextBuffer("\r\n"); + } + break; + } + } + AppendTextBuffer("wBytesPerInterval: 0x%04X\r\n", + EpCompDesc->wBytesPerInterval); + + if (EpCompDesc->bmAttributes.Isochronous.SspCompanion == 1 && + EpCompDesc->wBytesPerInterval != 0x1) + { + AppendTextBuffer("*!*ERROR: SuperSpeed endpoint wBytesPerInterval value should be 1 if \ + SuperSpeedPlus Isoch companion descriptor is present\r\n"); + } +} + + +/***************************************************************************** + +DisplayHidDescriptor() + +*****************************************************************************/ + +VOID +DisplayHidDescriptor ( + PUSB_HID_DESCRIPTOR HidDesc + ) +{ + UCHAR i = 0; + + AppendTextBuffer("\r\n ===>HID Descriptor<===\r\n"); + + //length checked in DisplayConfigDesc() + + AppendTextBuffer("bLength: 0x%02X\r\n", + HidDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + HidDesc->bDescriptorType); + AppendTextBuffer("bcdHID: 0x%04X\r\n", + HidDesc->bcdHID); + AppendTextBuffer("bCountryCode: 0x%02X\r\n", + HidDesc->bCountryCode); + AppendTextBuffer("bNumDescriptors: 0x%02X\r\n", + HidDesc->bNumDescriptors); + + for (i=0; ibNumDescriptors; i++) + { + if (HidDesc->OptionalDescriptors[i].bDescriptorType == 0x22) { + AppendTextBuffer("bDescriptorType: 0x%02X (Report Descriptor)\r\n", + HidDesc->OptionalDescriptors[i].bDescriptorType); + } + else { + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + HidDesc->OptionalDescriptors[i].bDescriptorType); + } + + AppendTextBuffer("wDescriptorLength: 0x%04X\r\n", + HidDesc->OptionalDescriptors[i].wDescriptorLength); + } +} + +/***************************************************************************** + +DisplayOTGDescriptor() + +*****************************************************************************/ + +VOID +DisplayOTGDescriptor ( + PUSB_OTG_DESCRIPTOR OTGDesc + ) +{ + AppendTextBuffer("\r\n ===>OTG Descriptor<===\r\n"); + + //length checked in DisplayConfigDesc() + + AppendTextBuffer("bLength: 0x%02X\r\n", + OTGDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + OTGDesc->bDescriptorType); + AppendTextBuffer("bmAttributes: 0x%02X", + OTGDesc->bmAttributes); + + switch (OTGDesc->bmAttributes) + { + case 0: + break; + case 1: + if(gDoAnnotation) + { + AppendTextBuffer(" -> SRP support\r\n"); + } + break; + case 2: + if(gDoAnnotation) + { + AppendTextBuffer(" -> HNP support\r\n"); + } + break; + case 3: + if(gDoAnnotation) + { + AppendTextBuffer(" -> SRP and HNP support\r\n"); + } + break; + default: + //@@TestCase A6.5 + //@@Priority 1 + //@@OTG Descriptor Field - bmAttributes + //@@Attribute bits D7-2 reserved (reset to 0) + AppendTextBuffer("*!*ERROR: bmAttributes bits 2-7 are reserved "\ + "(should be 0)\r\n"); + OOPS(); + break; + } +} + +/***************************************************************************** + +InitializeGlobalFlags () + +Initialize the global device flags in UVCView.h + +*****************************************************************************/ + +void +InitializePerDeviceSettings ( + PUSBDEVICEINFO info + ) +{ + // Save base address for this current device's info (including Configuration descriptor) + CurrentUSBDeviceInfo = info; + + // Initialize Configuration descriptor length + dwConfigLength = 0; + + // Save # of bytes from start of Configuration descriptor + // (Update this in the descriptor parsing routines) + dwConfigIndex = 0; + + // Flags used in dispvid.c to display default Frame descriptor for MJPEG, + // Uncompressed, Vendor and FrameBased Formats + g_chMJPEGFrameDefault = 0; + g_chUNCFrameDefault = 0; + g_chVendorFrameDefault = 0; + g_chFrameBasedFrameDefault = 0; + + // Spec version of UVC device + g_chUVCversion = 0; + + // Start and end address of the configuration descriptor and start of the string descriptors + g_pConfigDesc = NULL; + g_pStringDescs = NULL; + g_descEnd = NULL; + + // + // The GetConfigDescriptor() function in enum.c does not always work + // If that fails, the Configuration descriptor will be NULL + // and we can only display the device descriptor + // + CurrentConfigDesc = NULL; + if (NULL != info) + { + if (NULL != info->ConfigDesc) + { + CurrentConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); + + // Save the LENGTH of the Config descriptor + // Note that IsIADDevice() saves the ADDRESS of the END of the Config desc + // Be aware of the difference + dwConfigLength = CurrentConfigDesc->wTotalLength; + } + } + + return; +} + +/***************************************************************************** + +IsUVCDevice() + +Return Spec version of UVC device + 0x0 = Not a UVC device + 0x10 = UVC 1.0 + 0x11 = UVC 1.1 + + *****************************************************************************/ + +UINT +IsUVCDevice ( + PUSBDEVICEINFO info + ) +{ + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc = NULL; + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + PUCHAR descEnd = NULL; + UINT uUVCversion = 0; + + // + // The GetConfigDescriptor() function in enum.c does not always work + // If that fails, the Configuration descriptor will be NULL + // and we can only display the device descriptor + // + if (NULL == info) + { + return 0; + } + if (NULL == info->ConfigDesc) + { + return 0; + } + ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); + if (NULL == ConfigDesc) + { + return 0; + } + + // We've got a good Configuration Descriptor + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + + // walk through all the descriptors looking for the VIDEO_CONTROL_HEADER_UNIT + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + if ((commonDesc->bDescriptorType == CS_INTERFACE) && + (commonDesc->bLength > sizeof(VIDEO_CONTROL_HEADER_UNIT))) + { + // Right type, size. Now check subtype + PVIDEO_CONTROL_HEADER_UNIT pCSVC = NULL; + pCSVC = (PVIDEO_CONTROL_HEADER_UNIT) commonDesc; + if (VC_HEADER == pCSVC->bDescriptorSubtype) + { + // found the Class-specific VC Interface Header descriptor + uUVCversion = pCSVC->bcdVideoSpec; + // Save the version to global + g_chUVCversion = uUVCversion; + // We're done + break; + } + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + return (uUVCversion); +} + +/***************************************************************************** + +IsIADDevice() + +*****************************************************************************/ + +UINT +IsIADDevice ( + PUSBDEVICEINFO info + ) +{ + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc = NULL; + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + PUCHAR descEnd = NULL; + UINT uIADcount = 0; + + // + // The GetConfigDescriptor() function in enum.c does not always work + // If that fails, the Configuration descriptor will be NULL + // and we can only display the device descriptor + // + if (NULL == info) + { + return 0; + } + if (NULL == info->ConfigDesc) + { + return 0; + } + + ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); + if (NULL != ConfigDesc) + { + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + } + + // return total number of IAD descriptors in this device configuration + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + if (commonDesc->bDescriptorType == USB_IAD_DESCRIPTOR_TYPE) + { + uIADcount++; + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + return (uIADcount); +} + +/***************************************************************************** + +DisplayIADDescriptor() + +*****************************************************************************/ + +VOID +DisplayIADDescriptor ( + PUSB_IAD_DESCRIPTOR IADDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + int nInterfaces, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + AppendTextBuffer("\r\n ===>IAD Descriptor<===\r\n"); + + //length checked in DisplayConfigDesc() + + AppendTextBuffer("bLength: 0x%02X\r\n", + IADDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + IADDesc->bDescriptorType); + AppendTextBuffer("bFirstInterface: 0x%02X\r\n", + IADDesc->bFirstInterface); + AppendTextBuffer("bInterfaceCount: 0x%02X\r\n", + IADDesc->bInterfaceCount); + if (IADDesc->bInterfaceCount == 1) + { + //@@TestCase A7.1 + //@@Priority 1 + //@@Standard IAD Descriptor Field - bInterfaceCount + //@@The number of interfaces must be greater than 1 + AppendTextBuffer("*!*ERROR: bInterfaceCount must be greater than 1 \r\n"); + OOPS(); + } + if (nInterfaces < IADDesc->bFirstInterface + IADDesc->bInterfaceCount) + { + //@@TestCase A7.2 + //@@Priority 1 + //@@Standard IAD Descriptor Field - bInterfaceCount + //@@The total number of interfaces must be greater than or equal to + //@@ the highest linked interface number (base interface number plus count) + AppendTextBuffer("*!*ERROR: The total number of interfaces (%d) must be greater "\ + "than or equal to\r\n", + nInterfaces); + AppendTextBuffer(" the highest linked interface number (base %d + "\ + "count %d = %d)\r\n", + IADDesc->bFirstInterface, IADDesc->bInterfaceCount, + (IADDesc->bFirstInterface + IADDesc->bInterfaceCount)); + OOPS(); + } + AppendTextBuffer("bFunctionClass: 0x%02X", + IADDesc->bFunctionClass); + if (IADDesc->bFunctionClass == 0) + { + //@@TestCase A7.3 + //@@Priority 1 + //@@Standard IAD Descriptor Field - bFunctionClass + //@@"A value of zero is not allowed in this descriptor" + AppendTextBuffer("\r\n*!*ERROR: bFunctionClass contains an illegal value 0 \r\n"); + OOPS(); + } + + switch (IADDesc->bFunctionClass) + { + case USB_DEVICE_CLASS_AUDIO: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Audio Interface Class\r\n"); + } + + AppendTextBuffer("bFunctionSubClass: 0x%02X", + IADDesc->bFunctionSubClass); + + if(gDoAnnotation) + { + switch (IADDesc->bFunctionSubClass) + { + case USB_AUDIO_SUBCLASS_AUDIOCONTROL: + AppendTextBuffer(" -> Audio Control Interface SubClass\r\n"); + break; + + case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: + AppendTextBuffer(" -> Audio Streaming Interface SubClass\r\n"); + break; + + case USB_AUDIO_SUBCLASS_MIDISTREAMING: + AppendTextBuffer(" -> MIDI Streaming Interface SubClass\r\n"); + break; + + default: + //@@TestCase A7.4 + //@@CAUTION + //@@Descriptor Field - bFunctionSubClass + //@@Invalid bFunctionSubClass + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bFunctionSubClass\r\n"); + OOPS(); + break; + } + } + break; + + case USB_DEVICE_CLASS_VIDEO: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Video Interface Class\r\n"); + } + + AppendTextBuffer("bFunctionSubClass: 0x%02X", + IADDesc->bFunctionSubClass); + + switch(IADDesc->bFunctionSubClass) + { + case SC_VIDEO_INTERFACE_COLLECTION: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Video Interface Collection\r\n"); + } + break; + + default: + //@@TestCase A7.5 + //@@CAUTION + //@@Descriptor Field - bFunctionSubClass + //@@Invalid bFunctionSubClass + AppendTextBuffer("\r\n*!*ERROR: This should be USB_VIDEO_SC_VIDEO_INTERFACE_COLLECTION %d\r\n", + SC_VIDEO_INTERFACE_COLLECTION); + OOPS(); + break; + } + break; + + case USB_DEVICE_CLASS_HUMAN_INTERFACE: + if(gDoAnnotation) + { + AppendTextBuffer(" -> HID Interface Class\r\n"); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_HUB: + if(gDoAnnotation) + { + AppendTextBuffer(" -> HUB Interface Class\r\n"); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_RESERVED: + //@@TestCase A7.6 + //@@CAUTION + //@@Descriptor Field - bFunctionClass + //@@A reserved USB Device Interface Class has been defined + AppendTextBuffer("\r\n*!*CAUTION: %d is a Reserved USB Device Interface Class\r\n", + USB_DEVICE_CLASS_RESERVED); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_COMMUNICATIONS: + AppendTextBuffer(" -> This is Communications (CDC Control) USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_MONITOR: + AppendTextBuffer(" -> This is a Monitor USB Device Interface Class*** (This may be obsolete)\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: + AppendTextBuffer(" -> This is a Physical Interface USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_POWER: + if(IADDesc->bFunctionSubClass == 1 && IADDesc->bFunctionProtocol == 1) + { + AppendTextBuffer(" -> This is an Image USB Device Interface Class\r\n"); + } + else + { + AppendTextBuffer(" -> This is a Power USB Device Interface Class (This may be obsolete)\r\n"); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_PRINTER: + AppendTextBuffer(" -> This is a Printer USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DEVICE_CLASS_STORAGE: + AppendTextBuffer(" -> This is a Mass Storage USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_CDC_DATA_INTERFACE: + AppendTextBuffer(" -> This is a CDC Data USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_CHIP_SMART_CARD_INTERFACE: + AppendTextBuffer(" -> This is a Chip/Smart Card USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_CONTENT_SECURITY_INTERFACE: + AppendTextBuffer(" -> This is a Content Security USB Device Interface Class\r\n"); + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_DIAGNOSTIC_DEVICE_INTERFACE: + if(IADDesc->bFunctionSubClass == 1 && IADDesc->bFunctionProtocol == 1) + { + AppendTextBuffer(" -> This is a Reprogrammable USB2 Compliance Diagnostic Device USB Device\r\n"); + } + else + { + //@@TestCase A7.7 + //@@CAUTION + //@@Descriptor Field - bFunctionClass + //@@Invalid Interface Class + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_WIRELESS_CONTROLLER_INTERFACE: + if(IADDesc->bFunctionSubClass == 1 && IADDesc->bFunctionProtocol == 1) + { + AppendTextBuffer(" -> This is a Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface\r\n"); + } + else + { + //@@TestCase A7.8 + //@@CAUTION + //@@Descriptor Field - bFunctionClass + //@@Invalid Interface Class + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + case USB_APPLICATION_SPECIFIC_INTERFACE: + AppendTextBuffer(" -> This is an Application Specific USB Device Interface Class\r\n"); + + switch(IADDesc->bFunctionSubClass) + { + case 1: + AppendTextBuffer(" -> This is a Device Firmware Application Specific USB Device Interface Class\r\n"); + break; + case 2: + AppendTextBuffer(" -> This is an IrDA Bridge Application Specific USB Device Interface Class\r\n"); + break; + case 3: + AppendTextBuffer(" -> This is a Test & Measurement Class (USBTMC) Application Specific USB Device Interface Class\r\n"); + break; + default: + //@@TestCase A7.9 + //@@CAUTION + //@@Descriptor Field - bFunctionClass + //@@Invalid Interface Class + AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); + OOPS(); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + + default: + if(gDoAnnotation) + { + AppendTextBuffer(" -> Interface Class Unknown to USBView\r\n"); + } + AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", + IADDesc->bFunctionSubClass); + break; + } + + AppendTextBuffer("bFunctionProtocol: 0x%02X", + IADDesc->bFunctionProtocol); + + // check protocol for our class + if ((IADDesc->bFunctionClass == USB_DEVICE_CLASS_VIDEO)) + { + // USB Video Class + if(IADDesc->bFunctionProtocol == PC_PROTOCOL_UNDEFINED) + { + // correct protocol for UVC + if(gDoAnnotation) + { + AppendTextBuffer(" -> PC_PROTOCOL_UNDEFINED protocol\r\n"); + } else { + AppendTextBuffer("\r\n"); + } + } else { + // incorrect protocol for UVC + //@@TestCase A7.10 + //@@WARNING + //@@Descriptor Field - iInterface + //@@bFunctionProtocol must be set to PC_PROTOCOL_UNDEFINED + AppendTextBuffer("*!*WARNING: must be set to PC_PROTOCOL_UNDEFINED %d for this class\r\n", + PC_PROTOCOL_UNDEFINED); + OOPS(); + } + } else { + AppendTextBuffer("\r\n"); + } + + AppendTextBuffer("iFunction: 0x%02X\r\n", + IADDesc->iFunction); + + if(gDoAnnotation) + { + if (IADDesc->iFunction) + { + DisplayStringDescriptor(IADDesc->iFunction, + StringDescs, + LatestDevicePowerState); + } + } +} + +/***************************************************************************** + +GetConfigurationSize() + +*****************************************************************************/ + +UINT +GetConfigurationSize ( + PUSBDEVICEINFO info + ) +{ + PUSB_CONFIGURATION_DESCRIPTOR + ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); + PUSB_COMMON_DESCRIPTOR + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + PUCHAR + descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + UINT uCount = 0; + + // return this device configuration's total sum of descriptor lengths + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + uCount += commonDesc->bLength; + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + return (uCount); +} + +/***************************************************************************** + +GetInterfaceCount() + +*****************************************************************************/ + +UINT +GetInterfaceCount ( + PUSBDEVICEINFO info + ) +{ + // how do we handle composite devices? + PUSB_CONFIGURATION_DESCRIPTOR + ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); + PUSB_COMMON_DESCRIPTOR + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + PUCHAR + descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + UINT uCount = 0; + + // return this device configuration's total number of interface descriptors + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + if (commonDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) + { + uCount++; + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + return (uCount); +} + + +/***************************************************************************** + +DisplayUSEnglishStringDescriptor() + +*****************************************************************************/ + +VOID +DisplayUSEnglishStringDescriptor ( + UCHAR Index, + PSTRING_DESCRIPTOR_NODE USStringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + ULONG nBytes = 0; + BOOLEAN FoundMatchingString = FALSE; + CHAR pString[512]; + + //@@DisplayUSEnglishStringDescriptor - String Descriptor + for (; USStringDescs; USStringDescs = USStringDescs->Next) + { + if (USStringDescs->DescriptorIndex == Index && USStringDescs->LanguageID == 0x0409) + { + FoundMatchingString = TRUE; + + AppendTextBuffer("English product name: \""); + memset(pString, 0, 512); + nBytes = WideCharToMultiByte( + CP_ACP, // CodePage + WC_NO_BEST_FIT_CHARS, + USStringDescs->StringDescriptor->bString, + (USStringDescs->StringDescriptor->bLength - 2) / 2, + pString, + 512, + NULL, // lpDefaultChar + NULL); // pUsedDefaultChar + if (nBytes) + AppendTextBuffer("%s\"\r\n", pString); + else + AppendTextBuffer("\"\r\n", pString); + return; + } + } + + //@@TestCase A8.1 + //@@WARNING + //@@Descriptor Field - string index + //@@No support for english + if (!FoundMatchingString) + { + if (LatestDevicePowerState == PowerDeviceD0) + { + AppendTextBuffer("*!*ERROR: No String Descriptor for index %d!\r\n", Index); + OOPS(); + } + else + { + AppendTextBuffer("String Descriptor for index %d not available while device is in low power state.\r\n", Index); + } + } + else + { + AppendTextBuffer("*!*ERROR: The index selected does not support English(US)\r\n"); + OOPS(); + } + return; + +} + + +/***************************************************************************** + +DisplayStringDescriptor() + +*****************************************************************************/ +VOID +DisplayStringDescriptor ( + UCHAR Index, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + ULONG nBytes = 0; + BOOLEAN FoundMatchingString = FALSE; + PCHAR pStr = NULL; + CHAR pString[512]; + + //@@DisplayStringDescriptor - String Descriptor + + while (StringDescs) + { + if (StringDescs->DescriptorIndex == Index) + { + FoundMatchingString = TRUE; + if(gDoAnnotation) + { + pStr= GetLangIDString(StringDescs->LanguageID); + if(pStr) + { + AppendTextBuffer(" %s \"", + pStr); + } + else + { + //@@TestCase A9.1 + //@@WARNING + //@@Descriptor Field - string index + //@@The Language ID does not match any known languages supported by USB ORG + AppendTextBuffer("*!*WARNING: %d is an invalid Language ID\r\n", + Index); + OOPS(); + } + } + else + { + AppendTextBuffer(" 0x%04X: \"", StringDescs->LanguageID); + } + memset(pString, 0, 512); + + if (StringDescs->StringDescriptor->bLength > sizeof(USHORT)) + { + nBytes = WideCharToMultiByte( + CP_ACP, // CodePage + WC_NO_BEST_FIT_CHARS, + StringDescs->StringDescriptor->bString, + (StringDescs->StringDescriptor->bLength - 2) / 2, + pString, + 512, + NULL, // lpDefaultChar + NULL); // pUsedDefaultChar + if (nBytes) + { + AppendTextBuffer("%s\"\r\n", pString); + } + else + { + AppendTextBuffer("\"\r\n"); + } + } + else + { + // + // This is NULL string which is invalid + // + AppendTextBuffer("\"\r\n"); + } + } + StringDescs = StringDescs->Next; + } + + if (!FoundMatchingString) + { + if (LatestDevicePowerState == PowerDeviceD0) + { + AppendTextBuffer("*!*ERROR: No String Descriptor for index %d!\r\n", Index); + OOPS(); + } + else + { + AppendTextBuffer("String Descriptor for index %d not available while device is in low power state.\r\n", Index); + } + } +} + +/***************************************************************************** + +DisplayUnknownDescriptor() + +*****************************************************************************/ +VOID +DisplayUnknownDescriptor ( + PUSB_COMMON_DESCRIPTOR CommonDesc + ) +{ + AppendTextBuffer("\r\n ===>Descriptor Hex Dump<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", + CommonDesc->bLength); + + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", + CommonDesc->bDescriptorType); + + DisplayRemainingUnknownDescriptor((PUCHAR)CommonDesc, 0, CommonDesc->bLength); +} + +VOID +DisplayRemainingUnknownDescriptor( + PUCHAR DescriptorData, + ULONG Start, + ULONG Stop + ) +{ + ULONG i; + + for (i = Start; i < Stop; i++) + { + AppendTextBuffer("%02X ", + DescriptorData[i]); + + if (i % 16 == 15) + { + AppendTextBuffer("\r\n"); + } + } + + if (i % 16 != 0) + { + AppendTextBuffer("\r\n"); + } +} + + + +/***************************************************************************** + +GetVendorString() + +idVendor - USB Vendor ID + +Return Value - Vendor name string associated with idVendor, or NULL if +no vendor name string is found which is associated with idVendor. + +*****************************************************************************/ + +PCHAR +GetVendorString ( + USHORT idVendor + ) +{ + PVENDOR_ID vendorID = NULL; + + if (idVendor == 0x0000) + { + return NULL; + } + + vendorID = USBVendorIDs; + + while (vendorID->usVendorID != 0x0000) + { + if (vendorID->usVendorID == idVendor) + { + break; + } + vendorID++; + } + + return (vendorID->szVendor); +} + +/***************************************************************************** + +GetLangIDString() + +idVendor - USB Vendor ID + +Return Value - Vendor name string associated with idVendor, or NULL if +no vendor name string is found which is associated with idVendor. + +*****************************************************************************/ + +PCHAR +GetLangIDString ( + USHORT idLang + ) +{ + PUSBLANGID langID = NULL; + + if (idLang != 0x0000) + { + langID = USBLangIDs; + + while (langID->usLangID != 0x0000) + { + if (langID->usLangID == idLang) + { + return (langID->szLanguage); + } + langID++; + } + } + + return NULL; +} + +/***************************************************************************** + +GetStringFromList() + +PSTRINGLIST slList, - pointer to STRINGLIST used + +ULONG ulNumElements, - + number of elements in that STRINGLIST calc before call with sizeof(slList) / sizeof(STRINGLIST), +ULONG or ULONGLONG (if H264_SUPPORT is defined)ulFlag - - flag to look for +PCHAR szDefault - string to return if no match + +Return a string associated with a value from a stringtable. + +example: + GetStringFromList(slPowerState, + sizeof(slPowerState) / sizeof(STRINGLIST), + pUPI->SystemState, + "Invalid Power State") + +*****************************************************************************/ + +PCHAR +GetStringFromList( + PSTRINGLIST slList, + ULONG ulNumElements, +#ifdef H264_SUPPORT + ULONGLONG ulFlag, +#else + ULONG ulFlag, +#endif + _In_ PCHAR szDefault + ) +{ + // ulIndex is zero based, but ulNumElements is 1 based + // subtract 1 from ulNumElements so that are same base +#ifdef H264_SUPPORT + ULONGLONG ulIndex = 0; +#else + ULONG ulIndex = 0; +#endif + ulNumElements--; + + + for ( ; ulIndex <= ulNumElements; ulIndex++) + { + if (ulFlag == slList[ulIndex].ulFlag) + { + return (slList[ulIndex].pszString); + } + } + + return szDefault; +} + diff --git a/tests/projects/windows/winsdk/usbview/dispvid.c b/tests/projects/windows/winsdk/usbview/dispvid.c new file mode 100644 index 000000000..537309721 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/dispvid.c @@ -0,0 +1,5649 @@ +/*++ + +Copyright (c) 2002-2008 Microsoft Corporation + +Module Name: + +DISPVID.C + +Abstract: + +This source file contains routines which update the edit control +to display information about USB Video descriptors. + +Environment: + +user mode + +Revision History: + +11-22-2002 : created +03-28-2003 : major revisions from latest specs. +03-28-2008 : include USB Video Class 1.1 + +--*/ + +//***************************************************************************** +// I N C L U D E S +//***************************************************************************** + +#include "uvcview.h" +#include "h264.h" + +//***************************************************************************** +// G L O B A L S P R I V A T E T O T H I S F I L E +//***************************************************************************** + +int StillMethod = 0; + +// +// USB Device Class Definition for Video Devices 0.8b version +// +// 3.6.2.3 Camera Terminal Descriptor +// +STRINGLIST slCameraControl1 [] = +{ + {1, "Scanning Mode", ""}, + {2, "Auto-Exposure Mode", ""}, + {4, "Auto-Exposure Priority", ""}, + {8, "Exposure Time (Absolute)", ""}, + {0x10, "Exposure Time (Relative)", ""}, + {0x20, "Focus (Absolute)", ""}, + {0x40, "Focus (Relative)", ""}, + {0x80, "Iris (Absolute)", ""}, +}; +STRINGLIST slCameraControl2 [] = +{ + {1, "Iris (Relative)", ""}, + {2, "Zoom (Absolute)", ""}, + {4, "Zoom (Relative)", ""}, + {8, "PanTilt (Absolute)", ""}, + {0x10, "PanTilt (Relative)", ""}, + {0x20, "Roll (Absolute)", ""}, + {0x40, "Roll (Relative)", ""}, + {0x80, "Reserved", ""}, +}; +STRINGLIST slCameraControl3 [] = +{ + {1, "Reserved", ""}, + {2, "Focus, Auto", ""}, + {4, "Privacy", ""}, + {8, "Focus, Simple", ""}, + {0x10, "Window", ""}, + {0x20, "Region of Interest", ""}, + {0x40, "Reserved", ""}, + {0x80, "Reserved", ""}, +}; + +// 3.6.2.5 Processing Unit Descriptor +// +STRINGLIST slProcessorControls1 [] = +{ + {1, "Brightness", ""}, + {2, "Contrast", ""}, + {4, "Hue", ""}, + {8, "Saturation", ""}, + {0x10, "Sharpness", ""}, + {0x20, "Gamma", ""}, + {0x40, "White Balance Temperature", ""}, + {0x80, "White Balance Component", ""}, +}; +STRINGLIST slProcessorControls2 [] = +{ + {1, "Backlight Compensation", ""}, + {2, "Gain", ""}, + {4, "Power Line Frequency", ""}, + {8, "Hue, Auto", ""}, + {0x10, "White Balance Temperature, Auto", ""}, + {0x20, "White Balance Component, Auto", ""}, + {0x40, "Digital Multiplier", ""}, + {0x80, "Digital Multiplier Limit", ""}, +}; +STRINGLIST slProcessorControls3 [] = +{ + {1, "Analog Video Standard", ""}, + {2, "Analog Video Lock Status", ""}, + {4, "Contrast, Auto", ""}, + {8, "Reserved", ""}, + {0x10, "Reserved", ""}, + {0x20, "Reserved", ""}, + {0x40, "Reserved", ""}, + {0x80, "Reserved", ""}, +}; + + +STRINGLIST slProcessorVideoStandards [] = +{ + {1, "None", ""}, + {2, "NTSC - 525/60", ""}, + {4, "PAL - 625/50", ""}, + {8, "SECAM - 625/50", ""}, + {0x10, "NTSC - 625/50", ""}, + {0x20, "PAL - 525/60", ""}, + {0x40, "Reserved", ""}, + {0x80, "Reserved", ""}, +}; + +// 3.8.2.1 Input Header Descriptor +// +STRINGLIST slInputHeaderControls[]= +{ + {1, "Key Frame Rate" , ""}, + {2, "P Frame Rate" , ""}, + {4, "Compression Quality" , ""}, + {8, "Compression Window Size", ""}, + {0x10, "Generate Key Frame" , ""}, + {0x20, "Update Frame Segment" , ""}, + {0x40, "Reserved" , ""}, + {0x80, "Reserved" , ""}, +}; + +STRINGLIST slOutputHeaderControls[]= +{ + {1, "Key Frame Rate" , ""}, + {2, "P Frame Rate" , ""}, + {4, "Compression Quality" , ""}, + {8, "Compression Window Size", ""}, + {0x10, "Reserved" , ""}, + {0x20, "Reserved" , ""}, + {0x40, "Reserved" , ""}, + {0x80, "Reserved" , ""}, +}; + +STRINGLIST slMediaTransportControls[]= +{ + {1, "Transport Control" , ""}, + {2, "Absolute Track Number Control", ""}, + {4, "Media Information" , ""}, + {8, "Time Code Information" , ""}, + {0x10, "Reserved" , ""}, + {0x20, "Reserved" , ""}, + {0x40, "Reserved" , ""}, + {0x80, "Reserved" , ""}, +}; + +STRINGLIST slMediaTransportModes1[]= +{ + {1, "Play Forward", ""}, + {2, "Pause", ""}, + {4, "Rewind", ""}, + {8, "Fast Forward", ""}, + {0x10, "High Speed Rewind", ""}, + {0x20, "Stop", ""}, + {0x40, "Eject", ""}, + {0x80, "Play Next Frame", ""}, +}; + +STRINGLIST slMediaTransportModes2[]= +{ + {1, "Play Slowest Forward", ""}, + {2, "Play Slow Forward 4", ""}, + {4, "Play Slow Forward 3", ""}, + {8, "Play Slow Forward 2", ""}, + {0x10, "Play Slow Forward 1", ""}, + {0x20, "Play X1", ""}, + {0x40, "Play Fast Forward 1", ""}, + {0x80, "Play Fast Forward 2", ""}, +}; + +STRINGLIST slMediaTransportModes3[]= +{ + {1, "Play Fast Forward 3", ""}, + {2, "Play Fast Forward 4", ""}, + {4, "Play Fastest Forward", ""}, + {8, "Play Previous Frame", ""}, + {0x10, "Play Slowest Reverse", ""}, + {0x20, "Play Slow Reverse 4", ""}, + {0x40, "Play Slow Reverse 3", ""}, + {0x80, "Play Slow Reverse 2", ""}, +}; + +STRINGLIST slMediaTransportModes4[]= +{ + {1, "Play Slow Reverse 1", ""}, + {2, "Play X1 Reverse", ""}, + {4, "Play Fast Reverse 1", ""}, + {8, "Play Fast Reverse 2", ""}, + {0x10, "Play Fast Reverse 3", ""}, + {0x20, "Play Fast Reverse 4", ""}, + {0x40, "Play Fastest Reverse", ""}, + {0x80, "Record StateStart", ""}, +}; + +STRINGLIST slMediaTransportModes5[]= +{ + {1, "Record Pause", ""}, + {2, "Reserved", ""}, + {4, "Reserved", ""}, + {8, "Reserved", ""}, + {0x10, "Reserved", ""}, + {0x20, "Reserved", ""}, + {0x40, "Reserved", ""}, + {0x80, "Reserved", ""}, +}; + +STRINGLIST slInputTermTypes[]= +{ + {0x0100, "TT_VENDOR_SPECIFIC", "I//O"}, + {0x0101, "TT_STREAMING", "I//O"}, + {0x0400, "EXTERNAL_VENDOR_SPECIFIC", "I//O"}, + {0x0401, "COMPOSITE_CONNECTOR", "I//O"}, + {0x0402, "SVIDEO_CONNECTOR", "I//O"}, + {0x0403, "COMPONENT_CONNECTOR", "I//O"}, + {0x0200, "ITT_VENDOR_SPECIFIC", "I"}, + {0x0201, "ITT_CAMERA", "I"}, + {0x0202, "ITT_MEDIA_TRANSPORT_INPUT", "I"}, +}; +STRINGLIST slOutputTermTypes[]= +{ + {0x0100, "TT_VENDOR_SPECIFIC", "I//O"}, + {0x0101, "TT_STREAMING", "I//O"}, + {0x0400, "EXTERNAL_VENDOR_SPECIFIC", "I//O"}, + {0x0401, "COMPOSITE_CONNECTOR", "I//O"}, + {0x0402, "SVIDEO_CONNECTOR", "I//O"}, + {0x0403, "COMPONENT_CONNECTOR", "I//O"}, + {0x0300, "OTT_VENDOR_SPECIFIC", "O"}, + {0x0301, "OTT_DISPLAY", "O"}, + {0x0302, "OTT_MEDIA_TRANSPORT_OUTPUT", "O"}, +}; + +//***************************************************************************** +// L O C A L F U N C T I O N P R O T O T Y P E S +//***************************************************************************** + +BOOL +DisplayVCHeader ( + PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc + ); +BOOL +DisplayVCInputTerminal ( + PVIDEO_INPUT_TERMINAL VidITDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +BOOL +DisplayVCOutputTerminal ( + PVIDEO_OUTPUT_TERMINAL VidOTDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +BOOL +DisplayVCCameraTerminal ( + PVIDEO_CAMERA_TERMINAL CameraDesc + ); +BOOL +DisplayVCMediaTransInputTerminal ( + PVIDEO_INPUT_MTT VCMedTransInDesc + ); +BOOL +DisplayVCMediaTransOutputTerminal ( + PVIDEO_OUTPUT_MTT VCMedTransOutDesc + ); +BOOL +DisplayVCSelectorUnit ( + PVIDEO_SELECTOR_UNIT VidSelectorDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +BOOL +DisplayVCProcessingUnit ( + PVIDEO_PROCESSING_UNIT VidProcessingDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +BOOL +DisplayVCExtensionUnit ( + PVIDEO_EXTENSION_UNIT VidExtensionDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +BOOL +DisplayVidInHeader ( + PVIDEO_STREAMING_INPUT_HEADER VidInHeaderDesc + ); +BOOL +DisplayVidOutHeader ( + PVIDEO_STREAMING_OUTPUT_HEADER VidOutHeaderDesc + ); +BOOL +DisplayStillImageFrame ( + PVIDEO_STILL_IMAGE_FRAME StillFrameDesc + ); +BOOL +DisplayColorMatching ( + PVIDEO_COLORFORMAT ColorMatchDesc + ); +BOOL +DisplayUncompressedFormat ( + PVIDEO_FORMAT_UNCOMPRESSED UnCompFormatDesc + ); +BOOL +DisplayUncompressedFrameType ( + PVIDEO_FRAME_UNCOMPRESSED UnCompFrameDesc + ); +BOOL +DisplayUnComContinuousFrameType( + PVIDEO_FRAME_UNCOMPRESSED UContinuousDesc + ); +BOOL +DisplayUnComDiscreteFrameType( + PVIDEO_FRAME_UNCOMPRESSED UDiscreteDesc + ); +BOOL +DisplayMJPEGFormat ( + PVIDEO_FORMAT_MJPEG MJPEGFormatDesc + ); +BOOL +DisplayMJPEGFrameType ( + PVIDEO_FRAME_MJPEG MJPEGFrameDesc + ); +BOOL +DisplayMJPEGContinuousFrameType( + PVIDEO_FRAME_MJPEG MContinuousDesc + ); +BOOL +DisplayMJPEGDiscreteFrameType( + PVIDEO_FRAME_MJPEG MDiscreteDesc + ); +BOOL +DisplayMPEG1SSFormat ( + PVIDEO_FORMAT_MPEG1SS MPEG1SSFormatDesc + ); +BOOL +DisplayMPEG2PSFormat ( + PVIDEO_FORMAT_MPEG2PS MPEG2PSFormatDesc + ); +BOOL +DisplayMPEG2TSFormat ( + PVIDEO_FORMAT_MPEG2TS MPEG2TSFormatDesc + ); +BOOL +DisplayMPEG4SLFormat ( + PVIDEO_FORMAT_MPEG4SL MPEG4SLFormatDesc + ); +BOOL +DisplayDVFormat ( + PVIDEO_FORMAT_DV DVFormatDesc + ); +BOOL +DisplayVendorVidFormat ( + PVIDEO_FORMAT_VENDOR VendorVidFormatDesc + ); +BOOL +DisplayVendorVidFrameType ( + PVIDEO_FRAME_VENDOR VendorVidFrameDesc + ); +BOOL +DisplayVendorVidContinuousFrameType( + PVIDEO_FRAME_VENDOR VContinuousDesc + ); +BOOL +DisplayVendorVidDiscreteFrameType( + PVIDEO_FRAME_VENDOR VDiscreteDesc + ); +BOOL +DisplayFramePayloadFormat( + PVIDEO_FORMAT_FRAME FramePayloadFormatDesc + ); +BOOL +DisplayFramePayloadFrame( + PVIDEO_FRAME_FRAME FramePayloadFrameDesc + ); +BOOL +DisplayFramePayloadContinuousFrameType( + PVIDEO_FRAME_FRAME FContinuousDesc + ); +BOOL +DisplayFramePayloadDiscreteFrameType( + PVIDEO_FRAME_FRAME FDiscreteDesc + ); +BOOL +DisplayStreamPayload( + PVIDEO_FORMAT_STREAM StreamPayloadDesc + ); +BOOL +DisplayVSEndpoint ( + PVIDEO_CS_INTERRUPT VidEndpointDesc + ); +VOID +VDisplayBytes ( + PUCHAR Data, + USHORT Len + ); +PCHAR +VidFormatGUIDCodeToName ( + REFGUID VidFormatGUIDCode + ); +UINT +GetVCInterfaceSize ( + PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc + ); +UINT +CheckForColorMatchingDesc ( + PVIDEO_SPECIFIC FormatDesc, + UCHAR bNumFrameDescriptors, + UCHAR bDescriptorSubtype + ); +UINT +GetVSInterfaceSize ( + PUSB_COMMON_DESCRIPTOR VidInHeaderDesc, + USHORT wTotalLength + ); +BOOL +ValidateTerminalID( + UINT uTerminalID + ); +VOID +VDisplayDescString ( + UINT uControlSize, + PUCHAR pControl , + PSTRINGLIST pslControl + ); + +//***************************************************************************** +// L O C A L F U N C T I O N S +//***************************************************************************** + +//***************************************************************************** +// +// DisplayVideoDescriptor() UPDATED +// +// VidCommonDesc - An Video Class Descriptor +// +// bInterfaceSubClass - The SubClass of the Interface containing the descriptor +// +//***************************************************************************** + +BOOL +DisplayVideoDescriptor ( + PVIDEO_SPECIFIC VidCommonDesc, + UCHAR bInterfaceSubClass, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayVideoDescriptor -Class-Specific Video Descriptor + switch (VidCommonDesc->bDescriptorType) + { + case CS_INTERFACE: + //@@DisplayVideoDescriptor -Class-Specific Video Interface Descriptor + switch (bInterfaceSubClass) + { + case VIDEO_SUBCLASS_CONTROL: + //@@DisplayVideoDescriptor -Class-Specific Video Control Interface Descriptor + switch (VidCommonDesc->bDescriptorSubtype) + { + case VC_HEADER: + return DisplayVCHeader( + (PVIDEO_CONTROL_HEADER_UNIT)VidCommonDesc); + + case INPUT_TERMINAL: + return DisplayVCInputTerminal( + (PVIDEO_INPUT_TERMINAL)VidCommonDesc, + StringDescs, + LatestDevicePowerState); + + case OUTPUT_TERMINAL: + return DisplayVCOutputTerminal( + (PVIDEO_OUTPUT_TERMINAL)VidCommonDesc, + StringDescs, + LatestDevicePowerState); + + case SELECTOR_UNIT: + return DisplayVCSelectorUnit( + (PVIDEO_SELECTOR_UNIT)VidCommonDesc, + StringDescs, + LatestDevicePowerState); + + case PROCESSING_UNIT: + return DisplayVCProcessingUnit( + (PVIDEO_PROCESSING_UNIT)VidCommonDesc, + StringDescs, + LatestDevicePowerState); + + case EXTENSION_UNIT: + return DisplayVCExtensionUnit( + (PVIDEO_EXTENSION_UNIT)VidCommonDesc, + StringDescs, + LatestDevicePowerState); + +#ifdef H264_SUPPORT + case H264_ENCODING_UNIT: + return DisplayVCH264EncodingUnit( + (PVIDEO_ENCODING_UNIT)VidCommonDesc + ); + +#endif + +#ifdef H264_SUPPORT + case MAX_TYPE_UNIT+1: + // for H.264, the bDescriptorSubtype = 7, which is equal to MAX_TYPE_UNIT + // so now MAX_TYPE_UNIT needs to be set to 8 + //(TODO: need to change nt\sdpublic\internal\drivers\inc\uvcdesc.h's define + // of MAX_TYPE_UNIT from7 to 8, and ad the type for H.264 = 8) +#else + case MAX_TYPE_UNIT: +#endif + //@@TestCase B1.1 + //@@CAUTION + //@@Descriptor Field - bDescriptorSubtype + //@@An undefined descriptor subtype has been defined + AppendTextBuffer("*!*CAUTION: This is an undefined class specific "\ + "Video Control bDescriptorSubtype\r\n"); + break; + + default: + //@@TestCase B1.2 + //@@ERROR + //@@Descriptor Field - bDescriptorSubtype + //@@An unknown descriptor subtype has been defined + AppendTextBuffer("*!*ERROR: unknown bDescriptorSubtype\r\n"); + OOPS(); + break; + } + break; + + case VIDEO_SUBCLASS_STREAMING: + //@@DisplayVideoDescriptor -Class-Specific Video Streaming Interface Descriptor + switch (VidCommonDesc->bDescriptorSubtype) + { + case VS_INPUT_HEADER: + return DisplayVidInHeader( + (PVIDEO_STREAMING_INPUT_HEADER)VidCommonDesc); + + case VS_OUTPUT_HEADER: + return DisplayVidOutHeader( + (PVIDEO_STREAMING_OUTPUT_HEADER)VidCommonDesc); + + case VS_STILL_IMAGE_FRAME: + return DisplayStillImageFrame( + (PVIDEO_STILL_IMAGE_FRAME)VidCommonDesc); + + case VS_FORMAT_UNCOMPRESSED: +#ifdef H264_SUPPORT + { + BOOL retCode = DisplayUncompressedFormat( (PVIDEO_FORMAT_UNCOMPRESSED)VidCommonDesc ); + g_expectedNumberOfUncompressedFrameFrameDescriptors += ((PVIDEO_FORMAT_UNCOMPRESSED)VidCommonDesc)->bNumFrameDescriptors; + return retCode; + } +#else + return DisplayUncompressedFormat( + (PVIDEO_FORMAT_UNCOMPRESSED)VidCommonDesc); +#endif + + case VS_FRAME_UNCOMPRESSED: +#ifdef H264_SUPPORT + { + BOOL retCode = DisplayUncompressedFrameType( (PVIDEO_FRAME_UNCOMPRESSED)VidCommonDesc ); + g_numberOfUncompressedFrameFrameDescriptors++; + return retCode; + } +#else + return DisplayUncompressedFrameType( + (PVIDEO_FRAME_UNCOMPRESSED)VidCommonDesc); +#endif + +#ifdef H264_SUPPORT + case VS_FORMAT_H264: + { + BOOL retCode = DisplayVCH264Format( (PVIDEO_FORMAT_H264)VidCommonDesc ); + g_expectedNumberOfH264FrameDescriptors += ((PVIDEO_FORMAT_H264)VidCommonDesc)->bNumFrameDescriptors; + return retCode; + } + + case VS_FRAME_H264: + { + BOOL retCode = DisplayVCH264FrameType( (PVIDEO_FRAME_H264)VidCommonDesc ); + g_numberOfH264FrameDescriptors++; + return retCode; + } +#endif + + case VS_FORMAT_MJPEG: +#ifdef H264_SUPPORT // additional checks + { + BOOL retCode = DisplayMJPEGFormat( (PVIDEO_FORMAT_MJPEG)VidCommonDesc ); + g_expectedNumberOfMJPEGFrameDescriptors += ((PVIDEO_FORMAT_MJPEG)VidCommonDesc)->bNumFrameDescriptors; + return retCode; + } +#else + return DisplayMJPEGFormat( + (PVIDEO_FORMAT_MJPEG)VidCommonDesc); +#endif + + case VS_FRAME_MJPEG: +#ifdef H264_SUPPORT + { + BOOL retCode = DisplayMJPEGFrameType( (PVIDEO_FRAME_MJPEG)VidCommonDesc ); + g_numberOfMJPEGFrameDescriptors++; + return retCode; + } + +#else + return DisplayMJPEGFrameType( + (PVIDEO_FRAME_MJPEG)VidCommonDesc); +#endif + + + + case VS_FORMAT_MPEG1: + { + if (UVC10 == g_chUVCversion) + { + return DisplayMPEG1SSFormat( + (PVIDEO_FORMAT_MPEG1SS)VidCommonDesc); + } + else // this format is obsoleted in UVC version >= 1.1 + { + AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); + OOPS(); + break; + } + } + + case VS_FORMAT_MPEG2PS: + { + if (UVC10 == g_chUVCversion) + { + return DisplayMPEG2PSFormat( + (PVIDEO_FORMAT_MPEG2PS)VidCommonDesc); + } + else // this format is obsoleted in UVC version >= 1.1 + { + AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); + OOPS(); + break; + } + } + + case VS_FORMAT_MPEG2TS: + return DisplayMPEG2TSFormat( + (PVIDEO_FORMAT_MPEG2TS)VidCommonDesc); + + case VS_FORMAT_MPEG4SL: + { + if (UVC10 == g_chUVCversion) + { + return DisplayMPEG4SLFormat( + (PVIDEO_FORMAT_MPEG4SL)VidCommonDesc); + } + else // this format is obsoleted in UVC version >= 1.1 + { + AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); + OOPS(); + break; + } + } + + case VS_FORMAT_DV: + return DisplayDVFormat( + (PVIDEO_FORMAT_DV)VidCommonDesc); + + case VS_COLORFORMAT: + return DisplayColorMatching( + (PVIDEO_COLORFORMAT)VidCommonDesc); + + case VS_FORMAT_VENDOR: + { + if (UVC10 == g_chUVCversion) + { + return DisplayVendorVidFormat( + (PVIDEO_FORMAT_VENDOR)VidCommonDesc); + } + else // this format is obsoleted in UVC version >= 1.1 + { + AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); + OOPS(); + break; + } + } + + case VS_FRAME_VENDOR: + { + if (UVC10 == g_chUVCversion) + { + return DisplayVendorVidFrameType( + (PVIDEO_FRAME_VENDOR)VidCommonDesc); + } + else // this format is obsoleted in UVC version >= 1.1 + { + AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); + OOPS(); + break; + } + } + + case VS_FORMAT_FRAME_BASED: + { + if (UVC10 != g_chUVCversion) + { + return DisplayFramePayloadFormat( + (PVIDEO_FORMAT_FRAME)VidCommonDesc); + } + else // this format did not exist in UVC 1.0 + { + AppendTextBuffer("*!*ERROR: bDescriptorSubtype did not exist in UVC 1.0\r\n"); + OOPS(); + break; + } + } + + case VS_FRAME_FRAME_BASED: + { + if (UVC10 != g_chUVCversion) + { + return DisplayFramePayloadFrame( + (PVIDEO_FRAME_FRAME)VidCommonDesc); + } + else // this format did not exist in UVC 1.0 + { + AppendTextBuffer("*!*ERROR: bDescriptorSubtype did not exist in UVC 1.0\r\n"); + OOPS(); + break; + } + } + + case VS_FORMAT_STREAM_BASED: + { + if (UVC10 != g_chUVCversion) + { + return DisplayStreamPayload( + (PVIDEO_FORMAT_STREAM)VidCommonDesc); + } + else // this format did not exist in UVC 1.0 + { + AppendTextBuffer("*!*ERROR: bDescriptorSubtype did not exist in UVC 1.0\r\n"); + OOPS(); + break; + } + } + + case VS_DESCRIPTOR_UNDEFINED: + //@@TestCase B1.3 + //@@CAUTION + //@@Descriptor Field - bDescriptorSubtype + //@@An undefined descriptor subtype has been defined + AppendTextBuffer("*!*CAUTION: This is an undefined class specific Video "\ + "Streaming bDescriptorSubtype\r\n"); + break; + + default: + //@@TestCase B1.4 + //@@ERROR + //@@Descriptor Field - bDescriptorSubtype + //@@An unknown descriptor subtype has been defined + AppendTextBuffer("*!*ERROR: unknown bDescriptorSubtype\r\n"); + OOPS(); + break; + } + break; + + default: + //@@TestCase B1.6 + //@@ERROR + //@@Descriptor Field - bInterfaceSubClass + //@@An unknown interface sub-class has been defined + AppendTextBuffer("*!*ERROR: unknown bInterfaceSubClass\r\n"); + OOPS(); + break; + } + break; + + case CS_ENDPOINT: + //@@DisplayVideoDescriptor -Class-Specific Video Endpoint Descriptor + switch (VidCommonDesc->bDescriptorSubtype) + { + //@@TestCase B1.7 + //@@CAUTION + //@@Descriptor Field - bInterfaceSubtype + //@@An undefined descriptor subtype has been defined + case EP_UNDEFINED: + AppendTextBuffer("*!*CAUTION: This is an undefined bDescriptorSubtype\r\n"); + break; + //@@TestCase B1.8 + //@@Not yet implemented - Priority 3 + //@@Descriptor Field - bDescriptorSubtype + //@@Question: How valid are VIDEO_EP_GENERAL and VIDEO_EP_ENDPOINT? Should we test? + case EP_GENERAL: + break; + case EP_ENDPOINT: + break; + case EP_INTERRUPT: + return DisplayVSEndpoint( + (PVIDEO_CS_INTERRUPT)VidCommonDesc); + break; + default: + //@@TestCase B1.9 + //@@ERROR + //@@Descriptor Field - bDescriptorSubtype + //@@An unknown descriptor subtype has been defined + AppendTextBuffer("*!*CAUTION: Unknown bDescriptorSubtype"); + break; + } + break; + //@@DisplayVideoDescriptor -Class-Specific Video Device Descriptor + //@@DisplayVideoDescriptor -Class-Specific Video Configuration Descriptor + //@@DisplayVideoDescriptor -Class-Specific Video String Descriptor + //@@DisplayVideoDescriptor -Class-Specific Video Undefined Descriptor + //@@TestCase B1.10 + //@@Not yet implemented - Priority 3 + //@@Descriptor -Class-Specific Device, Configuration, String, Undefined + //@@Descriptor Field - bDescriptorType + //@@Question: How valid are these Descriptor Types? Should we test? + + /* case USB_VIDEO_CS_DEVICE: + AppendTextBuffer("USB_VIDEO_CS_DEVICE bDescriptorType\r\n"); + break; + + case USB_VIDEO_CS_CONFIGURATION: + AppendTextBuffer("USB_VIDEO_CS_CONFIGURATION bDescriptorType\r\n"); + break; + + case USB_VIDEO_CS_STRING: + AppendTextBuffer("USB_VIDEO_CS_STRING bDescriptorType\r\n"); + break; + + case USB_VIDEO_CS_UNDEFINED: + AppendTextBuffer("USB_VIDEO_CS_UNDEFINED bDescriptorType\r\n"); + break; + */ + default: + //@@TestCase B1.11 + //@@ERROR + //@@Descriptor Field - bDescriptorType + //@@An unknown descriptor type has been defined + AppendTextBuffer("*!*CAUTION: Unknown bDescriptorSubtype"); + OOPS(); + break; + } + + return FALSE; +} + + +//***************************************************************************** +// +// DisplayVCHeader() +// +//***************************************************************************** + +BOOL +DisplayVCHeader ( + PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc + ) +{ + //@@DisplayVCHeader -Video Control Interface Header + UINT i = 0; + UINT uSize = 0; + PUCHAR pData = NULL; + + AppendTextBuffer("\r\n ===>Class-Specific Video Control Interface Header "\ + "Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VCInterfaceDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VCInterfaceDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VCInterfaceDesc->bDescriptorSubtype); + if ( UVC10 == g_chUVCversion ) + { + AppendTextBuffer("bcdVDC: 0x%04X\r\n", VCInterfaceDesc->bcdVideoSpec); + } + else + { + AppendTextBuffer("bcdUVC: 0x%04X\r\n", VCInterfaceDesc->bcdVideoSpec); + } + AppendTextBuffer("wTotalLength: 0x%04X", VCInterfaceDesc->wTotalLength); + + // Verify the total interface size (size of this header and all descriptors + // following until and not including the first endpoint) + uSize = GetVCInterfaceSize(VCInterfaceDesc); + if (uSize != VCInterfaceDesc->wTotalLength) { + AppendTextBuffer("\r\n*!*ERROR: Invalid total interface size 0x%02X, should be 0x%02X\r\n", + VCInterfaceDesc->wTotalLength, uSize); + } else { + AppendTextBuffer(" -> Validated\r\n"); + } + AppendTextBuffer("dwClockFreq: 0x%08X", + VCInterfaceDesc->dwClockFreq); + if (gDoAnnotation) + { + AppendTextBuffer(" = (%d) Hz", VCInterfaceDesc->dwClockFreq); + } + AppendTextBuffer("\r\nbInCollection: 0x%02X\r\n", + VCInterfaceDesc->bInCollection); + + // baInterfaceNr is a variable length field + // Size is in bInCollection + for (i = 1, pData = (PUCHAR) &VCInterfaceDesc->bInCollection; + i <= VCInterfaceDesc->bInCollection; i++, pData++) + { + AppendTextBuffer("baInterfaceNr[%d]: 0x%02X\r\n", + i, *pData); + } + + uSize = (sizeof(VIDEO_CONTROL_HEADER_UNIT) + VCInterfaceDesc->bInCollection); + if (VCInterfaceDesc->bLength != uSize) + { + //@@TestCase B2.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is less than required length in + //@@ the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + VCInterfaceDesc->bLength, uSize); + OOPS(); + } + + //@@TestCase B2.2 (also in Descript.c) + //@@WARNING + //@@Descriptor Field - bcdVDC + //@@The bcdVDC version of the device is not the same as the version of used by USBView + if(VCInterfaceDesc->bcdVideoSpec < BCDVDC) + { + AppendTextBuffer("*!*WARNING: This device is set to the old USB Video "\ + "Class spec version 0x%04X\r\n", VCInterfaceDesc->bcdVideoSpec); + OOPS(); + } + + if (VCInterfaceDesc->dwClockFreq < 1) + { + //@@TestCase B2.3 (Descript.c Line 70) + //@@WARNING + //@@dwClockFrequency should be greater than 0 + //@@Question should we check that any non-zero value is accurate + AppendTextBuffer("*!*ERROR: dwClockFreq must be non-zero\r\n"); + OOPS(); + } + + //@@TestCase B2.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - baInterfaceNr + //@@We should test to verify each interface number is valid? + // for (i=0; ibInCollection; i++) + // {AppendTextBuffer("baInterfaceNr[%d]: 0x%02X\r\n", i+1, + // VCInterfaceDesc->baInterfaceNr[i]);} + + + if (gDoAnnotation) + { + switch(g_chUVCversion) + { + case UVC10: + AppendTextBuffer("USB Video Class device: spec version 1.0\r\n"); + break; + case UVC11: + AppendTextBuffer("USB Video Class device: spec version 1.1\r\n"); + break; +#ifdef H264_SUPPORT + case UVC15: + AppendTextBuffer("USB Video Class device: spec version 1.5\r\n"); + break; +#endif + + default: + break; + } + } + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCInputTerminal() +// +//***************************************************************************** + +BOOL +DisplayVCInputTerminal ( + PVIDEO_INPUT_TERMINAL VidITDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayVCInputTerminal -Video Control Input Terminal + PCHAR pStr = NULL; + + AppendTextBuffer("\r\n ===>Video Control Input Terminal Descriptor<===\r\n"); + + AppendTextBuffer("bLength: 0x%02X\r\n", VidITDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidITDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidITDesc->bDescriptorSubtype); + AppendTextBuffer("bTerminalID: 0x%02X\r\n", VidITDesc->bTerminalID); + AppendTextBuffer("wTerminalType: 0x%04X", VidITDesc->wTerminalType); + if(gDoAnnotation) + { + pStr = GetStringFromList(slInputTermTypes, + sizeof(slInputTermTypes) / sizeof(STRINGLIST), + VidITDesc->wTerminalType, + "Invalid Input Terminal Type"); + AppendTextBuffer(" = (%s)", pStr); + } + AppendTextBuffer("\r\n"); + + AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidITDesc->bAssocTerminal); + AppendTextBuffer("iTerminal: 0x%02X\r\n", VidITDesc->iTerminal); + if (gDoAnnotation) + { + if (VidITDesc->iTerminal) + { + // if executing this code, the configuration descriptor has been + // obtained. If a device is suspended, then its configuration + // descriptor was not obtained and we do not want errors to be + // displayed when string descriptors were not obtained. + DisplayStringDescriptor(VidITDesc->iTerminal, StringDescs, LatestDevicePowerState); + } + } + + if (VidITDesc->bLength < sizeof(VIDEO_INPUT_TERMINAL)) + { + //@@TestCase B3.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is less than required length in + //@@ the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d is too small\r\n", VidITDesc->bLength); + OOPS(); + } + + if (VidITDesc->bTerminalID < 1) + { + //@@TestCase B3.2 (descript.c line 133) + //@@ERROR + //@@Descriptor Field - bTerminalID + //@@bTerminalID should be greater than 0 + //@@Question: Should test to verify terminal number is valid + AppendTextBuffer("*!*ERROR: bTerminalID of %d is too small\r\n", VidITDesc->bTerminalID); + OOPS(); + } + + if (!(pStr)) + { + //@@TestCase B3.3 + //@@CAUTION + //@@Descriptor Field - wTerminalType + //@@No valid Terminal Type was found + AppendTextBuffer("*!*CAUTION: 0x%04X is an unknown wTerminalType for an Input "\ + "Terminal\r\n", VidITDesc->wTerminalType); + OOPS(); + } + + //@@TestCase B3.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bAssocTerminal + //@@Should test to verify terminal number is valid? + // AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidITDesc->bAssocTerminal); + + switch (VidITDesc->wTerminalType) + { + case 0x0100: // TT_VENDOR_SPECIFIC Terminal Type + break; + case 0x0101: // TT_STREAMING Terminal Type + break; + case 0x0200: // ITT_VENDOR_SPECIFIC Terminal Type + break; + case 0x0201: // ITT_CAMERA Terminal Type + return DisplayVCCameraTerminal( + (PVIDEO_CAMERA_TERMINAL)VidITDesc); + case 0x0202: // ITT_MEDIA_TRANSPORT_INPUT Terminal Type + return DisplayVCMediaTransInputTerminal( + (PVIDEO_INPUT_MTT)VidITDesc); + case 0x0400: // EXTERNAL_VENDOR_SPECIFIC Terminal Type + break; + case 0x0401: // COMPOSITE_CONNECTOR Terminal Type + break; + case 0x0402: // SVIDEO_CONNECTOR Terminal Type + break; + case 0x0403: // COMPONENT_CONNECTOR Terminal Type + break; + default: + break; + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCOutputTerminal() +// +//***************************************************************************** + +BOOL +DisplayVCOutputTerminal ( + PVIDEO_OUTPUT_TERMINAL VidOTDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayVCOutputTerminal -Video Control Output Terminal + PCHAR pStr = NULL; + + AppendTextBuffer("\r\n ===>Video Control Output Terminal Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VidOTDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidOTDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidOTDesc->bDescriptorSubtype); + AppendTextBuffer("bTerminalID: 0x%02X\r\n", VidOTDesc->bTerminalID); + AppendTextBuffer("wTerminalType: 0x%04X", VidOTDesc->wTerminalType); + if(gDoAnnotation) + { + pStr = GetStringFromList(slOutputTermTypes, + sizeof(slOutputTermTypes) / sizeof(STRINGLIST), + VidOTDesc->wTerminalType, + "Invalid Output Terminal Type"); + AppendTextBuffer(" = (%s)", pStr); + } + AppendTextBuffer("\r\n"); + AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidOTDesc->bAssocTerminal); + AppendTextBuffer("bSourceID: 0x%02X\r\n", VidOTDesc->bSourceID); + AppendTextBuffer("iTerminal: 0x%02X\r\n", VidOTDesc->iTerminal); + if (gDoAnnotation) + { + if (VidOTDesc->iTerminal) + { + // if executing this code, the configuration descriptor has been + // obtained. If a device is suspended, then its configuration + // descriptor was not obtained and we do not want errors to be + // displayed when string descriptors were not obtained. + DisplayStringDescriptor(VidOTDesc->iTerminal, StringDescs, LatestDevicePowerState); + } + } + + if (VidOTDesc->bLength < sizeof(PVIDEO_OUTPUT_TERMINAL)) + { + //@@TestCase B4.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is less than required length in + //@@ the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d is too small\r\n", VidOTDesc->bLength); + OOPS(); + } + + if (VidOTDesc->bTerminalID < 1) + { + //@@TestCase B4.2 (see Descript.c line 328) + //@@ERROR + //@@Descriptor Field - bTerminalID + //@@bTerminalID should be greater than 0 + //@@Question: Should test to verify terminal number is valid + AppendTextBuffer("*!*ERROR: bTerminalID of %d is too small\r\n", VidOTDesc->bTerminalID); + OOPS(); + } + + + if (!(pStr)) + { + //@@TestCase B4.3 + //@@ERROR + //@@Descriptor Field - wTerminalType + //@@No valid Terminal Type was found + AppendTextBuffer("*!*ERROR: 0x%04X is an invalid wTerminalType for an Output Terminal\r\n", + VidOTDesc->wTerminalType); + OOPS(); + } + + //@@TestCase B4.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bAssocTerminal + //@@We should test to verify terminal number is valid + // AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidOTDesc->bAssocTerminal); + + if (VidOTDesc->bSourceID < 1) + { + //@@TestCase B4.5 (see Descript.c line 333) + //@@ERROR + //@@Descriptor Field - bSourceID + //@@bSourceID should be greater than 0 + //@@Question: Should test to verify source number is valid + AppendTextBuffer("*!*ERROR: bSourceID of %d is too small\r\n", VidOTDesc->bSourceID); + OOPS(); + } + + switch (VidOTDesc->wTerminalType) + { + case 0x0100: // TT_VENDOR_SPECIFIC Terminal Type + break; + case 0x0101: // TT_STREAMING Terminal Type + break; + case 0x0300: // OTT_VENDOR_SPECIFIC Terminal Type + break; + case 0x0301: // OTT_DISPLAY Terminal Type + break; + case 0x0302: // OTT_MEDIA_TRANSPORT_OUTPUT Terminal Type + return DisplayVCMediaTransOutputTerminal( + (PVIDEO_OUTPUT_MTT)VidOTDesc); + case 0x0400: // EXTERNAL_VENDOR_SPECIFIC Terminal Type + break; + case 0x0401: // COMPOSITE_CONNECTOR Terminal Type + break; + case 0x0402: // SVIDEO_CONNECTOR Terminal Type + break; + case 0x0403: // COMPONENT_CONNECTOR Terminal Type + break; + default: + break; + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCMediaTransInputTerminal() +// +//***************************************************************************** + +BOOL +DisplayVCMediaTransInputTerminal( + PVIDEO_INPUT_MTT MediaTransportInDesc + ) +{ + //@@DisplayVCMediaTransInputTerminal -Video Control Media Transport Input Terminal + UCHAR p = 0; + PUCHAR pData = NULL; + size_t bLength = 0; + + bLength = SizeOfVideoInputMTT(MediaTransportInDesc); + + AppendTextBuffer("===>Additional Media Transport Input Terminal Data\r\n"); + AppendTextBuffer("bControlSize: 0x%02X\r\n", + MediaTransportInDesc->bControlSize); + + // point to bControlSize + pData = & MediaTransportInDesc->bControlSize; + + // Are there any controls? + if (0 < * pData) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 1); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportControls, + sizeof(slMediaTransportControls) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportCtrl bmControl value")); + + cMask = cMask << 1; + } + } + + // point to bTransportModeSize + pData = pData + 2 ; + + // Are there any controls? + if (0 < * pData) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 1); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes1, + sizeof(slMediaTransportModes1) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + + // Is there a second control? + if (1 < * pData) + { + // map the second control + for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 2); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes2, + sizeof(slMediaTransportModes2) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + // Is there a third control? + if (2 < * pData) + { + // map the third control + for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 3); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes3, + sizeof(slMediaTransportModes3) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + // Is there a fourth control? + if (3 < * pData) + { + // map the fourth control + for ( uBitIndex = 24, cMask = 1; uBitIndex < 32; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 4); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes4, + sizeof(slMediaTransportModes4) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + // Is there a fifth control? + if (4 < * pData) + { + // map the fifth control + for ( uBitIndex = 32, cMask = 1; uBitIndex < 40; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 5); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes5, + sizeof(slMediaTransportModes5) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + } + + // The size of a Media Transport Descriptor is + // the size of the Descriptor plus + // (bControlSize - 1) plus + // IF bmControls & 1 THEN 1 (bTransportModeSize) plus + // bTransportModeSize + // +// p = sizeof(VIDEO_INPUT_MTT) + +// (MediaTransportInDesc->bControlSize - 1); +// if (MediaTransportInDesc->bmControls[0] & 1) +// p += 1 + (*pData); + if (MediaTransportInDesc->bLength != bLength) + { + //@@TestCase B5.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@Invalid Descriptor length + AppendTextBuffer("*!*ERROR: Invalid descriptor bLength 0x%02X. "\ + "Should be 0x%02X\r\n", + MediaTransportInDesc->bLength, p); + OOPS(); + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCMediaTransOutputTerminal() +// +//***************************************************************************** + +BOOL +DisplayVCMediaTransOutputTerminal( + PVIDEO_OUTPUT_MTT MediaTransportOutDesc + ) +{ + //@@DisplayVCMediaTransOutputTerminal -Video Control Media Transport Output Terminal + UCHAR p = 0; + PUCHAR pData = NULL; + + AppendTextBuffer("===>Additional Media Transport Output Terminal Data\r\n"); + AppendTextBuffer("bControlSize: 0x%02X\r\n", + MediaTransportOutDesc->bControlSize); + + // point to bControlSize + pData = & MediaTransportOutDesc->bControlSize; + + // Are there any controls? + if (0 < * pData) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 1); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportControls, + sizeof(slMediaTransportControls) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportCtrl bmControl value")); + + cMask = cMask << 1; + } + } + + // point to bTransportModeSize + pData = pData + 2 ; + + // Are there any controls? + if (0 < * pData) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 1); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes1, + sizeof(slMediaTransportModes1) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + + // Is there a second control? + if (1 < * pData) + { + // map the second control + for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 2); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes2, + sizeof(slMediaTransportModes2) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + // Is there a third control? + if (2 < * pData) + { + // map the third control + for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 3); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes3, + sizeof(slMediaTransportModes3) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + // Is there a fourth control? + if (3 < * pData) + { + // map the fourth control + for ( uBitIndex = 24, cMask = 1; uBitIndex < 32; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 4); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes4, + sizeof(slMediaTransportModes4) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + // Is there a fifth control? + if (4 < * pData) + { + // map the fourth control + for ( uBitIndex = 32, cMask = 1; uBitIndex < 40; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 5); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slMediaTransportModes5, + sizeof(slMediaTransportModes5) / sizeof(STRINGLIST), + cMask, + "Invalid MediaTransportMode value")); + + cMask = cMask << 1; + } + } + } + + // The size of a Media Transport Descriptor is + // the size of the Descriptor plus + // (bControlSize - 1) plus + // IF bmControls & 1 THEN 1 (bTransportModeSize) plus + // bTransportModeSize + // + p = sizeof(VIDEO_OUTPUT_MTT) + + (MediaTransportOutDesc->bControlSize - 1); + if (MediaTransportOutDesc->bmControls[0] & 1) + p += 1 + (*pData); + if (MediaTransportOutDesc->bLength != p) + { + //@@TestCase B5.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@Invalid Descriptor length + AppendTextBuffer("*!*ERROR: Invalid descriptor bLength 0x%02X. "\ + "Should be 0x%02X\r\n", + MediaTransportOutDesc->bLength, p); + OOPS(); + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCCameraTerminal() +// +//***************************************************************************** + +BOOL +DisplayVCCameraTerminal( + PVIDEO_CAMERA_TERMINAL CameraDesc + ) +{ + //@@DisplayVCCameraTerminal -Video Control Camera Terminal + UCHAR p = 0; + PUCHAR pData = NULL; + + AppendTextBuffer("===>Camera Input Terminal Data\r\n"); + AppendTextBuffer("wObjectiveFocalLengthMin: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMin); + AppendTextBuffer("wObjectiveFocalLengthMax: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMax); + AppendTextBuffer("wOcularFocalLength: 0x%04X\r\n", CameraDesc->wOcularFocalLength); + AppendTextBuffer("bControlSize: 0x%02X\r\n", CameraDesc->bControlSize); + + pData = &CameraDesc->bControlSize; + + // Are there any controls? + if (0 < * pData) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 1); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slCameraControl1, + sizeof(slCameraControl1) / sizeof(STRINGLIST), + cMask, + "Invalid CamCtrl bmControl value")); + + cMask = cMask << 1; + } + + // Is there a second control? + if (1 < * pData) + { + // map the second control + for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 2); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slCameraControl2, + sizeof(slCameraControl2) / sizeof(STRINGLIST), + cMask, + "Invalid CamCtrl bmControl value")); + + cMask = cMask << 1; + } + } + // Is there a third control? + if (2 < * pData) + { + // map the third control + for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 3); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slCameraControl3, + sizeof(slCameraControl3) / sizeof(STRINGLIST), + cMask, + "Invalid CamCtrl bmControl value")); + + cMask = cMask << 1; + } + } + } + + p = (sizeof(VIDEO_CAMERA_TERMINAL) + CameraDesc->bControlSize); + if (CameraDesc->bLength != p) + { + //@@TestCase B7.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The descriptor should be the size of the descriptor structure + //@@ plus the number of controls + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + CameraDesc->bLength, p); + OOPS(); + } + + //@@TestCase B7.2 + //@@Not yet implemented - Priority 3 + //@@Descriptor Field - wObjectiveFocalLengthMin + //@@Question - Should we do any checking here? What are the acceptable boundaries? + //@@Question - Is zero an acceptable value? + // AppendTextBuffer("wObjectiveFocalLengthMin: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMin); + + //@@TestCase B7.3 + //@@Not yet implemented - Priority 3 + //@@Descriptor Field - wObjectiveFocalLengthMax + //@@Question - Should we do any checking here? What are the acceptable boundaries + //@@Question - Is zero an acceptable value? + // AppendTextBuffer("wObjectiveFocalLengthMax: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMax); + + //@@TestCase B7.4 + //@@Not yet implemented - Priority 3 + //@@Descriptor Field - wOcularFocalLength + //@@Question - Should we do any checking here? What are the acceptable boundaries + //@@Question - Is zero an acceptable value? + // AppendTextBuffer("wOcularFocalLength: 0x%04X\r\n", CameraDesc->wOcularFocalLength); + + //@@TestCase B7.5 + //@@ERROR + //@@Descriptor Field - wObjectiveFocalLengthMin and wObjectiveFocalLengthMax + //@@Verify that wObjectiveFocalLengthMax is greater than wObjectiveFocalLengthMin + if(CameraDesc->wObjectiveFocalLengthMin > CameraDesc->wObjectiveFocalLengthMax) + { + AppendTextBuffer("*!*ERROR: wObjectiveFocalLengthMin is larger than wObjectiveFocalLengthMax\r\n"); + OOPS(); + } + + //@@TestCase B7.6 + //@@ERROR + //@@Descriptor Field - bControlSize + //@@Verify that wObjectiveFocalLengthMax is 3 or less + if(CameraDesc->bControlSize > 3) + { + AppendTextBuffer("*!*ERROR: bControlSize must be 3 or less\r\n"); + OOPS(); + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayVCSelectorUnit() +// +//***************************************************************************** + +BOOL +DisplayVCSelectorUnit ( + PVIDEO_SELECTOR_UNIT VidSelectorDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayVCSelectorUnit -Video Control Selector Unit + UCHAR i = 0; + UCHAR p = 0; + PUCHAR pData = NULL; + + AppendTextBuffer("\r\n ===>Video Control Selector Unit Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VidSelectorDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidSelectorDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidSelectorDesc->bDescriptorSubtype); + AppendTextBuffer("bUnitID: 0x%02X\r\n", VidSelectorDesc->bUnitID); + AppendTextBuffer("bNrInPins: 0x%02X\r\n", VidSelectorDesc->bNrInPins); + if (gDoAnnotation) + { + AppendTextBuffer("===>List of Connected Unit and Terminal ID's\r\n"); + } + // baSourceID is a variable length field + // Size is in bNrInPins, must be at least 1 (so index starts at 1) + for (i = 1, pData = (PUCHAR) &VidSelectorDesc->baSourceID; + i <= VidSelectorDesc->bNrInPins; i++, pData++) + { + AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", + i, *pData); + } + + // get address of iSelector, the last field in this descriptor + pData = (PUCHAR) VidSelectorDesc + (VidSelectorDesc->bLength - 1); + AppendTextBuffer("iSelector: 0x%02X\r\n", *pData); + if (gDoAnnotation) + { + if (*pData) + { + // if executing this code, the configuration descriptor has been + // obtained. If a device is suspended, then its configuration + // descriptor was not obtained and we do not want errors to be + // displayed when string descriptors were not obtained. + DisplayStringDescriptor(*pData, StringDescs, LatestDevicePowerState); + } + } + + p = (sizeof(VIDEO_SELECTOR_UNIT) + VidSelectorDesc->bNrInPins + 1); + if (VidSelectorDesc->bLength != p) + { + //@@TestCase B8.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The descriptor should be the size of the descriptor structure plus the number of pins + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + VidSelectorDesc->bLength, p); + OOPS(); + } + + if (VidSelectorDesc->bUnitID < 1) + { + //@@TestCase B8.2 (Descript.c Line 396) + //@@ERROR + //@@Descriptor Field - bUnitID + //@@bUnitID must be greater than 0 + //@@Question: Should we test to verify unit number is unique? + AppendTextBuffer("*!*ERROR: bUnitID must be non-zero\r\n"); + OOPS(); + } + + if (VidSelectorDesc->bNrInPins < 1) + { + //@@TestCase B8.3 + //@@ERROR + //@@Descriptor Field - bNrInPins + //@@bNrInPins should be greater than 0 + //@@Question: Should test to verify total in pins is valid + AppendTextBuffer("*!*ERROR: bNrInPins must be non-zero\r\n"); + OOPS(); + } + + // baSourceID is a variable length field + // Size is in bNrInPins, must be at least 1 (so index starts at 1) + for (i = 1, pData = (PUCHAR) &VidSelectorDesc->baSourceID; + i <= VidSelectorDesc->bNrInPins; i++, pData++) + { + if (*pData < 1) + { + //@@TestCase B8.4 + //@@ERROR + //@@Descriptor Field - baSourceID[] + //@@baSourceID should be greater than 0 + AppendTextBuffer("*!*ERROR: baSourceID[%d] must be non-zero\r\n", i); + OOPS(); + } else { + if (! ValidateTerminalID(*pData)) { + //@@TestCase B8.5 + //@@ERROR + //@@Descriptor Field - baSourceID[] + //@@baSourceID should be a valid terminal ID + AppendTextBuffer("*!*ERROR: baSourceID[%d] must be non-zero\r\n", i); + OOPS(); + } + } + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCProcessingUnit() +// +//***************************************************************************** + +BOOL +DisplayVCProcessingUnit ( + PVIDEO_PROCESSING_UNIT VidProcessingDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayVCProcessingUnit -Video Control Processor Unit + PUCHAR pData = NULL; + UCHAR bLength = 0; + + AppendTextBuffer("\r\n ===>Video Control Processing Unit Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VidProcessingDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidProcessingDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidProcessingDesc->bDescriptorSubtype); + AppendTextBuffer("bUnitID: 0x%02X\r\n", VidProcessingDesc->bUnitID); + AppendTextBuffer("bSourceID: 0x%02X\r\n", VidProcessingDesc->bSourceID); + AppendTextBuffer("wMaxMultiplier: 0x%04X\r\n", VidProcessingDesc->wMaxMultiplier); + AppendTextBuffer("bControlSize: 0x%02X\r\n", VidProcessingDesc->bControlSize); + + pData = &VidProcessingDesc->bControlSize; + + // Are there any controls? + if (0 < * pData) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 1); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slProcessorControls1, + sizeof(slProcessorControls1) / sizeof(STRINGLIST), + cMask, + "Invalid PU bmControl value")); + + cMask = cMask << 1; + } + + // Is there a second control? + if (1 < * pData) + { + // map the second control + for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 2); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slProcessorControls2, + sizeof(slProcessorControls2) / sizeof(STRINGLIST), + cMask, + "Invalid PU bmControl value")); + + cMask = cMask << 1; + } + } + + // Is there a third control? + if (2 < * pData) + { + // map the third control + for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + 3); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slProcessorControls3, + sizeof(slProcessorControls3) / sizeof(STRINGLIST), + cMask, + "Invalid PU bmControl value")); + + cMask = cMask << 1; + } + } + } + + // get address of iProcessing + if (UVC10 != g_chUVCversion) + { + // size of descriptor is struct size plus control size plus 2 if UVC11 + bLength = sizeof(VIDEO_PROCESSING_UNIT) + 2 + VidProcessingDesc->bControlSize; + pData = (PUCHAR) VidProcessingDesc + (VidProcessingDesc->bLength - 2); + } + else // UVC 1.0 + { + // size of descriptor is struct size plus control size plus 1 if UVC10 + bLength = sizeof(VIDEO_PROCESSING_UNIT) + 1 + VidProcessingDesc->bControlSize; + pData = (PUCHAR) VidProcessingDesc + (VidProcessingDesc->bLength - 1); + } + AppendTextBuffer("iProcessing : 0x%02X\r\n", *pData); + if (gDoAnnotation) + { + if (*pData) + { + // if executing this code, the configuration descriptor has been + // obtained. If a device is suspended, then its configuration + // descriptor was not obtained and we do not want errors to be + // displayed when string descriptors were not obtained. + DisplayStringDescriptor(*pData, StringDescs, LatestDevicePowerState); + } + } + + // check for new UVC 1.1 bmVideoStandards fields + if (UVC10 != g_chUVCversion) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + pData = (PUCHAR) VidProcessingDesc + (VidProcessingDesc->bLength - 1); + + AppendTextBuffer("bmVideoStandards : "); + VDisplayBytes(pData, 1); + + // map the first control + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slProcessorVideoStandards, + sizeof(slProcessorVideoStandards) / sizeof(STRINGLIST), + cMask, + "Invalid PU bmVideoStandards value")); + + cMask = cMask << 1; + } + } + + if (VidProcessingDesc->bLength != bLength) + { + //@@TestCase B9.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + AppendTextBuffer("*!*ERROR: bLength of 0x%02X incorrect, should be 0x%02X\r\n", + VidProcessingDesc->bLength, bLength); + OOPS(); + } + + if (VidProcessingDesc->bUnitID < 1) + { + //@@TestCase B9.2 (Descript.c Line 466) + //@@ERROR + //@@Descriptor Field - bUnitID + //@@bUnitID must be greater than 0 + //@@Question: Should we test to verify unit number is unique? + AppendTextBuffer("*!*ERROR: bUnitID must be non-zero\r\n"); + OOPS(); + } + + if (VidProcessingDesc->bSourceID < 1) + { + //@@TestCase B9.3 (Descript.c Line 471) + //@@ERROR + //@@Descriptor Field - bSourceID + //@@bSourceID must be non-zero + //@@Question: Should we test to verify the bSourceID is valid? + AppendTextBuffer("*!*ERROR: bSourceID must be non-zero\r\n"); + OOPS(); + } + + //@@TestCase B9.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - wMaxMultiplier + //@@We should test to verify multiplier is valid + // AppendTextBuffer("wMaxMultiplier: 0x%04X\r\n", VidProcessingDesc->wMaxMultiplier); + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCExtensionUnit() +// +//***************************************************************************** + +BOOL +DisplayVCExtensionUnit ( + PVIDEO_EXTENSION_UNIT VidExtensionDesc, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ) +{ + //@@DisplayVCExtensionUnit -Video Control Extension Unit + int i = 0; + UCHAR p = 0; + UCHAR bControlSize = 0; + PUCHAR pData = NULL; + OLECHAR szGUID[256]; + size_t bLength = 0; + + bLength = SizeOfVideoExtensionUnit(VidExtensionDesc); + + memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); + i = StringFromGUID2((REFGUID) &VidExtensionDesc->guidExtensionCode, (LPOLESTR) szGUID, 255); + i++; + + AppendTextBuffer("\r\n ===>Video Control Extension Unit Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VidExtensionDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidExtensionDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidExtensionDesc->bDescriptorSubtype); + AppendTextBuffer("bUnitID: 0x%02X\r\n", VidExtensionDesc->bUnitID); + AppendTextBuffer("guidExtensionCode: %S\r\n", szGUID); + AppendTextBuffer("bNumControls: 0x%02X\r\n", VidExtensionDesc->bNumControls); + AppendTextBuffer("bNrInPins: 0x%02X\r\n", VidExtensionDesc->bNrInPins); + if (gDoAnnotation) + { + AppendTextBuffer("===>List of Connected Units and Terminal ID's\r\n"); + } + // baSourceID is a variable length field + // Size is in bNrInPins, must be at least 1 (so index starts at 1) + for (i = 1, pData = (PUCHAR) &VidExtensionDesc->baSourceID; + i <= VidExtensionDesc->bNrInPins; i++, pData++) + { + AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", + i, *pData); + } + // point to bControlSize (address of bNrInPins plus number of fields in bNrInPins + // plus 1 for next field) + pData = &VidExtensionDesc->bNrInPins + VidExtensionDesc->bNrInPins +1; + bControlSize = *pData; + AppendTextBuffer("bControlSize: 0x%02X\r\n", bControlSize); + + // Are there any controls? + if ( bControlSize > 0) + { + AppendTextBuffer("bmControls : "); + VDisplayBytes(pData + 1, *pData); + + // Map one byte at a time of the bmControls field in the Video Control Extension Unit Descriptor + for (i = 1; i <= bControlSize; i++) + { + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + // map byte + for ( ; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData + i); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex + 8 * (i-1), + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + "Vendor-Specific (Optional)"); + + cMask = cMask << 1; + } + } + } + + // get address of iExtension + pData = &VidExtensionDesc->bNrInPins + VidExtensionDesc->bNrInPins + bControlSize + 2; +// pData = (PUCHAR) VidExtensionDesc + (VidExtensionDesc->bLength - 1); + AppendTextBuffer("iExtension: 0x%02X\r\n", *pData); + if (gDoAnnotation) + { + if (*pData) + { + DisplayStringDescriptor(*pData,StringDescs, LatestDevicePowerState); + } + } + + // size of descriptor struct size (23) + bNrInPins + bControlSize + iExtension size + // +// p = (sizeof(VIDEO_EXTENSION_UNIT) +// + VidExtensionDesc->bNrInPins + bControlSize + 1); + if (VidExtensionDesc->bLength != bLength) + { + //@@TestCase B10.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@ required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of 0x%02X incorrect, should be 0x%02X\r\n", + VidExtensionDesc->bLength, p); + OOPS(); + } + + if (VidExtensionDesc->bUnitID < 1) + { + //@@TestCase B10.2 (Descript.c Line 517) + //@@ERROR + //@@Descriptor Field - bUnitID + //@@bUnitID must be non-zero + //@@Question: Should we test to verify bUnitID is valid + AppendTextBuffer("*!*ERROR: bUnitID must be non-zero\r\n"); + OOPS(); + } + + //bugbug do we need two + if (VidExtensionDesc->bNrInPins < 1) + { + //@@TestCase B10.3 (Descript.c Line 522) + //@@ERROR + //@@Descriptor Field - bNrInPins + //@@bNrInPins must be non-zero + //@@Question: Should we test to verify bNrInPins is valid + AppendTextBuffer("*!*ERROR: bNrInPins must be non-zero\r\n"); + OOPS(); + } + + for (i = 1, pData = (PUCHAR) &VidExtensionDesc->baSourceID; + i <= VidExtensionDesc->bNrInPins; i++, pData++) + { + if (*pData == 0) + { + //@@TestCase B10.4 (Descript.c Line 527) + //@@ERROR + //@@Descriptor Field - baSourceID[] + //@@baSourceID[] must be non-zero + //@@Question: Should we test to verify baSourceID is valid + AppendTextBuffer("*!*ERROR: baSourceID[%d] must be non-zero\r\n", *pData); + OOPS(); + } + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayVidInHeaderl() +// +//***************************************************************************** + +BOOL +DisplayVidInHeader ( + PVIDEO_STREAMING_INPUT_HEADER VidInHeaderDesc + ) +{ + //@@DisplayVidInHeader -Video Streaming Video Input Header + UINT p = 0; + UINT uCount = 0; + PUCHAR pData = NULL; + + AppendTextBuffer("\r\n ===>Video Class-Specific VS Video Input Header Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VidInHeaderDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidInHeaderDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidInHeaderDesc->bDescriptorSubtype); + AppendTextBuffer("bNumFormats: 0x%02X\r\n", VidInHeaderDesc->bNumFormats); + AppendTextBuffer("wTotalLength: 0x%04X", VidInHeaderDesc->wTotalLength); + + uCount = GetVSInterfaceSize((PUSB_COMMON_DESCRIPTOR) VidInHeaderDesc, VidInHeaderDesc->wTotalLength); + if (uCount != VidInHeaderDesc->wTotalLength) { + AppendTextBuffer("\r\n*!*ERROR: invalid interface size 0x%02X, should be 0x%02X\r\n", + VidInHeaderDesc->wTotalLength, uCount); + } else { + AppendTextBuffer(" -> Validated\r\n"); + } + + AppendTextBuffer("bEndpointAddress: 0x%02X", + VidInHeaderDesc->bEndpointAddress); + if (USB_ENDPOINT_DIRECTION_IN(VidInHeaderDesc->bEndpointAddress)) + { + if (gDoAnnotation) + { + AppendTextBuffer(" -> Direction: IN - EndpointID: %d", + (VidInHeaderDesc->bEndpointAddress & 0x0F)); + } + AppendTextBuffer("\r\n"); + } + AppendTextBuffer("bmInfo: 0x%02X", VidInHeaderDesc->bmInfo); + if (gDoAnnotation) + { + AppendTextBuffer(" -> Dynamic Format Change %sSupported", + ! (VidInHeaderDesc->bmInfo & 0x01) ? "not " : " "); + } + AppendTextBuffer("\r\nbTerminalLink: 0x%02X\r\n", + VidInHeaderDesc->bTerminalLink); + AppendTextBuffer("bStillCaptureMethod: 0x%02X", + VidInHeaderDesc->bStillCaptureMethod); + + // globally save the StillMethod, then verify value + StillMethod = VidInHeaderDesc->bStillCaptureMethod; + if (StillMethod > 3) + { + //@@TestCase B11.1 (Descript.c Line 798) + //@@ERROR + //@@Descriptor Field - bStillCaptureMethod + //@@bStillCaptureMethod is greater than 3 + AppendTextBuffer("*!*ERROR: invalid bStillCaptureMethod 0x%02X\r\n", + VidInHeaderDesc->bStillCaptureMethod); + if (gDoAnnotation) + { + AppendTextBuffer(" -> Invalid Still Capture Method"); + } + } + else + { + if (0 == StillMethod) + { + AppendTextBuffer(" -> No Still Capture"); + } + else + { + AppendTextBuffer(" -> Still Capture Method %d", + VidInHeaderDesc->bStillCaptureMethod); + } + } + + AppendTextBuffer("\r\nbTriggerSupport: 0x%02X", + VidInHeaderDesc->bTriggerSupport); + if(gDoAnnotation) + { + AppendTextBuffer(" -> "); + if (! VidInHeaderDesc->bTriggerSupport) + AppendTextBuffer("No "); + AppendTextBuffer("Hardware Triggering Support"); + } + AppendTextBuffer("\r\n"); + + AppendTextBuffer("bTriggerUsage: 0x%02X", + VidInHeaderDesc->bTriggerUsage); + if (gDoAnnotation) + { + if (VidInHeaderDesc->bTriggerSupport != 0) + { + if (VidInHeaderDesc->bTriggerUsage == 0) + AppendTextBuffer(" -> Host will initiate still image capture"); + if (VidInHeaderDesc->bTriggerUsage == 1) + AppendTextBuffer(" -> Host will notify client application of button event"); + } + } + + AppendTextBuffer("\r\nbControlSize: 0x%02X\r\n", + VidInHeaderDesc->bControlSize); + + // are there formats to display? + if (VidInHeaderDesc->bNumFormats) + { + UINT uFormatIndex = 1; + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + // There are (bNumFormats) bmaControls fields, each with size (bControlSize) + pData = (PUCHAR) &(VidInHeaderDesc->bControlSize); + + // VidInHeaderDesc->bNumFormats -> number of formats + // VidInHeaderDesc->bControlSize -> size of EACH format control + // ((PUCHAR) &VidInHeaderDesc->bControlSize) + 1 -> address of first format control + for ( pData++ ; uFormatIndex <= VidInHeaderDesc->bNumFormats; uFormatIndex++ ) + { + AppendTextBuffer("Video Payload Format %d ", uFormatIndex); + + // Handle case of 0 control size + if (! VidInHeaderDesc->bControlSize) + { + AppendTextBuffer("0x00\r\n"); + } + else + { + VDisplayBytes(pData, VidInHeaderDesc->bControlSize); + + // map the first control + for (uBitIndex = 0, cMask = 1; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pData); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slInputHeaderControls, + sizeof(slInputHeaderControls) / sizeof(STRINGLIST), + cMask, + "Invalid Control value")); + + cMask = cMask << 1; + } + } + pData += VidInHeaderDesc->bControlSize; + } + } + + p = (sizeof(VIDEO_STREAMING_INPUT_HEADER) + + (VidInHeaderDesc->bNumFormats * VidInHeaderDesc->bControlSize)); + if (VidInHeaderDesc->bLength != p) + { + //@@TestCase B11.2 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The descriptor should be the size of the descriptor structure + //@@ plus the number of formats times the size of each format + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + VidInHeaderDesc->bLength, p); + OOPS(); + } + + if (VidInHeaderDesc->bNumFormats < 1) + { + //@@TestCase B11.3 (Descript.c Line778) + //@@ERROR + //@@Descriptor Field - bNumFormats + //@@bNumFormats must be non-zero + //@@Question: Should we test to verify the non-zero value for bNumFormats is valid + AppendTextBuffer("*!*ERROR: bNumFormats must be non-zero\r\n", + VidInHeaderDesc->bNumFormats); + OOPS(); + } + + if (VidInHeaderDesc->bEndpointAddress < 1) + { + //@@TestCase B11.4 (Descript.c Line788) + //@@ERROR + //@@Descriptor Field - bEndpointAddress + //@@bEndpointAddress should be greater than 0 + //@@Question: Should we test to verify the non-zero value for bEndpointAddress is valid + AppendTextBuffer("*!*ERROR: bEndpointAddress of %d is too small\r\n", + VidInHeaderDesc->bEndpointAddress); + OOPS(); + } + + //@@TestCase B11.5 + //@@ERROR + //@@Descriptor Field - bEndPointAddress + //@@The bEndPointAddress is set incorrectly according to the USB Video Device Specification + if (!USB_ENDPOINT_DIRECTION_IN(VidInHeaderDesc->bEndpointAddress)){ + AppendTextBuffer("\r\n*!*ERROR: bEndPointAddress needs to have the Direction IN for this header\r\n"); + OOPS();} + + //@@TestCase B11.6 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bmInfo + //@@We should validate that reserved bits are set to zero. + // AppendTextBuffer("bmInfo: 0x%02X", VidInHeaderDesc->bmInfo); + + if (VidInHeaderDesc->bTerminalLink < 1) + { + //@@TestCase B11.7 (Descript.c Line 793) + //@@ERROR + //@@Descriptor Field - bTerminalLink + //@@bTerminalLink should be greater than 0 + //@@Question: Should we test to verify the non-zero value for bTerminalLink is valid + AppendTextBuffer("*!*ERROR: bTerminalLink of %d is too small\r\n", + VidInHeaderDesc->bTerminalLink); + OOPS(); + } + + //@@TestCase B11.8 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bTriggerSupport + //@@We should validate that reserved bits are set to zero. + // AppendTextBuffer("bTriggerSupport: 0x%02X", VidInHeaderDesc->bTriggerSupport); + + //@@TestCase B11.9 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bTriggerUsage + //@@We should validate that reserved bits are set to zero. + // AppendTextBuffer("bTriggerUsage: 0x%02X", VidInHeaderDesc->bTriggerUsage); + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVidOutHeader() +// +//***************************************************************************** + +BOOL +DisplayVidOutHeader ( + PVIDEO_STREAMING_OUTPUT_HEADER VidOutHeaderDesc + ) +{ + //@@DisplayVidOutHeader -Video Streaming Video Output Header + UINT uCount = 0; + UCHAR bLength = sizeof(VIDEO_STREAMING_OUTPUT_HEADER); + + AppendTextBuffer("\r\n ===>Video Class-Specific VS Video Output Header Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VidOutHeaderDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidOutHeaderDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidOutHeaderDesc->bDescriptorSubtype); + AppendTextBuffer("bNumFormats: 0x%02X\r\n", VidOutHeaderDesc->bNumFormats); + AppendTextBuffer("wTotalLength: 0x%04X", VidOutHeaderDesc->wTotalLength); + + uCount = GetVSInterfaceSize((PUSB_COMMON_DESCRIPTOR) VidOutHeaderDesc, VidOutHeaderDesc->wTotalLength); + if (uCount != VidOutHeaderDesc->wTotalLength) { + AppendTextBuffer("\r\n*!*ERROR: invalid interface size 0x%02X, should be 0x%02X\r\n", + VidOutHeaderDesc->wTotalLength, uCount); + } else { + AppendTextBuffer(" -> Validated\r\n"); + } + + AppendTextBuffer("bEndpointAddress: 0x%02X", VidOutHeaderDesc->bEndpointAddress); + if(USB_ENDPOINT_DIRECTION_OUT(VidOutHeaderDesc->bEndpointAddress)) { + if (gDoAnnotation) + { + AppendTextBuffer(" -> Direction: OUT - EndpointID: %d", + (VidOutHeaderDesc->bEndpointAddress & 0x0F)); + } + AppendTextBuffer("\r\n"); + } + AppendTextBuffer("bTerminalLink: 0x%02X\r\n", VidOutHeaderDesc->bTerminalLink); + + // UVC11 Video Output Header has additional fields, larger size +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) +#else + if (UVC11 == g_chUVCversion) +#endif + { + UCHAR bControlSize = 0; + PUCHAR pControls = NULL; + + // bControlSize field is next after bTerminalLink + pControls = &(VidOutHeaderDesc->bTerminalLink)+1; + bControlSize = *(pControls); + // point to first bmaControls + pControls++; + + // Size of UVC 1.1 Video Output Header is 1.0 size + // plus 1 (bControlSize field) plus (number of formats * bControlSize) + bLength += 1 + (VidOutHeaderDesc->bNumFormats * bControlSize); + + // Need new uvcdesc.h to handle new fields + AppendTextBuffer("bControlSize: 0x%02X\r\n", bControlSize); + + // are there formats to display? + if (VidOutHeaderDesc->bNumFormats) + { + UINT uFormatIndex = 1; + UINT uBitIndex = 0; + BYTE cCheckBit = 0; + BYTE cMask = 1; + + // There are (bNumFormats) bmaControls fields, each with size (bControlSize) + for ( ; uFormatIndex <= VidOutHeaderDesc->bNumFormats; uFormatIndex++, pControls ++) + { + AppendTextBuffer("Video Payload Format %d ", uFormatIndex); + + // Handle case of 0 control size + if (0 == bControlSize) + { + AppendTextBuffer("0x00\r\n"); + } + else + { + VDisplayBytes(pControls, bControlSize); + + // map the first control + for (uBitIndex = 0, cMask = 1; uBitIndex < 8; uBitIndex++ ) + { + cCheckBit = cMask & *(pControls); + + AppendTextBuffer(" D%02d = %d %s %s\r\n", + uBitIndex, + cCheckBit ? 1 : 0, + cCheckBit ? "yes - " : " no - ", + GetStringFromList(slOutputHeaderControls, + sizeof(slOutputHeaderControls) / sizeof(STRINGLIST), + cMask, + "Invalid control value")); + + cMask = cMask << 1; + } + } + } // for ( pData++ ; uFormatIndex <= VidOutHeaderDesc->bNumFormats; uFormatIndex++ ) + } // if (VidOutHeaderDesc->bNumFormats) + } // if (UVC11 == g_chUVCversion) + + if (VidOutHeaderDesc->bLength != bLength) + { + //@@TestCase B12.1 (also in Descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@ required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + VidOutHeaderDesc->bLength, + sizeof(VIDEO_STREAMING_OUTPUT_HEADER)); + OOPS(); + } + + if (VidOutHeaderDesc->bNumFormats < 1) + { + //@@TestCase B12.2 (Descript.c Line 827) + //@@ERROR + //@@Descriptor Field - bNumFormats + //@@bNumFormats should be greater than 0 + //@@Question: Should we test to verify the non-zero value for bNumFormats is valid + AppendTextBuffer("*!*ERROR: bNumFormats of %d is too small\r\n", + VidOutHeaderDesc->bNumFormats); + OOPS(); + } + + if (VidOutHeaderDesc->wTotalLength < VidOutHeaderDesc->bLength) + { + //@@TestCase B12.3 (Descript.c Line 832) + //@@ERROR + //@@Descriptor Field - wTotalLength + //@@wTotalLength should be greater than bLength + //@@Question: Should we calculate wTotalLength to verify the value is valid + AppendTextBuffer("*!*ERROR: wTotalLength of %d is small than the bLength of %d\r\n", + VidOutHeaderDesc->wTotalLength, + VidOutHeaderDesc->bLength); + OOPS(); + } + + if (VidOutHeaderDesc->bEndpointAddress < 1) + { + //@@TestCase B12.4 (Descript.c Line 837) + //@@ERROR + //@@Descriptor Field - bEndpointAddress + //@@bEndpointAddress should be greater than 0 + //@@Question: Should we test to verify the non-zero value for bEndpointAddress is valid + AppendTextBuffer("*!*ERROR: bEndpointAddress of %d is too small\r\n", + VidOutHeaderDesc->bEndpointAddress); + OOPS(); + } + + if(!(USB_ENDPOINT_DIRECTION_OUT(VidOutHeaderDesc->bEndpointAddress))) { + //@@TestCase B12.5 + //@@ERROR + //@@Descriptor Field - bEndPointAddress + //@@The bEndPointAddress is set for the wrong direction + AppendTextBuffer("\r\n*!*ERROR: bEndPointAddress needs to have the Direction OUT for this header\r\n"); + OOPS();} + + if (VidOutHeaderDesc->bTerminalLink < 1) + { + //@@TestCase B12.6 (Descript.c Line 842) + //@@ERROR + //@@Descriptor Field - bTerminalLink + //@@bTerminalLink should be greater than 0 + //@@Question: Should we test to verify the non-zero value for bTerminalLink is valid + AppendTextBuffer("*!*ERROR: bTerminalLink of %d is too small\r\n", + VidOutHeaderDesc->bTerminalLink); + OOPS(); + } + + return TRUE; + +} + + +//***************************************************************************** +// +// DisplayStillImageFrame() +// +//***************************************************************************** + +BOOL +DisplayStillImageFrame ( + PVIDEO_STILL_IMAGE_FRAME StillFrameDesc + ) +{ + //@@DisplayStillImageFrame -Still Image Frame + VIDEO_STILL_IMAGE_RECT * pXY; + PUCHAR pbCurr = NULL; + UINT i = 0; + UINT uNumComp = 0; + UINT uSize = 0; + size_t bLength = 0; + + bLength = SizeOfVideoStillImageFrame(StillFrameDesc); + + AppendTextBuffer("\r\n ===>Still Image Frame Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", StillFrameDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", StillFrameDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", StillFrameDesc->bDescriptorSubtype); + AppendTextBuffer("bEndpointAddress: 0x%02X\r\n", StillFrameDesc->bEndpointAddress); + AppendTextBuffer("bNumImageSizePatterns: 0x%02X\r\n", + StillFrameDesc->bNumImageSizePatterns); + if (StillFrameDesc->bNumImageSizePatterns < 1) + { + //@@TestCase B13.1 (also Descript.c Line 886) + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bNumImageSizePatterns + //@@The bNumImageSizePatterns should be greater than 0 + //@@Question: Should we test to verify the non-zero value for bNumImageSizePatterns is valid + AppendTextBuffer("*!*ERROR: bNumImageSizePatterns must be non-zero\r\n"); + OOPS(); + } + + // point to first StillFrameDesc->dwStillImage structure + pXY = (VIDEO_STILL_IMAGE_RECT *) &StillFrameDesc->aStillRect[0]; + + for (i = 1; i <= StillFrameDesc->bNumImageSizePatterns; i++, pXY++) + { + AppendTextBuffer("wWidth[%d]: 0x%04X\r\n", + i, pXY->wWidth); + AppendTextBuffer("wHeight[%d]: 0x%04X\r\n", + i, pXY->wHeight); + } + // point to bNumCompressionPattern field (after variable count field dwStillImage) + pbCurr = (PUCHAR) pXY; + // get number of compression patterns + uNumComp = *pbCurr; + + AppendTextBuffer("bNumCompressionPattern: 0x%02X\r\n", *pbCurr++); + for (i = 1; i <= uNumComp; i++) + { + AppendTextBuffer("bCompression[%d]: 0x%02X\r\n", + i, *pbCurr++); + } + + switch(StillMethod) { + case 0: + //@@TestCase B13.2 + //@@ERROR + //@@Descriptor Field - Still Image Frame Type Descriptor + //@@An still method type has been defined that shouldn't use a Still Image Frame + AppendTextBuffer("*!*ERROR: VS Video Input Header set to "\ + "No Still Method support\r\n"); + OOPS(); + case 1: + //@@TestCase B13.3 + //@@ERROR + //@@Descriptor Field - Still Image Frame Type Descriptor + //@@An still method type has been defined that shouldn't use a Still Image Frame + AppendTextBuffer("*!*ERROR: VS Video Input Header set to "\ + "Still Method One support with a Still Image Frame descriptor\r\n"); + OOPS(); + default: + break;} + + if (StillFrameDesc->bLength != bLength) + { + //@@TestCase B13.4 (Also in descript.c) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is incorrect + AppendTextBuffer("*!*ERROR: bLength 0x%02X incorrect, should be 0x%02X\r\n", + StillFrameDesc->bLength, uSize); + OOPS(); + } + + //@@TestCase B13.5 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bEndpointAddress + //@@Should test to verify endpoint validity + // AppendTextBuffer("bEndpointAddress: 0x%02X", StillFrameDesc->bEndpointAddress); + + if(USB_ENDPOINT_DIRECTION_IN(StillFrameDesc->bEndpointAddress) && StillMethod==3){ + if((StillFrameDesc->bEndpointAddress) == 0){ + //@@TestCase B13.6 + //@@ERROR + //@@Descriptor Field - bEndPointAddress + //@@bEndPointAddress should be non-zero for 0 when using StillMethod 3 + AppendTextBuffer("\r\n*!*ERROR: bEndpointAddress is reported as %d. "\ + "This should be non-zero when using StillMethod 3.\r\n", + (StillFrameDesc->bEndpointAddress)); + OOPS(); } + if (gDoAnnotation) + { + AppendTextBuffer(" -> Direction: IN - EndpointID: %d", + (StillFrameDesc->bEndpointAddress & 0x0F)); + } + AppendTextBuffer("\r\n"); + } + else if(USB_ENDPOINT_DIRECTION_OUT(StillFrameDesc->bEndpointAddress) && StillMethod==2) { + if((StillFrameDesc->bEndpointAddress & 0x0F) != 0) { + //@@TestCase B13.7 + //@@ERROR + //@@Descriptor Field - bEndPointAddress + //@@The EndpointID of bEndPointAddress should be set for 0 when using StillMethod 2 + AppendTextBuffer("\r\n*!*ERROR: The EndpointID of the "\ + "bEndpointAddress is reported as %d. This should be 0.\r\n", + (StillFrameDesc->bEndpointAddress & 0x0F)); + OOPS(); } + else {AppendTextBuffer("\r\n");}} + else if (StillFrameDesc->bEndpointAddress != 0) { + //@@TestCase B13.8 + //@@ERROR + //@@Descriptor Field - bEndPointAddress + //@@The bEndPointAddress should be set for 0 when not using StillMethod 2 or 3 + AppendTextBuffer("\r\n*!*ERROR: bEndPointAddress should be 0.\r\n"); + OOPS(); } + else {AppendTextBuffer("\r\n");} + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayColorMatching() +// +//***************************************************************************** + +BOOL +DisplayColorMatching ( + PVIDEO_COLORFORMAT ColorMatchDesc + ) +{ + //@@DisplayColorMatching -Color Matching + + AppendTextBuffer("\r\n ===>Color Matching Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", ColorMatchDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", ColorMatchDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", ColorMatchDesc->bDescriptorSubtype); + AppendTextBuffer("bColorPrimaries: 0x%02X\r\n", ColorMatchDesc->bColorPrimaries); + AppendTextBuffer("bTransferCharacteristics: 0x%02X\r\n", ColorMatchDesc->bTransferCharacteristics); + AppendTextBuffer("bMatrixCoefficients: 0x%02X\r\n", ColorMatchDesc->bMatrixCoefficients); + + if (ColorMatchDesc->bLength != sizeof(VIDEO_COLORFORMAT)) + { + //@@TestCase B14.1 (Descript.c Line 1596) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + ColorMatchDesc->bLength, + sizeof(VIDEO_COLORFORMAT)); + OOPS(); + } + + //@@TestCase B14.2 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bColorPrimaries + //@@Question - Should we test to verify bColorPrimaries + // AppendTextBuffer("bColorPrimaries: 0x%02X\r\n", ColorMatchDesc->bColorPrimaries); + + //@@TestCase B14.3 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bTransferCharacteristics + //@@Question - Should we test to verify bTransferCharacteristics + // AppendTextBuffer("bTransferCharacteristics: 0x%02X\r\n", ColorMatchDesc->bTransferCharacteristics); + + //@@TestCase B14.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bMatrixCoefficients + //@@Question - Should we test to verify bMatrixCoefficients + // AppendTextBuffer("bMatrixCoefficients: 0x%02X\r\n", ColorMatchDesc->bMatrixCoefficients); + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayUncompressedFormat() +// +//***************************************************************************** + +BOOL +DisplayUncompressedFormat ( + PVIDEO_FORMAT_UNCOMPRESSED UnCompFormatDesc + ) +{ + //@@DisplayUncompressedFormat - Uncompressed Format + int i = 0; + PCHAR pStr = NULL; + OLECHAR szGUID[256]; + + // Initialize the default Frame + g_chUNCFrameDefault = UnCompFormatDesc->bDefaultFrameIndex; + + memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); + i = StringFromGUID2((REFGUID) &UnCompFormatDesc->guidFormat, (LPOLESTR) szGUID, 255); + i++; + + AppendTextBuffer("\r\n ===>Video Streaming Uncompressed Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", UnCompFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", UnCompFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", UnCompFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", UnCompFormatDesc->bFormatIndex); + AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", UnCompFormatDesc->bNumFrameDescriptors); + AppendTextBuffer("guidFormat: %S", szGUID); + + pStr = VidFormatGUIDCodeToName((REFGUID) &UnCompFormatDesc->guidFormat); + if ( pStr ) + { + if ( gDoAnnotation ) + { + AppendTextBuffer(" = %s Format", pStr); + } + } + AppendTextBuffer("\r\n"); + AppendTextBuffer("bBitsPerPixel: 0x%02X\r\n", UnCompFormatDesc->bBitsPerPixel); + AppendTextBuffer("bDefaultFrameIndex: 0x%02X\r\n", UnCompFormatDesc->bDefaultFrameIndex); + + if (UnCompFormatDesc->bLength != sizeof(VIDEO_FORMAT_UNCOMPRESSED)) + { + //@@TestCase B15.1 (descript.c line 925) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required + //@@length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + UnCompFormatDesc->bLength, + sizeof(VIDEO_FORMAT_UNCOMPRESSED)); + OOPS(); + } + + if (UnCompFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B15.2 (descript.c line 930) + //@@ERROR + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bFormatIndex = 0, this is a 1 based index\r\n"); + OOPS(); + } + + if (UnCompFormatDesc->bNumFrameDescriptors == 0 ) + { + //@@TestCase B15.3 (descript.c line 930) + //@@ERROR + //@@Descriptor Field - bNumFrameDescriptors + //@@bNumFrameDescriptors is set to zero which is not in accordance with the + //@@USB Video Device Specification + AppendTextBuffer("*!*ERROR: bNumFrameDescriptors = 0, must have at least 1 Frame descriptor\r\n"); + OOPS(); + } + + if(!(pStr)) + { + //@@TestCase B15.4 + //@@WARNING + //@@Descriptor Field - guidFormat + //@@guidFormat is set to unknown or undefined format + AppendTextBuffer("\r\n*!*WARNING: guidFormat is an unknown format\r\n"); + OOPS(); + } + + if (UnCompFormatDesc->bBitsPerPixel == 0 ) + { + //@@TestCase B15.5 (descript.c line 940) + //@@ERROR + //@@Descriptor Field - bBitsPerPixel + //@@bBitsPerPixel is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bBitsPerPixel = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (UnCompFormatDesc->bDefaultFrameIndex == 0 || UnCompFormatDesc->bDefaultFrameIndex > + UnCompFormatDesc->bNumFrameDescriptors) + { + //@@TestCase B15.6 (desctipt.c line 945) + //@@ERROR + //@@Descriptor Field - bDefaultFrameIndex + //@@The value for bDefaultFrameIndex is not greater than 0 or less than or equal to bNumFrameDescriptors + AppendTextBuffer("*!*ERROR: The value %d for the bDefaultFrameIndex is out of range, this invalidates the descriptor\r\n*!*The proper range is 1 to %d)", + UnCompFormatDesc->bDefaultFrameIndex, + UnCompFormatDesc->bNumFrameDescriptors); + OOPS(); + } + + AppendTextBuffer("bAspectRatioX: 0x%02X\r\n", + UnCompFormatDesc->bAspectRatioX); + AppendTextBuffer("bAspectRatioY: 0x%02X", + UnCompFormatDesc->bAspectRatioY); + + if (((UnCompFormatDesc->bmInterlaceFlags & 0x01) && + (UnCompFormatDesc->bAspectRatioY != 0 && + UnCompFormatDesc->bAspectRatioX != 0))) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Aspect Ratio is set for a %d:%d display", + (UnCompFormatDesc->bAspectRatioX),(UnCompFormatDesc->bAspectRatioY)); + } + else + { + if (UnCompFormatDesc->bAspectRatioY != 0 || UnCompFormatDesc->bAspectRatioX != 0) + { + //@@TestCase B15.7 + //@@ERROR + //@@Descriptor Field - bAspectRatioX, bAspectRatioY + //@@Verify that that bAspectRatioX and bAspectRatioY are set to zero + //@@ if stream is non-interlaced + AppendTextBuffer("\r\n*!*ERROR: Both bAspectRatioX and bAspectRatioY "\ + "must equal 0 if stream is non-interlaced"); + OOPS(); + } + } + } + AppendTextBuffer("\r\nbmInterlaceFlags: 0x%02X\r\n", + UnCompFormatDesc->bmInterlaceFlags); + + if (gDoAnnotation) + { + AppendTextBuffer(" D0 = 0x%02X Interlaced stream or variable: %s\r\n", + (UnCompFormatDesc->bmInterlaceFlags & 1), + (UnCompFormatDesc->bmInterlaceFlags & 1) ? "Yes" : "No"); + AppendTextBuffer(" D1 = 0x%02X Fields per frame: %s\r\n", + ((UnCompFormatDesc->bmInterlaceFlags >> 1) & 1), + ((UnCompFormatDesc->bmInterlaceFlags >> 1) & 1) ? "1 field" : "2 fields"); + AppendTextBuffer(" D2 = 0x%02X Field 1 first: %s\r\n", + ((UnCompFormatDesc->bmInterlaceFlags >> 2) & 1), + ((UnCompFormatDesc->bmInterlaceFlags >> 2) & 1) ? "Yes" : "No"); + //@@TestCase B15.9 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bmInterlaceFlags + //@@Validate that reserved bits (D3) are set to zero. + AppendTextBuffer(" D3 = 0x%02X Reserved%s\r\n", + ((UnCompFormatDesc->bmInterlaceFlags >> 3) & 1), + ((UnCompFormatDesc->bmInterlaceFlags >> 3) & 1) ? + "\r\n*!*ERROR: Reserved to 0" : "" ); + AppendTextBuffer(" D4..5 = 0x%02X Field patterns ->", + ((UnCompFormatDesc->bmInterlaceFlags >> 4) & 3)); + switch(UnCompFormatDesc->bmInterlaceFlags & 0x30) + { + case 0x00: + AppendTextBuffer(" Field 1 only"); + break; + case 0x10: + AppendTextBuffer(" Field 2 only"); + break; + case 0x20: + AppendTextBuffer(" Regular Pattern of fields 1 and 2"); + break; + case 0x30: + AppendTextBuffer(" Random Pattern of fields 1 and 2"); + break; + } + AppendTextBuffer("\r\n D6..7 = 0x%02X Display Mode ->", + ((UnCompFormatDesc->bmInterlaceFlags >> 6) & 3)); + + switch(UnCompFormatDesc->bmInterlaceFlags & 0xC0) + { + case 0x00: + AppendTextBuffer(" Bob only"); + break; + case 0x40: + AppendTextBuffer(" Weave only"); + break; + case 0x80: + AppendTextBuffer(" Bob or weave"); + break; + case 0xC0: + //@@TestCase B15.10 + //@@Not yet implemented - Priority 3 + //@@Descriptor Field - bmInterlaceFlags + //@@Question - Should we validate that reserved bits are set to zero? + AppendTextBuffer(" Reserved"); + break; + } + } + + //@@TestCase B15.11 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bCopyProtect + //@@Question - Are their reserved bits and should we validate that + //@@ reserved bits are set to zero? + AppendTextBuffer("\r\nbCopyProtect: 0x%02X", + UnCompFormatDesc->bCopyProtect); + if (gDoAnnotation) + { + if (UnCompFormatDesc->bCopyProtect) + AppendTextBuffer(" -> Duplication Restricted"); + else + AppendTextBuffer(" -> Duplication Unrestricted"); + } + AppendTextBuffer("\r\n"); + + //@@TestCase B15.12 + //@@We should check to make sure that a Color Matching Descriptor is included in the device + // Check that the correct number of Frame Descriptors and one Color Matching + // descriptor follow + CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) UnCompFormatDesc, + UnCompFormatDesc->bNumFrameDescriptors, VS_FRAME_UNCOMPRESSED); + + return TRUE; + } + + +//***************************************************************************** +// +// DisplayUncompressedFrameType() +// +//***************************************************************************** + +BOOL +DisplayUncompressedFrameType ( + PVIDEO_FRAME_UNCOMPRESSED UnCompFrameDesc + ) +{ + size_t bLength = 0; + bLength = SizeOfVideoFrameUncompressed(UnCompFrameDesc); + + //@@DisplayUncompressedFrameType -Uncompressed Frame + + AppendTextBuffer("\r\n ===>Video Streaming Uncompressed Frame Type Descriptor<===\r\n"); + if (gDoAnnotation) + { + if(UnCompFrameDesc->bFrameIndex == g_chUNCFrameDefault) + { + AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); + } + } + AppendTextBuffer("bLength: 0x%02X\r\n", UnCompFrameDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", UnCompFrameDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", UnCompFrameDesc->bDescriptorSubtype); + AppendTextBuffer("bFrameIndex: 0x%02X\r\n", UnCompFrameDesc->bFrameIndex); + AppendTextBuffer("bmCapabilities: 0x%02X\r\n", UnCompFrameDesc->bmCapabilities); + AppendTextBuffer("wWidth: 0x%04X = %d\r\n", UnCompFrameDesc->wWidth, UnCompFrameDesc->wWidth); + AppendTextBuffer("wHeight: 0x%04X = %d\r\n", UnCompFrameDesc->wHeight, UnCompFrameDesc->wHeight); + AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", UnCompFrameDesc->dwMinBitRate); + AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", UnCompFrameDesc->dwMaxBitRate); + AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", UnCompFrameDesc->dwMaxVideoFrameBufferSize); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + UnCompFrameDesc->dwDefaultFrameInterval, + ((double)UnCompFrameDesc->dwDefaultFrameInterval)/10000.0, + (10000000.0/((double)UnCompFrameDesc->dwDefaultFrameInterval)) + ); + AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", UnCompFrameDesc->bFrameIntervalType); + + if (UnCompFrameDesc->bLength != bLength) + { + //@@TestCase B15.1 (descript.c line 925) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required + //@@length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + UnCompFrameDesc->bLength, bLength); + OOPS(); + } + + if (UnCompFrameDesc->bFrameIndex == 0 ) + { + //@@TestCase B16.2 (descript.c line 991) + //@@ERROR + //@@Descriptor Field - bFrameIndex + //@@bFrameIndex must be nonzero + AppendTextBuffer("*!*ERROR: bFrameIndex = 0, this is a 1 based index\r\n"); + OOPS(); + } + + //@@TestCase B16.3 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bmCapabilities + //@@Question: Should we try to verify that bmCapabilities is valid? + // AppendTextBuffer("bmCapabilities: 0x%02X\r\n", UnCompFrameDesc->bmCapabilities); + + if (UnCompFrameDesc->wWidth == 0 ) + { + //@@TestCase B16.4 (descript.c line 996) + //@@ERROR + //@@Descriptor Field - wWidth + //@@wWidth must be nonzero + AppendTextBuffer("*!*ERROR: wWidth must be nonzero\r\n"); + OOPS(); + } + + if (UnCompFrameDesc->wHeight == 0 ) + { + //@@TestCase B16.5 (descript.c line 1001) + //@@ERROR + //@@Descriptor Field - wHeight + //@@wHeight must be nonzero + AppendTextBuffer("*!*ERROR: wHeight must be nonzero\r\n"); + OOPS(); + } + + if (UnCompFrameDesc->dwMinBitRate == 0 ) + { + //@@TestCase B16.6 (descript.c line 1006) + //@@ERROR + //@@Descriptor Field - dwMinBitRate + //@@dwMinBitRate must be nonzero + AppendTextBuffer("*!*ERROR: dwMinBitRate must be nonzero\r\n"); + OOPS(); + } + + if (UnCompFrameDesc->dwMaxBitRate == 0 ) + { + //@@TestCase B16.7 (descript.c line 1011) + //@@ERROR + //@@Descriptor Field - dwMaxBitRate + //@@dwMaxBitRate must be nonzero + AppendTextBuffer("*!*ERROR: dwMaxBitRate must be nonzero\r\n"); + OOPS(); + } + + if(UnCompFrameDesc->dwMinBitRate > UnCompFrameDesc->dwMaxBitRate) + { + //@@TestCase B16.8 + //@@ERROR + //@@Descriptor Field - dwMinBitRate and dwMaxBitRate + //@@Verify that dwMaxBitRate is greater than dwMinBitRate + AppendTextBuffer("*!*ERROR: dwMinBitRate should be less than dwMaxBitRate\r\n"); + OOPS(); + } + else + { + if (UnCompFrameDesc->bFrameIntervalType == 1 && + UnCompFrameDesc->dwMinBitRate != UnCompFrameDesc->dwMaxBitRate) + { + //@@TestCase B16.9 + //@@WARNING + //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate + //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 + AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate "\ + "should equal dwMaxBitRate\r\n"); + OOPS(); + } + } + + if (UnCompFrameDesc->dwMaxVideoFrameBufferSize == 0 ) + { + //@@TestCase B16.10 (descript.c line 1015) + //@@WARNING + //@@Descriptor Field - bFrameIndex + //@@bFrameIndex must be nonzero + AppendTextBuffer("*!*WARNING: dwMaxVideoFrameBufferSize must be nonzero\r\n"); + OOPS(); + } + + if (UnCompFrameDesc->dwDefaultFrameInterval == 0 ) + { + //@@TestCase B16.11 (descript.c line 1020) + //@@WARNING + //@@Descriptor Field - dwDefaultFrameInterval + //@@dwDefaultFrameInterval must be nonzero + AppendTextBuffer("*!*WARNING: dwDefaultFrameInterval must be nonzero\r\n"); + OOPS(); + } + if (0 == UnCompFrameDesc->bFrameIntervalType) + { + DisplayUnComContinuousFrameType(UnCompFrameDesc); + } + else + { + DisplayUnComDiscreteFrameType(UnCompFrameDesc); + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayUnComContinuousFrameType() +// +//***************************************************************************** + +BOOL +DisplayUnComContinuousFrameType( + PVIDEO_FRAME_UNCOMPRESSED UContinuousDesc + ) +{ + //@@DisplayUnComContinuousFrameType -Uncompressed Continuous Frame + ULONG dwMinFrameInterval = UContinuousDesc->adwFrameInterval[0]; + ULONG dwMaxFrameInterval = UContinuousDesc->adwFrameInterval[1]; + ULONG dwFrameIntervalStep = UContinuousDesc->adwFrameInterval[2]; + + AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + + AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMinFrameInterval, + ((double)dwMinFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); + + AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMaxFrameInterval, + ((double)dwMaxFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); + + AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); + + if (dwMinFrameInterval == 0 ) + { + //@@TestCase B17.2 (descript.c line 1025) + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval + //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (dwMaxFrameInterval == 0 ) + { + //@@TestCase B17.3 (descript.c line 1025) + //@@ERROR + //@@Descriptor Field - dwMaxFrameInterval + //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if(dwMinFrameInterval > dwMaxFrameInterval) + { + //@@TestCase B17.4 (descript.c 1043) + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval + AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); + OOPS(); + } + else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) + { + //@@TestCase B17.5 + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) + { + //@@TestCase B17.6 + //@@CAUTION + //@@Descriptor Field - dwFrameIntervalStep + //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero + AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) + { + //@@TestCase B17.7 (descript.c 1052) + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); + OOPS(); + } + + if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) + { + //@@TestCase B17.8 (descript.c line 1032) + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval + AppendTextBuffer("*!*WARNING: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between dwMinFrameInterval and dwMaxFrameInterval\r\n"); + OOPS(); + } + + return TRUE; +} + +//***************************************************************************** +// +// DisplayUnComDiscreteFrameType() +// +//***************************************************************************** + +BOOL +DisplayUnComDiscreteFrameType( + PVIDEO_FRAME_UNCOMPRESSED UDiscreteDesc + ) +{ + //@@DisplayUnComDiscreteFrameType -Uncompressed Discrete Frame + UINT iNdex = 1; + UINT iCurFrame = 0; + ULONG * ulFrameInterval = NULL; + + AppendTextBuffer("===>Additional Discrete Frame Type Data\r\n"); + + // There are (UDiscreteDesc->bFrameIntervalType) dwFrameIntervals (1 based index) + for (; iNdex <= UDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) + { + ulFrameInterval = &UDiscreteDesc->adwFrameInterval[iCurFrame]; + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + iNdex, *ulFrameInterval, + ((double)*ulFrameInterval)/10000.0, + (10000000.0/((double)*ulFrameInterval)) + ); + if (0 == *ulFrameInterval) + { + //@@TestCase B18.1 (descript.c line 1061) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[x] must be non-zero + AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); + OOPS(); + } + if ((iNdex > 1)&&(*ulFrameInterval <= UDiscreteDesc->adwFrameInterval[iCurFrame - 1])) + { + //@@TestCase B18.2 (descript.c line 1067) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] + AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ + "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); + OOPS(); + } + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayMJPEGFormat() +// +//***************************************************************************** + +BOOL +DisplayMJPEGFormat ( + PVIDEO_FORMAT_MJPEG MJPEGFormatDesc + ) +{ + //@@DisplayMJPEGFormat - MJPEG Format + // Initialize the default Frame + g_chMJPEGFrameDefault = MJPEGFormatDesc->bDefaultFrameIndex; + + AppendTextBuffer("\r\n ===>Video Streaming MJPEG Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", MJPEGFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MJPEGFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MJPEGFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MJPEGFormatDesc->bFormatIndex); + AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", MJPEGFormatDesc->bNumFrameDescriptors); + + if (MJPEGFormatDesc->bLength != sizeof(VIDEO_FORMAT_MJPEG)) + { + //@@TestCase B19.1 (descript.c line 1098) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the + //@@ required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + MJPEGFormatDesc->bLength, + sizeof(VIDEO_FORMAT_MJPEG)); + OOPS(); + } + + if (MJPEGFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B19.2 (descript.c line 1103) + //@@ERROR + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with + //@@ the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bFormatIndex must be non-zero\r\n"); + OOPS(); + } + + if (MJPEGFormatDesc->bNumFrameDescriptors == 0 ) + { + //@@TestCase B19.3 (descript.c line 1108) + //@@ERROR + //@@Descriptor Field - bNumFrameDescriptors + //@@bNumFrameDescriptors is set to zero which is not in accordance + //@@ with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bNumFrameDescriptors must be non-zero\r\n"); + OOPS(); + } + + AppendTextBuffer("bmFlags: 0x%02X", + (MJPEGFormatDesc->bmFlags & 0x01)); + + //@@TestCase B19.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bmFlags + //@@We should validate that reserved bits are set to zero. + if (gDoAnnotation) + { + if(MJPEGFormatDesc->bmFlags & 0x01) + { + AppendTextBuffer(" -> Sample Size is Fixed"); + } + else + { + AppendTextBuffer(" -> Sample Size is Not Fixed"); + } + } + AppendTextBuffer("\r\nbDefaultFrameIndex: 0x%02X\r\n", + MJPEGFormatDesc->bDefaultFrameIndex); + + if (MJPEGFormatDesc->bDefaultFrameIndex == 0 || + MJPEGFormatDesc->bDefaultFrameIndex > + MJPEGFormatDesc->bNumFrameDescriptors) + { + //@@TestCase B19.5 (descript.c line 1113) + //@@ERROR + //@@Descriptor Field - bDefaultFrameIndex + //@@bDefaultFrameIndex is not in the domain of constrained by + //@@ bNumFrameDescriptors + AppendTextBuffer("*!*ERROR: bDefaultFrameIndex 0x%02X invalid, should "\ + "be between 1 and 0x%02x/r/n", + MJPEGFormatDesc->bDefaultFrameIndex, + MJPEGFormatDesc->bNumFrameDescriptors); + OOPS(); + } + + AppendTextBuffer("bAspectRatioX: 0x%02X\r\n", + MJPEGFormatDesc->bAspectRatioX); + AppendTextBuffer("bAspectRatioY: 0x%02X", + MJPEGFormatDesc->bAspectRatioY); + + if(((MJPEGFormatDesc->bmInterlaceFlags & 0x01) && + ((MJPEGFormatDesc->bAspectRatioY != 0) && + (MJPEGFormatDesc->bAspectRatioX != 0)))) + { + if (gDoAnnotation) + { + AppendTextBuffer(" -> Aspect Ratio is set for a %d:%d display", + (MJPEGFormatDesc->bAspectRatioX), (MJPEGFormatDesc->bAspectRatioY)); + } + } + else + { + if (MJPEGFormatDesc->bAspectRatioY != 0 || MJPEGFormatDesc->bAspectRatioX != 0) + { + //@@TestCase B19.6 + //@@ERROR + //@@Descriptor Field - bAspectRatioX and bAspectRatioY + //@@Verify that that bAspectRatioX and bAspectRatioY are set to zero + //@@ if stream is non-interlaced + AppendTextBuffer("\r\n*!*ERROR: bAspectRatioX and bAspectRatioY must "\ + "be 0 if stream non-Interlaced"); + OOPS(); + } + } + AppendTextBuffer("\r\nbmInterlaceFlags: 0x%02X\r\n", + MJPEGFormatDesc->bmInterlaceFlags); + + if (gDoAnnotation) + { + AppendTextBuffer(" D00 = %x %sInterlaced stream or variable\r\n", + (MJPEGFormatDesc->bmInterlaceFlags & 1), + (MJPEGFormatDesc->bmInterlaceFlags & 1) ? "" : " non-"); + AppendTextBuffer(" D01 = %x %s per frame\r\n", + ((MJPEGFormatDesc->bmInterlaceFlags >> 1) & 1), + ((MJPEGFormatDesc->bmInterlaceFlags >> 1) & 1) ? " 1 field" : " 2 fields"); + AppendTextBuffer(" D02 = %x Field 1 %sfirst\r\n", + ((MJPEGFormatDesc->bmInterlaceFlags >> 2) & 1), + ((MJPEGFormatDesc->bmInterlaceFlags >> 2) & 1) ? "" : "not "); + //@@TestCase B19.7 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bmInterlaceFlags + //@@Validate that reserved bits (D3) are set to zero. + AppendTextBuffer(" D03 = %x Reserved%s\r\n", + ((MJPEGFormatDesc->bmInterlaceFlags >> 3) & 1), + ((MJPEGFormatDesc->bmInterlaceFlags >> 3) & 1) ? + "\r\n*!*ERROR: non zero" : "" ); + AppendTextBuffer(" D4..5 = %x Field patterns ->", + ((MJPEGFormatDesc->bmInterlaceFlags >> 4) & 3)); + switch (MJPEGFormatDesc->bmInterlaceFlags & 0x30) + { + case 0x00: + AppendTextBuffer(" Field 1 only"); + break; + case 0x10: + AppendTextBuffer(" Field 2 only"); + break; + case 0x20: + AppendTextBuffer(" Regular Pattern of fields 1 and 2"); + break; + case 0x30: + AppendTextBuffer(" Random Pattern of fields 1 and 2"); + break; + } + AppendTextBuffer("\r\n D6..7 = %x Display Mode ->", + ((MJPEGFormatDesc->bmInterlaceFlags >> 6) & 3)); + switch(MJPEGFormatDesc->bmInterlaceFlags & 0xC0) + { + case 0x00: + AppendTextBuffer(" Bob only"); + break; + case 0x40: + AppendTextBuffer(" Weave only"); + break; + case 0x80: + AppendTextBuffer(" Bob or weave"); + break; + case 0xC0: + //@@TestCase B19.8 + //@@Not yet implemented - Priority 3 + //@@Descriptor Field - bmInterlaceFlags + //@@Question - Should we validate that reserved bits are set to zero? + AppendTextBuffer(" Reserved"); + break; + } + } + + //@@TestCase B19.9 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bCopyProtect + //@@Question - Are their reserved bits and should we validate that + //@@ reserved bits are set to zero? + AppendTextBuffer("\r\nbCopyProtect: 0x%02X", + MJPEGFormatDesc->bCopyProtect); + if (gDoAnnotation) + { + if (MJPEGFormatDesc->bCopyProtect) + AppendTextBuffer(" -> Duplication Restricted"); + else + AppendTextBuffer(" -> Duplication Unrestricted"); + } + AppendTextBuffer("\r\n"); + + // Check that the correct number of Frame Descriptors and one Color Matching + // descriptor follow + CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) MJPEGFormatDesc, + MJPEGFormatDesc->bNumFrameDescriptors, VS_FRAME_MJPEG); + + return TRUE; +} + +//***************************************************************************** +// +// DisplayMJPEGFrameType() +// +//***************************************************************************** + +BOOL +DisplayMJPEGFrameType ( + PVIDEO_FRAME_MJPEG MJPEGFrameDesc + ) +{ + //@@DisplayMJPEGFrameType -MJPEG Frame + size_t bLength = 0; + bLength = SizeOfVideoFrameMjpeg(MJPEGFrameDesc); + + AppendTextBuffer("\r\n ===>Video Streaming MJPEG Frame Type Descriptor<===\r\n"); + if (gDoAnnotation) + { + if(MJPEGFrameDesc->bFrameIndex == g_chMJPEGFrameDefault) + { + AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); + } + } + AppendTextBuffer("bLength: 0x%02X\r\n", MJPEGFrameDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MJPEGFrameDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MJPEGFrameDesc->bDescriptorSubtype); + AppendTextBuffer("bFrameIndex: 0x%02X\r\n", MJPEGFrameDesc->bFrameIndex); + AppendTextBuffer("bmCapabilities: 0x%02X\r\n", MJPEGFrameDesc->bmCapabilities); + AppendTextBuffer("wWidth: 0x%04X = %d\r\n", MJPEGFrameDesc->wWidth, MJPEGFrameDesc->wWidth); + AppendTextBuffer("wHeight: 0x%04X = %d\r\n", MJPEGFrameDesc->wHeight, MJPEGFrameDesc->wHeight); + AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", MJPEGFrameDesc->dwMinBitRate); + AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", MJPEGFrameDesc->dwMaxBitRate); + AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", MJPEGFrameDesc->dwMaxVideoFrameBufferSize); + + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + MJPEGFrameDesc->dwDefaultFrameInterval, + ((double)MJPEGFrameDesc->dwDefaultFrameInterval)/10000.0, + (10000000.0/((double)MJPEGFrameDesc->dwDefaultFrameInterval)) + ); + AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", MJPEGFrameDesc->bFrameIntervalType); + + if (MJPEGFrameDesc->bLength != bLength) + { + //@@TestCase B20.1 (descript.c line 1154) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is less than required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d is incorrect, should be %d\r\n", + MJPEGFrameDesc->bLength, bLength); + OOPS(); + } + + if (MJPEGFrameDesc->bFrameIndex == 0 ) + { + //@@TestCase B20.2 (descript.c line 1159) + //@@WARNING + //@@Descriptor Field - bFrameIndex + //@@bFrameIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: bFrameIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + //@@TestCase B20.3 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bmCapabilities + //@@Question: Should we try to verify that bmCapabilities is valid? + // AppendTextBuffer("bmCapabilities: 0x%02X\r\n", MJPEGFrameDesc->bmCapabilities); + + if (MJPEGFrameDesc->wWidth == 0 ) + { + //@@TestCase B20.4 (descript.c line 1164) + //@@ERROR + //@@Descriptor Field - wWidth + //@@wWidth is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: wWidth = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (MJPEGFrameDesc->wHeight == 0 ) + { + //@@TestCase B20.5 (descript.c line 1169) + //@@ERROR + //@@Descriptor Field - wHeight + //@@wHeight is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: wHeight = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (MJPEGFrameDesc->dwMinBitRate == 0 ) + { + //@@TestCase B20.6 (descript.c line 1174) + //@@ERROR + //@@Descriptor Field - dwMinBitRate + //@@dwMinBitRate is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMinBitRate = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (MJPEGFrameDesc->dwMaxBitRate == 0 ) + { + //@@TestCase B20.7 (descript.c line 1179) + //@@ERROR + //@@Descriptor Field - dwMaxBitRate + //@@dwMaxBitRate is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxBitRate = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if(MJPEGFrameDesc->dwMinBitRate > MJPEGFrameDesc->dwMaxBitRate) + { + //@@TestCase B20.8 + //@@ERROR + //@@Descriptor Field - dwMinBitRate and dwMaxBitRate + //@@Verify that dwMaxBitRate is greater than dwMinBitRate + AppendTextBuffer("*!*ERROR: dwMinBitRate > dwMaxBitRate, this invalidates the descriptor\r\n"); + OOPS(); + } + else if(MJPEGFrameDesc->bFrameIntervalType == 1 && MJPEGFrameDesc->dwMinBitRate != MJPEGFrameDesc->dwMaxBitRate) + { + //@@TestCase B20.9 + //@@WARNING + //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate + //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 + AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate should equal dwMaxBitRate\r\n"); + OOPS(); + } + + if (MJPEGFrameDesc->dwMaxVideoFrameBufferSize == 0 ) + { + //@@TestCase B20.10 (descript.c line 1183) + //@@ERROR + //@@Descriptor Field - dwMaxVideoFrameBufferSize + //@@dwMaxVideoFrameBufferSize is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxVideoFrameBufferSize = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (MJPEGFrameDesc->dwMaxVideoFrameBufferSize == 0 ) + { + //@@TestCase B20.11 (descript.c line 1188) + //@@ERROR + //@@Descriptor Field - dwDefaultFrameInterval + //@@dwDefaultFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwDefaultFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (0 == MJPEGFrameDesc->bFrameIntervalType) + { + DisplayMJPEGContinuousFrameType(MJPEGFrameDesc); + } + else + { + DisplayMJPEGDiscreteFrameType(MJPEGFrameDesc); + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayMJPEGContinuousFrameType() +// +//***************************************************************************** + +BOOL +DisplayMJPEGContinuousFrameType( + PVIDEO_FRAME_MJPEG MContinuousDesc + ) +{ + //@@DisplayMJPEGContinuousFrameType - MJPEG Continuous Frame + ULONG dwMinFrameInterval = MContinuousDesc->adwFrameInterval[0]; + ULONG dwMaxFrameInterval = MContinuousDesc->adwFrameInterval[1]; + ULONG dwFrameIntervalStep = MContinuousDesc->adwFrameInterval[2]; + + AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + + AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMinFrameInterval, + ((double)dwMinFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); + + AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMaxFrameInterval, + ((double)dwMaxFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); + + AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); + + if (dwMinFrameInterval == 0 ) + { + //@@TestCase B21.2 (descript.c line 1188) + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval + //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (dwMaxFrameInterval == 0 ) + { + //@@TestCase B21.3 (descript.c line 1188) + //@@ERROR + //@@Descriptor Field - dwMaxFrameInterval + //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if(dwMinFrameInterval > dwMaxFrameInterval) + { + //@@TestCase B21.4 (descript.c line 1211) + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval + AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); + OOPS(); + } + else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) + { + //@@TestCase B21.5 + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) + { + //@@TestCase B21.6 + //@@CAUTION + //@@Descriptor Field - dwFrameIntervalStep + //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero + AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) + { + //@@TestCase B21.7 (descript.c line 1220) + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); + OOPS(); + } + + if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) + { + //@@TestCase B21.8 (descript.c line 1200) + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval + AppendTextBuffer("*!*WARNING: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between \r\n *!*dwMinFrameInterval and dwMaxFrameInterval\r\n"); + OOPS(); + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayMJPEGDiscreteFrameType() +// +//***************************************************************************** + +BOOL +DisplayMJPEGDiscreteFrameType( + PVIDEO_FRAME_MJPEG MDiscreteDesc + ) +{ + //@@DisplayMJPEGDiscreteFrameType -MJPEG Discrete Frame + UINT iNdex = 1; + UINT iCurFrame = 0; + ULONG * ulFrameInterval = NULL; + + AppendTextBuffer("===>Additional Discrete Frame TypeData\r\n"); + + // There are (MDiscreteDesc->bFrameIntervalType) dwFrameIntervals (1 based index) + for (; iNdex <= MDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) + { + ulFrameInterval = &MDiscreteDesc->adwFrameInterval[iCurFrame]; + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + iNdex, *ulFrameInterval, + ((double)*ulFrameInterval)/10000.0, + (10000000.0/((double)*ulFrameInterval)) + ); + if (0 == *ulFrameInterval) + { + //@@TestCase B22.1 (descript.c line 1229) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[x] must be non-zero + AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); + OOPS(); + } + if ((iNdex > 1)&&(*ulFrameInterval <= MDiscreteDesc->adwFrameInterval[iCurFrame - 1])) + { + //@@TestCase B22.2 (descript.c line 1235) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] + AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ + "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); + OOPS(); + } + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayMPEG1SSFormat() +// +//***************************************************************************** + +BOOL +DisplayMPEG1SSFormat ( + PVIDEO_FORMAT_MPEG1SS MPEG1SSFormatDesc + ) +{ + //@@DisplayMPEG1SSFormat -MPEG1 SS Format + AppendTextBuffer("\r\n ===>Video Streaming MPEG1-SS Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", MPEG1SSFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG1SSFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG1SSFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG1SSFormatDesc->bFormatIndex); + AppendTextBuffer("wPacketLength: 0x%02X\r\n", MPEG1SSFormatDesc->bPacketLength); + AppendTextBuffer("wPackLength: 0x%02X\r\n", MPEG1SSFormatDesc->bPackLength); + AppendTextBuffer("bPackdataType: 0x%02X", (MPEG1SSFormatDesc->bPackDataType)); + if(gDoAnnotation) { + if(MPEG1SSFormatDesc->bPackDataType & 0x01){AppendTextBuffer(" -> Pack data size fixed\r\n");} + else {AppendTextBuffer(" -> Pack data size variable\r\n"); }} + else {AppendTextBuffer("\r\n");} + + + if (MPEG1SSFormatDesc->bLength != sizeof(VIDEO_FORMAT_MPEG1SS)) + { + //@@TestCase B23.1 (descript.c line 1514) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", + MPEG1SSFormatDesc->bLength, + sizeof(VIDEO_FORMAT_MPEG1SS)); + OOPS(); + } + + if (MPEG1SSFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B23.2 (descript.c line 1519) + //@@WARNING + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + //@@TestCase B23.3 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bPackdataType + //@@Question - Should we validate that reserved bits are set to zero? + // AppendTextBuffer("bPackdataType: 0x%02X", (MPEG1SSFormatDesc->bPackdataType & 0x01)); + + // This descriptor is deprecated for UVC 1.1 +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); + } +#else + if (UVC11 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); + } +#endif + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayMPEG2PSFormat() +// +//***************************************************************************** + +BOOL +DisplayMPEG2PSFormat ( + PVIDEO_FORMAT_MPEG2PS MPEG2PSFormatDesc + ) +{ + //@@DisplayMPEG2PSFormat -MPEG2 PS Format + AppendTextBuffer("\r\n ===>Video Streaming MPEG2-PS Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", MPEG2PSFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG2PSFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG2PSFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG2PSFormatDesc->bFormatIndex); + AppendTextBuffer("bPacketLength: 0x%02X\r\n", MPEG2PSFormatDesc->bPacketLength); + AppendTextBuffer("bPackLength: 0x%02X\r\n", MPEG2PSFormatDesc->bPackLength); + AppendTextBuffer("bPackDataType: 0x%02X", (MPEG2PSFormatDesc->bPackDataType)); + + if (MPEG2PSFormatDesc->bLength != sizeof(VIDEO_FORMAT_MPEG2PS)) + { + //@@TestCase B24.1 (descript.c line 1542) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", + MPEG2PSFormatDesc->bLength, + sizeof(VIDEO_FORMAT_MPEG2PS)); + OOPS(); + AppendTextBuffer("*!*USBView will try to display the rest of the descriptor but results may not be accurate\r\n"); + } + + if (MPEG2PSFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B24.2 (descript.c line 1547) + //@@WARNING + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + //@@TestCase B24.3 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bPackdataType + //@@Question - Should we validate that reserved bits are set to zero? + // AppendTextBuffer("bPackdataType: 0x%02X", (MPEG2PSFormatDesc->bPackdataType & 0x01)); + + // This descriptor is deprecated for UVC 1.1 +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); + } +#else + if (UVC11 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); + } +#endif + + return TRUE; + +} + + +//***************************************************************************** +// +// DisplayMPEG2TSFormat() +// +//***************************************************************************** + +BOOL +DisplayMPEG2TSFormat ( + PVIDEO_FORMAT_MPEG2TS MPEG2TSFormatDesc + ) +{ + //@@DisplayMPEG2TSFormat -MPEG2 TS Format + UCHAR bLength = sizeof(VIDEO_FORMAT_MPEG2TS); + + AppendTextBuffer("\r\n ===>Video Streaming MPEG2-TS Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", MPEG2TSFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG2TSFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG2TSFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG2TSFormatDesc->bFormatIndex); + AppendTextBuffer("bDataOffset: 0x%02X\r\n", MPEG2TSFormatDesc->bDataOffset); + AppendTextBuffer("bPacketLength: 0x%02X\r\n", MPEG2TSFormatDesc->bPacketLength); + AppendTextBuffer("bStrideLength: 0x%02X\r\n", MPEG2TSFormatDesc->bStrideLength); + +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) +#else + if (UVC11 == g_chUVCversion) +#endif + { + int i = 0; + PCHAR pStr = NULL; + OLECHAR szGUID[256]; + GUID * pStrideGuid = NULL; + + pStrideGuid = (GUID *) (&MPEG2TSFormatDesc->bStrideLength + 1); + + memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); + i = StringFromGUID2((REFGUID) pStrideGuid, (LPOLESTR) szGUID, 255); + i++; + AppendTextBuffer("guidStrideFormat: %S", szGUID); + pStr = VidFormatGUIDCodeToName((REFGUID) pStrideGuid); + if(gDoAnnotation) + { + if (pStr) + { + AppendTextBuffer(" = %s Format", pStr); + } + } + AppendTextBuffer("\r\n"); + bLength = sizeof(VIDEO_FORMAT_MPEG2TS) + sizeof(GUID); + } + + if (MPEG2TSFormatDesc->bLength != bLength) + { + //@@TestCase B25.1 (descript.c line 1486) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + MPEG2TSFormatDesc->bLength, + sizeof(VIDEO_FORMAT_MPEG2TS)); + OOPS(); + } + + if (MPEG2TSFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B25.2 (descript.c line 1491) + //@@WARNING + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + //@@TestCase B25.3 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bDataOffset, wPacket and wStride + //@@Question - Should we check that if bDataOffset is 0 that wPacket and wStride should equal each other + // AppendTextBuffer("bDataOffset: 0x%02X\r\n", MPEG2TSFormatDesc->bDataOffset); + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayMPEG4SLFormat() +// +//***************************************************************************** + +BOOL +DisplayMPEG4SLFormat ( + PVIDEO_FORMAT_MPEG4SL MPEG4SLFormatDesc + ) +{ + //@@DisplayMPEG4SLFormat -MPEG4 SL Format + + AppendTextBuffer("\r\n ===>Video Streaming MPEG4-SL Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", MPEG4SLFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG4SLFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG4SLFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG4SLFormatDesc->bFormatIndex); + AppendTextBuffer("bPacketLength: 0x%02X\r\n", MPEG4SLFormatDesc->bPacketLength); + + if (MPEG4SLFormatDesc->bLength != sizeof(VIDEO_FORMAT_MPEG4SL)) + { + //@@TestCase B26.1 (descript.c line 1568) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", + MPEG4SLFormatDesc->bLength, + sizeof(VIDEO_FORMAT_MPEG4SL)); + OOPS(); + } + + if (MPEG4SLFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B26.2 (descript.c line 1573) + //@@WARNING + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + // This descriptor is deprecated for UVC 1.1 +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); + } +#else + if (UVC11 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); + } +#endif + return TRUE; +} + + +//***************************************************************************** +// +// DisplayStreamPayload() +// +//***************************************************************************** + +BOOL +DisplayStreamPayload ( + PVIDEO_FORMAT_STREAM StreamPayloadDesc + ) +{ + //@@DisplayStreamPayload -Stream Based Payload Format + PCHAR pStr = NULL; + OLECHAR szGUID[256]; + int i = 0; + + memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); + i = StringFromGUID2((REFGUID) &StreamPayloadDesc->guidFormat, (LPOLESTR) szGUID, 255); + i++; + + AppendTextBuffer("\r\n ===>Video Streaming Stream Based Payload Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", StreamPayloadDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", StreamPayloadDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", StreamPayloadDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", StreamPayloadDesc->bFormatIndex); + AppendTextBuffer("guidFormat: %S", szGUID); + + pStr = VidFormatGUIDCodeToName((REFGUID) &StreamPayloadDesc->guidFormat); + if(gDoAnnotation) + { + if (pStr) + { + AppendTextBuffer(" = %s Format", pStr); + } + } + AppendTextBuffer("\r\n"); + AppendTextBuffer("dwPacketLength: 0x%02X\r\n", StreamPayloadDesc->dwPacketLength); + + if (StreamPayloadDesc->bLength != sizeof(VIDEO_FORMAT_STREAM)) + { + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + StreamPayloadDesc->bLength, + sizeof(PVIDEO_FORMAT_STREAM)); + OOPS(); + } + + if (StreamPayloadDesc->bFormatIndex == 0 ) + { + //@@WARNING + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this is a 1 based index\r\n"); + OOPS(); + } + + // This descriptor is new for UVC 1.1 + if (UVC10 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.0 devices\r\n"); + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayDVFormat() +// +//***************************************************************************** + +BOOL +DisplayDVFormat ( + PVIDEO_FORMAT_DV DVFormatDesc + ) +{ + //@@DisplayDVFormat -Digital Video Format + + AppendTextBuffer("\r\n ===>Video Streaming DV Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", DVFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", DVFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", DVFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", DVFormatDesc->bFormatIndex); + AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", DVFormatDesc->dwMaxVideoFrameBufferSize); + AppendTextBuffer("bFormatType: 0x%02X\r\n", DVFormatDesc->bFormatType); + if (gDoAnnotation) + { + AppendTextBuffer(" D0..6 = Format Type ->"); + switch(DVFormatDesc->bFormatType & 0x03) + { + case 0x00: + AppendTextBuffer(" SD-DV\r\n"); + break; + case 0x01: + AppendTextBuffer(" SDL-DV\r\n"); + break; + case 0x02: + AppendTextBuffer(" HD-DV\r\n"); + break; + default: + AppendTextBuffer(" Unknown Format\r\n"); + break; + } + if (DVFormatDesc->bFormatType & 0x80) + AppendTextBuffer(" D7 = 60Hz"); + else + AppendTextBuffer(" D7 = 50Hz"); + AppendTextBuffer("\r\n");} + + if (DVFormatDesc->bLength != sizeof(VIDEO_FORMAT_DV)) + { + //@@TestCase B27.1 (descript.c line 1453) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + DVFormatDesc->bLength, + sizeof(VIDEO_FORMAT_DV)); + OOPS(); + } + + if (DVFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B27.2 (descript.c line 1458) + //@@ERROR + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex invalid + AppendTextBuffer("*!*ERROR: bFormatIndex of 0x%02X is invalid\r\n", + DVFormatDesc->bFormatIndex); + OOPS(); + } + + if (DVFormatDesc->dwMaxVideoFrameBufferSize == 0 ) + { + //@@TestCase B27.3 (descript.c line 1463) + //@@ERROR + //@@Descriptor Field - dwMaxVideoFrameBufferSize + //@@dwMaxVideoFrameBufferSize invalid + AppendTextBuffer("*!*ERROR: dwMaxVideoFrameBufferSize of 0x%02X is invalid\r\n", + DVFormatDesc->dwMaxVideoFrameBufferSize); + OOPS(); + } + + //@@TestCase B27.4 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bFormatType + //@@Question - Should we validate that reserved bits are set to zero? + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVidVendorFormat() +// +//***************************************************************************** + +BOOL +DisplayVendorVidFormat ( + PVIDEO_FORMAT_VENDOR VendorVidFormatDesc + ) +{ + //@@DisplayVendorVidFormat -Vendor Video Format + OLECHAR szGUID[256]; + int i = 0; + + // Initialize the default Frame + g_chVendorFrameDefault = VendorVidFormatDesc->bDefaultFrameIndex; + + memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); + i = StringFromGUID2((REFGUID) &VendorVidFormatDesc->guidMajorFormat, (LPOLESTR) szGUID, 255); + i++; + + AppendTextBuffer("\r\n ===>Video Streaming Vendor Video Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", VendorVidFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VendorVidFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VendorVidFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", VendorVidFormatDesc->bFormatIndex); + AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", VendorVidFormatDesc->bNumFrameDescriptors); + AppendTextBuffer("guidMajorFormat: %S\r\n", szGUID); + i = StringFromGUID2((REFGUID) &VendorVidFormatDesc->guidSubFormat, (LPOLESTR) szGUID, 255); + i++; + AppendTextBuffer("guidSubFormat: %S\r\n", szGUID); + i = StringFromGUID2((REFGUID) &VendorVidFormatDesc->guidSpecifier, (LPOLESTR) szGUID, 255); + i++; + AppendTextBuffer("guidSpecifier: %S\r\n", szGUID); + AppendTextBuffer("bPayloadClass: 0x%02X\r\n", VendorVidFormatDesc->bPayloadClass); + AppendTextBuffer("bDefaultFrameIndex: 0x%02X\r\n", VendorVidFormatDesc->bDefaultFrameIndex); + AppendTextBuffer("bCopyProtect: 0x%02X", VendorVidFormatDesc->bCopyProtect); + if(gDoAnnotation) { + if(VendorVidFormatDesc->bCopyProtect) { AppendTextBuffer(" -> Duplication Restricted\r\n");} + else {AppendTextBuffer(" -> Duplication Unrestricted\r\n");}} + else {AppendTextBuffer("\r\n");} + + if (VendorVidFormatDesc->bLength != sizeof(VIDEO_FORMAT_VENDOR)) + { + //@@TestCase B28.1 (descript.c line 1297) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", + VendorVidFormatDesc->bLength, + sizeof(VIDEO_FORMAT_VENDOR)); + OOPS(); + } + + if (VendorVidFormatDesc->bFormatIndex == 0 ) + { + //@@TestCase B28.2 (descript.c line 1302) + //@@ERROR + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bFormatIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (VendorVidFormatDesc->bNumFrameDescriptors == 0 ) + { + //@@TestCase B28.3 (descript.c line 1307) + //@@ERROR + //@@Descriptor Field - bNumFrameDescriptors + //@@bNumFrameDescriptors is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bNumFrameDescriptors = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if(VendorVidFormatDesc->bPayloadClass > 1) + { + //@@TestCase B28.4 + //@@WARNING + //@@Descriptor Field - bPayloadClass + //@@bPayloadClass is using reserved space + AppendTextBuffer("*!*WARNING: bPayloadClass is incorrectly using reserved space\r\n"); + OOPS(); + } + else + { + if (gDoAnnotation) + { + if(VendorVidFormatDesc->bPayloadClass == 1) { AppendTextBuffer(" -> Using a Frame Based Payload\r\n");} + else { AppendTextBuffer(" -> Using a Stream Based Payload\r\n");} + } + else {AppendTextBuffer("\r\n");} + } + + if (VendorVidFormatDesc->bDefaultFrameIndex == 0 ) + { + //@@TestCase B28.5 (descript.c line 1312) + //@@ERROR + //@@Descriptor Field - bDefaultFrameIndex + //@@bDefaultFrameIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bDefaultFrameIndex = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (VendorVidFormatDesc->bDefaultFrameIndex == 0 || VendorVidFormatDesc->bDefaultFrameIndex > VendorVidFormatDesc->bNumFrameDescriptors) + { + //@@TestCase B28.6 + //@@WARNING + //@@Descriptor Field - bDefaultFrameIndex + //@@bDefaultFrameIndex is out of range + AppendTextBuffer("*!*WARNING: The value %d for the bDefaultFrameIndex is out of range this invalidates the descriptor\r\n*!* The proper range is 1 to %d)", + VendorVidFormatDesc->bDefaultFrameIndex, + VendorVidFormatDesc->bNumFrameDescriptors); + OOPS(); + } + + //@@TestCase B28.7 + //@@Not yet implemented - Priority 1 + //@@Descriptor Field - bCopyProtect + //@@Question - Are their reserved bits and should we validate that reserved bits are set to zero? + // AppendTextBuffer("bCopyProtect: 0x%02X", VendorVidFormatDesc->bCopyProtect); + + // Check that the correct number of Frame Descriptors and one Color Matching + // descriptor follow + CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) VendorVidFormatDesc, + VendorVidFormatDesc->bNumFrameDescriptors, VS_FRAME_VENDOR); + + // This descriptor is deprecated for UVC 1.1 +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); + } +#else + if (UVC11 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); + } +#endif + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVendorVidFrameType() +// +//***************************************************************************** + +BOOL +DisplayVendorVidFrameType ( + PVIDEO_FRAME_VENDOR VendorVidFrameDesc + ) +{ + //@@DisplayVendorVidFrameType -Vendor Video Frame + size_t bLength = 0; + bLength = SizeOfVideoFrameVendor(VendorVidFrameDesc); + + AppendTextBuffer("\r\n ===>Video Streaming Vendor Video Frame Type Descriptor<===\r\n"); + if (gDoAnnotation) + { + if(VendorVidFrameDesc->bFrameIndex == g_chVendorFrameDefault) + { + AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); + } + } + AppendTextBuffer("bLength: 0x%02X\r\n", VendorVidFrameDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VendorVidFrameDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VendorVidFrameDesc->bDescriptorSubtype); + AppendTextBuffer("bFrameIndex: 0x%02X\r\n", VendorVidFrameDesc->bFrameIndex); + + if (VendorVidFrameDesc->bLength != bLength) + { + //@@TestCase B29.1 (descript.c line 1352) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is less than required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + VendorVidFrameDesc->bLength, bLength); + OOPS(); + } + + if (VendorVidFrameDesc->bFrameIndex == 0 ) + { + //@@TestCase B29.2 (descript.c line 1357) + //@@ERROR + //@@Descriptor Field - bFrameIndex + //@@bFrameIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bFrameIndex = 0, this is a 1 based index\r\n"); + OOPS(); + } + + AppendTextBuffer("bmCapabilities: 0x%02X", VendorVidFrameDesc->bmCapabilities); + + if(VendorVidFrameDesc->bmCapabilities & 0x01){ + if(gDoAnnotation) { AppendTextBuffer(" -> Still Images are supported\r\n");} + else {AppendTextBuffer("\r\n");} } + else if (VendorVidFrameDesc->bmCapabilities & 0xFF) + { + //@@TestCase B29.3 + //@@WARNING + //@@Descriptor Field - bmCapabilities + //@@bmCapabilities has a bit using reserved areas that should be set to zero + AppendTextBuffer("\r\n*!*WARNING: bmCapabilities is using reserved areas.\r\n"); + OOPS(); } + else {AppendTextBuffer("\r\n");} + AppendTextBuffer("wWidth: 0x%04X = %d\r\n", VendorVidFrameDesc->wWidth, VendorVidFrameDesc->wWidth); + AppendTextBuffer("wHeight: 0x%04X = %d\r\n", VendorVidFrameDesc->wHeight, VendorVidFrameDesc->wHeight); + AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", VendorVidFrameDesc->dwMinBitRate); + AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", VendorVidFrameDesc->dwMaxBitRate); + AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", VendorVidFrameDesc->dwMaxVideoFrameBufferSize); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + VendorVidFrameDesc->dwDefaultFrameInterval, + ((double)VendorVidFrameDesc->dwDefaultFrameInterval)/10000.0, + (10000000.0/((double)VendorVidFrameDesc->dwDefaultFrameInterval)) + ); + AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", VendorVidFrameDesc->bFrameIntervalType); + + if (VendorVidFrameDesc->wWidth == 0 ) + { + //@@TestCase B29.4 (descript.c line 1362) + //@@ERROR + //@@Descriptor Field - wWidth + //@@wWidth is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: wWidth must be nonzero\r\n"); + OOPS(); + } + + if (VendorVidFrameDesc->wHeight == 0 ) + { + //@@TestCase B29.5 (descript.c line 1367) + //@@ERROR + //@@Descriptor Field - wHeight + //@@wHeight is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: wHeight must be nonzero\r\n"); + OOPS(); + } + + if (VendorVidFrameDesc->dwMinBitRate == 0 ) + { + //@@TestCase B29.6 (descript.c line 1372) + //@@ERROR + //@@Descriptor Field - dwMinBitRate + //@@dwMinBitRate is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMinBitRate must be nonzero\r\n"); + OOPS(); + } + + if (VendorVidFrameDesc->dwMaxBitRate == 0 ) + { + //@@TestCase B29.7 (descript.c line 1377) + //@@ERROR + //@@Descriptor Field - dwMaxBitRate + //@@dwMaxBitRate is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxBitRate must be nonzero\r\n"); + OOPS(); + } + + if(VendorVidFrameDesc->dwMinBitRate > VendorVidFrameDesc->dwMaxBitRate) + { + //@@TestCase B29.8 + //@@ERROR + //@@Descriptor Field - dwMinBitRate and dwMaxBitRate + //@@Verify that dwMaxBitRate is greater than dwMinBitRate + AppendTextBuffer("*!*ERROR: dwMinBitRate should be less than dwMaxBitRate\r\n"); + OOPS(); + } + else + { + if (VendorVidFrameDesc->bFrameIntervalType == 1 && + VendorVidFrameDesc->dwMinBitRate != VendorVidFrameDesc->dwMaxBitRate) + { + //@@TestCase B29.9 + //@@WARNING + //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate + //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 + AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate "\ + "should equal dwMaxBitRate\r\n"); + OOPS(); + } + } + + if (VendorVidFrameDesc->dwMaxVideoFrameBufferSize == 0 ) + { + //@@TestCase B29.10 (descript.c line 1382) + //@@WARNING + //@@Descriptor Field - dwMaxVideoFrameBufferSize + //@@dwMaxVideoFrameBufferSize is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*WARNING: dwMaxVideoFrameBufferSize must be nonzero\r\n"); + OOPS(); + } + if (VendorVidFrameDesc->dwDefaultFrameInterval == 0 ) + { + //@@TestCase B29.11 (descript.c line 1020) + //@@WARNING + //@@Descriptor Field - dwDefaultFrameInterval + //@@dwDefaultFrameInterval must be nonzero + AppendTextBuffer("*!*WARNING: dwDefaultFrameInterval must be nonzero\r\n"); + OOPS(); + } + + if (VendorVidFrameDesc->bFrameIntervalType == 0) + { + DisplayVendorVidContinuousFrameType(VendorVidFrameDesc); + } + else + { + DisplayVendorVidDiscreteFrameType(VendorVidFrameDesc); + } + // This descriptor is deprecated for UVC 1.1 +#ifdef H264_SUPPORT + if (UVC10 != g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); + } +#else + if (UVC11 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); + } +#endif + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVendorVidContinuousFrameType() +// +//***************************************************************************** + +BOOL +DisplayVendorVidContinuousFrameType( + PVIDEO_FRAME_VENDOR VContinuousDesc + ) +{ + //@@DisplayVendorVidContinuousFrameType -Vendor Video Continuous Frame + ULONG dwMinFrameInterval = VContinuousDesc->adwFrameInterval[0]; + ULONG dwMaxFrameInterval = VContinuousDesc->adwFrameInterval[1]; + ULONG dwFrameIntervalStep = VContinuousDesc->adwFrameInterval[2]; + + AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + + AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMinFrameInterval, + ((double)dwMinFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); + + AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMaxFrameInterval, + ((double)dwMaxFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); + AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); + + if (dwMinFrameInterval == 0 ) + { + //@@TestCase B30.2 (descript.c line 1388) + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval + //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (dwMaxFrameInterval == 0 ) + { + //@@TestCase B30.3 (descript.c line 1388) + //@@ERROR + //@@Descriptor Field - dwMaxFrameInterval + //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if(dwMinFrameInterval > dwMaxFrameInterval) + { + //@@TestCase B30.4 (descript.c line 1405) + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval + AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); + OOPS(); + } + else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) + { + //@@TestCase B30.5 + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) + { + //@@TestCase B30.6 + //@@CAUTION + //@@Descriptor Field - dwFrameIntervalStep + //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero + AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) + { + //@@TestCase B30.7 (descript.c line 1414) + //@@ERROR + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep + AppendTextBuffer("*!*ERROR: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); + OOPS(); + } + + if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) + { + //@@TestCase B30.8 (descript.c line 1394) + //@@ERROR + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval + AppendTextBuffer("*!*ERROR: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between \r\n dwMinFrameInterval and dwMaxFrameInterval\r\n"); + OOPS(); + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVendorVidDiscreteFrameType() +// +//***************************************************************************** + +BOOL +DisplayVendorVidDiscreteFrameType( + PVIDEO_FRAME_VENDOR VDiscreteDesc + ) +{ + //@@DisplayVendorVidDiscreteFrameType -Vendor Video Discrete Frame + UINT iNdex = 1; + UINT iCurFrame = 0; + ULONG * ulFrameInterval = NULL; + + AppendTextBuffer("===>Additional Discrete Frame TypeData\r\n"); + + // There are (VDiscreteDesc->bFrameIntervalType) dwFrameIntervals + for (; iNdex <= VDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) + { + ulFrameInterval = &VDiscreteDesc->adwFrameInterval[iCurFrame]; + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + iNdex, *ulFrameInterval, + ((double)*ulFrameInterval)/10000.0, + (10000000.0/((double)*ulFrameInterval)) + ); + if (0 == *ulFrameInterval) + { + //@@TestCase B31.1 (descript.c line 1061) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[x] must be non-zero + AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); + OOPS(); + } + if ((iNdex > 1)&&(*ulFrameInterval <= VDiscreteDesc->adwFrameInterval[iCurFrame - 1])) + { + //@@TestCase B31.2 (descript.c line 1067) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] + AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ + "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); + OOPS(); + } + } + + return TRUE; +} + +//***************************************************************************** +// +// DisplayFramePayloadFormat() +// +//***************************************************************************** + +BOOL +DisplayFramePayloadFormat ( + PVIDEO_FORMAT_FRAME FramePayloadFormatDesc + ) +{ + //@@DisplayFramePayloadFormat - FrameBased Payload Format + PCHAR pStr = NULL; + OLECHAR szGUID[256]; + int i = 0; + + // Initialize the default Frame + g_chFrameBasedFrameDefault = FramePayloadFormatDesc->bDefaultFrameIndex; + + memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); + i = StringFromGUID2((REFGUID) &FramePayloadFormatDesc->guidFormat, (LPOLESTR) szGUID, 255); + i++; + + AppendTextBuffer("\r\n ===>Video Streaming Frame Based Payload Format Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X\r\n", FramePayloadFormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", FramePayloadFormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", FramePayloadFormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X\r\n", FramePayloadFormatDesc->bFormatIndex); + AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", FramePayloadFormatDesc->bNumFrameDescriptors); + AppendTextBuffer("guidFormat: %S", szGUID); + + pStr = VidFormatGUIDCodeToName((REFGUID) &FramePayloadFormatDesc->guidFormat); + if ( pStr ) + { + if ( gDoAnnotation ) + { + AppendTextBuffer(" = %s Format", pStr); + } + } + AppendTextBuffer("\r\n"); + AppendTextBuffer("bBitsPerPixel: 0x%02X\r\n", FramePayloadFormatDesc->bBitsPerPixel); + AppendTextBuffer("bDefaultFrameIndex: 0x%02X\r\n", FramePayloadFormatDesc->bDefaultFrameIndex); + + if (FramePayloadFormatDesc->bLength != sizeof(VIDEO_FORMAT_FRAME)) + { + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required + //@@length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + FramePayloadFormatDesc->bLength, + sizeof(VIDEO_FORMAT_FRAME)); + OOPS(); + } + + if (FramePayloadFormatDesc->bFormatIndex == 0 ) + { + //@@ERROR + //@@Descriptor Field - bFormatIndex + //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bFormatIndex = 0, this is a 1 based index\r\n"); + OOPS(); + } + + if (FramePayloadFormatDesc->bNumFrameDescriptors == 0 ) + { + //@@ERROR + //@@Descriptor Field - bNumFrameDescriptors + //@@bNumFrameDescriptors is set to zero which is not in accordance with the + //@@USB Video Device Specification + AppendTextBuffer("*!*ERROR: bNumFrameDescriptors = 0, must have at least 1 Frame descriptor\r\n"); + OOPS(); + } + + if(!(pStr)) + { + //@@WARNING + //@@Descriptor Field - guidFormat + //@@guidFormat is set to unknown or undefined format + AppendTextBuffer("\r\n*!*WARNING: guidFormat is an unknown format\r\n"); + OOPS(); + } + + if (FramePayloadFormatDesc->bBitsPerPixel == 0 ) + { + //@@ERROR + //@@Descriptor Field - bBitsPerPixel + //@@bBitsPerPixel is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bBitsPerPixel = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (FramePayloadFormatDesc->bDefaultFrameIndex == 0 || FramePayloadFormatDesc->bDefaultFrameIndex > + FramePayloadFormatDesc->bNumFrameDescriptors) + { + //@@ERROR + //@@Descriptor Field - bDefaultFrameIndex + //@@The value for bDefaultFrameIndex is not greater than 0 or less than or equal to bNumFrameDescriptors + AppendTextBuffer("*!*ERROR: The value %d for the bDefaultFrameIndex is out of range, this invalidates the descriptor\r\n*!*The proper range is 1 to %d)", + FramePayloadFormatDesc->bDefaultFrameIndex, + FramePayloadFormatDesc->bNumFrameDescriptors); + OOPS(); + } + + AppendTextBuffer("bAspectRatioX: 0x%02X\r\n", + FramePayloadFormatDesc->bAspectRatioX); + AppendTextBuffer("bAspectRatioY: 0x%02X", + FramePayloadFormatDesc->bAspectRatioY); + + if (((FramePayloadFormatDesc->bmInterlaceFlags & 0x01) && + (FramePayloadFormatDesc->bAspectRatioY != 0 && + FramePayloadFormatDesc->bAspectRatioX != 0))) + { + if(gDoAnnotation) + { + AppendTextBuffer(" -> Aspect Ratio is set for a %d:%d display", + (FramePayloadFormatDesc->bAspectRatioX),(FramePayloadFormatDesc->bAspectRatioY)); + } + else + { + if (FramePayloadFormatDesc->bAspectRatioY != 0 || FramePayloadFormatDesc->bAspectRatioX != 0) + { + //@@ERROR + //@@Descriptor Field - bAspectRatioX, bAspectRatioY + //@@Verify that that bAspectRatioX and bAspectRatioY are set to zero + //@@ if stream is non-interlaced + AppendTextBuffer("\r\n*!*ERROR: Both bAspectRatioX and bAspectRatioY "\ + "must equal 0 if stream is non-interlaced"); + OOPS(); + } + } + } + AppendTextBuffer("\r\nbmInterlaceFlags: 0x%02X\r\n", + FramePayloadFormatDesc->bmInterlaceFlags); + + if (gDoAnnotation) + { + AppendTextBuffer(" D0 = 0x%02X Interlaced stream or variable: %s\r\n", + (FramePayloadFormatDesc->bmInterlaceFlags & 1), + (FramePayloadFormatDesc->bmInterlaceFlags & 1) ? "Yes" : "No"); + AppendTextBuffer(" D1 = 0x%02X Fields per frame: %s\r\n", + ((FramePayloadFormatDesc->bmInterlaceFlags >> 1) & 1), + ((FramePayloadFormatDesc->bmInterlaceFlags >> 1) & 1) ? "1 field" : "2 fields"); + AppendTextBuffer(" D2 = 0x%02X Field 1 first: %s\r\n", + ((FramePayloadFormatDesc->bmInterlaceFlags >> 2) & 1), + ((FramePayloadFormatDesc->bmInterlaceFlags >> 2) & 1) ? "Yes" : "No"); + //@@Descriptor Field - bmInterlaceFlags + //@@Validate that reserved bits (D3) are set to zero. + AppendTextBuffer(" D3 = 0x%02X Reserved%s\r\n", + ((FramePayloadFormatDesc->bmInterlaceFlags >> 3) & 1), + ((FramePayloadFormatDesc->bmInterlaceFlags >> 3) & 1) ? + "\r\n*!*ERROR: Reserved to 0" : "" ); + AppendTextBuffer(" D4..5 = 0x%02X Field patterns ->", + ((FramePayloadFormatDesc->bmInterlaceFlags >> 4) & 3)); + switch(FramePayloadFormatDesc->bmInterlaceFlags & 0x30) + { + case 0x00: + AppendTextBuffer(" Field 1 only"); + break; + case 0x10: + AppendTextBuffer(" Field 2 only"); + break; + case 0x20: + AppendTextBuffer(" Regular Pattern of fields 1 and 2"); + break; + case 0x30: + AppendTextBuffer(" Random Pattern of fields 1 and 2"); + break; + } + AppendTextBuffer("\r\n D6..7 = 0x%02X Display Mode ->", + ((FramePayloadFormatDesc->bmInterlaceFlags >> 6) & 3)); + + switch(FramePayloadFormatDesc->bmInterlaceFlags & 0xC0) + { + case 0x00: + AppendTextBuffer(" Bob only"); + break; + case 0x40: + AppendTextBuffer(" Weave only"); + break; + case 0x80: + AppendTextBuffer(" Bob or weave"); + break; + case 0xC0: + //@@Descriptor Field - bmInterlaceFlags + //@@Question - Should we validate that reserved bits are set to zero? + AppendTextBuffer(" Reserved"); + break; + } + } + + //@@Descriptor Field - bCopyProtect + //@@Question - Are their reserved bits and should we validate that + //@@ reserved bits are set to zero? + AppendTextBuffer("\r\nbCopyProtect: 0x%02X", + FramePayloadFormatDesc->bCopyProtect); + if (gDoAnnotation) + { + if (FramePayloadFormatDesc->bCopyProtect) + AppendTextBuffer(" -> Duplication Restricted"); + else + AppendTextBuffer(" -> Duplication Unrestricted"); + } + + //@@Descriptor Field - bVariableSize + AppendTextBuffer("\r\nbVariableSize: 0x%02X", + FramePayloadFormatDesc->bVariableSize); + if (gDoAnnotation) + { + if (FramePayloadFormatDesc->bVariableSize) + AppendTextBuffer(" -> Variable Size"); + else + AppendTextBuffer(" -> Fixed Size"); + } + AppendTextBuffer("\r\n"); + + // Check that the correct number of Frame Descriptors and one Color Matching + // descriptor follow + CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) FramePayloadFormatDesc, + FramePayloadFormatDesc->bNumFrameDescriptors, VS_FRAME_FRAME_BASED); + + // This descriptor is new for UVC 1.1 + if (UVC10 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.0 devices\r\n"); + } + return TRUE; + } + + +//***************************************************************************** +// +// DisplayFramePayloadFrame() +// +//***************************************************************************** + +BOOL +DisplayFramePayloadFrame ( + PVIDEO_FRAME_FRAME FramePayloadFrameDesc + ) +{ + size_t bLength = 0; + bLength = SizeOfVideoFrameFrame(FramePayloadFrameDesc); + + //@@DisplayFramePayloadFrame -Frame Based Payload Frame + + AppendTextBuffer("\r\n ===>Video Streaming Frame Based Payload Frame Type Descriptor<===\r\n"); + if (gDoAnnotation) + { + if(FramePayloadFrameDesc->bFrameIndex == g_chFrameBasedFrameDefault) + { + AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); + } + } + AppendTextBuffer("bLength: 0x%02X\r\n", FramePayloadFrameDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", FramePayloadFrameDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", FramePayloadFrameDesc->bDescriptorSubtype); + AppendTextBuffer("bFrameIndex: 0x%02X\r\n", FramePayloadFrameDesc->bFrameIndex); + AppendTextBuffer("bmCapabilities: 0x%02X\r\n", FramePayloadFrameDesc->bmCapabilities); + AppendTextBuffer("wWidth: 0x%04X = %d\r\n", FramePayloadFrameDesc->wWidth, FramePayloadFrameDesc->wWidth); + AppendTextBuffer("wHeight: 0x%04X = %d\r\n", FramePayloadFrameDesc->wHeight, FramePayloadFrameDesc->wHeight); + AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", FramePayloadFrameDesc->dwMinBitRate); + AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", FramePayloadFrameDesc->dwMaxBitRate); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + FramePayloadFrameDesc->dwDefaultFrameInterval, + ((double)FramePayloadFrameDesc->dwDefaultFrameInterval)/10000.0, + (10000000.0/((double)FramePayloadFrameDesc->dwDefaultFrameInterval)) + ); + AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", FramePayloadFrameDesc->bFrameIntervalType); + + if (FramePayloadFrameDesc->bLength != bLength) + { + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required + //@@length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", + FramePayloadFrameDesc->bLength, bLength); + OOPS(); + } + + if (FramePayloadFrameDesc->bFrameIndex == 0 ) + { + //@@ERROR + //@@Descriptor Field - bFrameIndex + //@@bFrameIndex must be nonzero + AppendTextBuffer("*!*ERROR: bFrameIndex = 0, this is a 1 based index\r\n"); + OOPS(); + } + + //@@Descriptor Field - bmCapabilities + //@@Question: Should we try to verify that bmCapabilities is valid? + // AppendTextBuffer("bmCapabilities: 0x%02X\r\n", UnCompFrameDesc->bmCapabilities); + + if (FramePayloadFrameDesc->wWidth == 0 ) + { + //@@ERROR + //@@Descriptor Field - wWidth + //@@wWidth must be nonzero + AppendTextBuffer("*!*ERROR: wWidth must be nonzero\r\n"); + OOPS(); + } + + if (FramePayloadFrameDesc->wHeight == 0 ) + { + //@@ERROR + //@@Descriptor Field - wHeight + //@@wHeight must be nonzero + AppendTextBuffer("*!*ERROR: wHeight must be nonzero\r\n"); + OOPS(); + } + + if (FramePayloadFrameDesc->dwMinBitRate == 0 ) + { + //@@ERROR + //@@Descriptor Field - dwMinBitRate + //@@dwMinBitRate must be nonzero + AppendTextBuffer("*!*ERROR: dwMinBitRate must be nonzero\r\n"); + OOPS(); + } + + if (FramePayloadFrameDesc->dwMaxBitRate == 0 ) + { + //@@ERROR + //@@Descriptor Field - dwMaxBitRate + //@@dwMaxBitRate must be nonzero + AppendTextBuffer("*!*ERROR: dwMaxBitRate must be nonzero\r\n"); + OOPS(); + } + + if(FramePayloadFrameDesc->dwMinBitRate > FramePayloadFrameDesc->dwMaxBitRate) + { + //@@ERROR + //@@Descriptor Field - dwMinBitRate and dwMaxBitRate + //@@Verify that dwMaxBitRate is greater than dwMinBitRate + AppendTextBuffer("*!*ERROR: dwMinBitRate should be less than dwMaxBitRate\r\n"); + OOPS(); + } + else + { + if (FramePayloadFrameDesc->bFrameIntervalType == 1 && + FramePayloadFrameDesc->dwMinBitRate != FramePayloadFrameDesc->dwMaxBitRate) + { + //@@WARNING + //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate + //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 + AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate "\ + "should equal dwMaxBitRate\r\n"); + OOPS(); + } + } + + if (FramePayloadFrameDesc->dwDefaultFrameInterval == 0 ) + { + //@@TestCase B16.11 (descript.c line 1020) + //@@WARNING + //@@Descriptor Field - dwDefaultFrameInterval + //@@dwDefaultFrameInterval must be nonzero + AppendTextBuffer("*!*WARNING: dwDefaultFrameInterval must be nonzero\r\n"); + OOPS(); + } + + if (0 == FramePayloadFrameDesc->bFrameIntervalType) + { + DisplayFramePayloadContinuousFrameType(FramePayloadFrameDesc); + } + else + { + DisplayFramePayloadDiscreteFrameType(FramePayloadFrameDesc); + } + // This descriptor is new for UVC 1.1 + if (UVC10 == g_chUVCversion) + { + AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.0 devices\r\n"); + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayFramePayloadContinuousFrameType() +// +//***************************************************************************** + +BOOL +DisplayFramePayloadContinuousFrameType( + PVIDEO_FRAME_FRAME FContinuousDesc + ) +{ + //@@DisplayFramePayloadContinuousFrameType -Frame Payload Continuous Frame + ULONG dwMinFrameInterval = FContinuousDesc->adwFrameInterval[0]; + ULONG dwMaxFrameInterval = FContinuousDesc->adwFrameInterval[1]; + ULONG dwFrameIntervalStep = FContinuousDesc->adwFrameInterval[2]; + + AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + + AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMinFrameInterval, + ((double)dwMinFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); + + AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", + dwMaxFrameInterval, + ((double)dwMaxFrameInterval)/10000.0, + (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); + + AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); + + if (dwMinFrameInterval == 0 ) + { + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval + //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if (dwMaxFrameInterval == 0 ) + { + //@@ERROR + //@@Descriptor Field - dwMaxFrameInterval + //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification + AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); + OOPS(); + } + + if(dwMinFrameInterval > dwMaxFrameInterval) + { + //@@ERROR + //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval + AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); + OOPS(); + } + else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) + { + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) + { + //@@CAUTION + //@@Descriptor Field - dwFrameIntervalStep + //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero + AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); + OOPS(); + } + else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) + { + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep + AppendTextBuffer("*!*WARNING: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); + OOPS(); + } + + if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) + { + //@@WARNING + //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval + //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval + AppendTextBuffer("*!*WARNING: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between dwMinFrameInterval and dwMaxFrameInterval\r\n"); + OOPS(); + } + + return TRUE; +} + +//***************************************************************************** +// +// DisplayFramePayloadDiscreteFrameType() +// +//***************************************************************************** + +BOOL +DisplayFramePayloadDiscreteFrameType( + PVIDEO_FRAME_FRAME FDiscreteDesc + ) +{ + //@@DisplayFramePayloadDiscreteFrameType -Frame Based Payload Discrete Frame + UINT iNdex = 1; + UINT iCurFrame = 0; + ULONG * ulFrameInterval = NULL; + + AppendTextBuffer("===>Additional Discrete Frame Type Data\r\n"); + + // There are (UDiscreteDesc->bFrameIntervalType) dwFrameIntervals (1 based index) + for (; iNdex <= FDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) + { + ulFrameInterval = &FDiscreteDesc->adwFrameInterval[iCurFrame]; + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", + iNdex, *ulFrameInterval, + ((double)*ulFrameInterval)/10000.0, + (10000000.0/((double)*ulFrameInterval)) + ); + if (0 == *ulFrameInterval) + { + //@@TestCase B18.1 (descript.c line 1061) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[x] must be non-zero + AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); + OOPS(); + } + if ((iNdex > 1)&&(*ulFrameInterval <= FDiscreteDesc->adwFrameInterval[iCurFrame - 1])) + { + //@@TestCase B18.2 (descript.c line 1067) + //@@ERROR + //@@Descriptor Field - dwFrameInterval[x] + //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] + AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ + "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); + OOPS(); + } + } + return TRUE; +} + +//***************************************************************************** +// +// DisplayVSEndpoint() +// +//***************************************************************************** + +BOOL +DisplayVSEndpoint ( + PVIDEO_CS_INTERRUPT VidEndpointDesc + ) +{ + //@@DisplayVSEndpoint - Video Streaming Endpoint + AppendTextBuffer("\r\n ===>Class-specific VC Interrupt Endpoint Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X \r\n", VidEndpointDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidEndpointDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidEndpointDesc->bDescriptorSubtype); + AppendTextBuffer("wMaxTransferSize: 0x%04X", VidEndpointDesc->wMaxTransferSize); + if(gDoAnnotation) { + AppendTextBuffer(" = (%d) Bytes\r\n", VidEndpointDesc->wMaxTransferSize);} + else {AppendTextBuffer("\r\n");} + + if (VidEndpointDesc->bLength != sizeof(VIDEO_CS_INTERRUPT)) + { + //@@TestCase B32.1 (descript.c line 1616) + //@@ERROR + //@@Descriptor Field - bLength + //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification + AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", + VidEndpointDesc->bLength, + sizeof(VIDEO_CS_INTERRUPT)); + OOPS(); + } + + return TRUE; +} + +//***************************************************************************** +// +// VDisplayBytes() +// +//***************************************************************************** + +VOID +VDisplayBytes ( + PUCHAR Data, + USHORT Len + ) +{ + USHORT i = 0; + + for (i = 0; i < Len; i++) + { + AppendTextBuffer("0x%02X ", Data[i]); + + if (i % 16 == 15) + { + AppendTextBuffer("\r\n"); + } + } + + if (i % 16 != 0) + { + AppendTextBuffer("\r\n"); + } +} + +//***************************************************************************** +// +// VidFormatGUIDCodeToName() +// +//***************************************************************************** + + +PCHAR +VidFormatGUIDCodeToName ( + REFGUID VidFormatGUIDCode + ) +{ + // GUID pYUY2 = YUY2_Format; + // GUID pNV12 = NV12_Format; + if (IsEqualGUID(VidFormatGUIDCode, (REFGUID) &YUY2_Format)) + { + return (PCHAR) &"YUY2"; + } + if (IsEqualGUID(VidFormatGUIDCode, (REFGUID) &NV12_Format)) + { + return (PCHAR) &"NV12"; + } +#ifdef H264_SUPPORT + // GUID pH264 = H264_Format; + if (IsEqualGUID(VidFormatGUIDCode, (REFGUID) &H264_Format)) + { + return (PCHAR) &"H.264"; + } +#endif + + return FALSE; +} + +/***************************************************************************** + +GetVCInterfaceSize() + +*****************************************************************************/ + +UINT +GetVCInterfaceSize ( + PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc + ) +{ + PUSB_COMMON_DESCRIPTOR commonDesc = (PUSB_COMMON_DESCRIPTOR) VCInterfaceDesc; + PUCHAR descEnd = (PUCHAR) VCInterfaceDesc + VCInterfaceDesc->wTotalLength; + UINT uCount = 0; + + // return this interface's sum of descriptor lengths + // starting from this header until (and not including) the first endpoint + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + if (commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) + break; + uCount += commonDesc->bLength; + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + return (uCount); +} + +/***************************************************************************** + +CheckForColorMatchingDesc () + +Given starting address of format descriptor; +number of frame descriptors; +subtype of frame to look for; + +1) walk through each descriptor += if desc is frame of given subtype, update counter += if desc is still frame, update counter += if desc is color matching descriptor, update counter +! if frame is something else, break (all these frames should be consecutive) +! if next frame is beyond ending address of configuration, break + +PASS +frame count == numframes passed in +color match == 1 +still frames are handled in the video stream input header and the frame displays + +*****************************************************************************/ + +UINT +CheckForColorMatchingDesc ( + PVIDEO_SPECIFIC pFormatDesc, + UCHAR bNumFrameDescriptors, + UCHAR bDescriptorSubtype + ) +{ + UINT uFrameCount = 0; + UINT uStillFrameCount = 0; + UINT uColorCount = 0; + + // DONE if the descriptor address is beyond the configuration range + for ( ; ValidateDescAddress ((PUSB_COMMON_DESCRIPTOR) pFormatDesc); ) + { + // DONE if it's not an interface desc + if (CS_INTERFACE != pFormatDesc->bDescriptorType) + { + break; + } + switch (pFormatDesc->bDescriptorSubtype) + { + case VS_STILL_IMAGE_FRAME: + uStillFrameCount++; + break; + case VS_COLORFORMAT: + uColorCount++; + break; + default: + if (bDescriptorSubtype == pFormatDesc->bDescriptorSubtype) + { + uFrameCount++; + } + break; + } + pFormatDesc = (PVIDEO_SPECIFIC) ((PUCHAR) pFormatDesc + pFormatDesc->bLength); + } + if (uFrameCount != bNumFrameDescriptors) + { + AppendTextBuffer("*!*ERROR: Found %d frame descriptors (should be %d)\r\n", + uFrameCount, bNumFrameDescriptors); + } + // We already check Still Frames in the Video Info Header and Still Frames displays + if (0 == uColorCount) + { + AppendTextBuffer("*!*ERROR: no Color Matching Descriptor for this format\r\n"); + } + return (uColorCount); +} + +/***************************************************************************** + +GetVSInterfaceSize() + +*****************************************************************************/ + +UINT +GetVSInterfaceSize ( + PUSB_COMMON_DESCRIPTOR VidInHeaderDesc, + USHORT wTotalLength + ) +{ + PUSB_COMMON_DESCRIPTOR commonDesc = (PUSB_COMMON_DESCRIPTOR) VidInHeaderDesc; + PUCHAR descEnd = (PUCHAR) VidInHeaderDesc + wTotalLength; + UINT uCount = 0; + + // return this interface's sum of descriptor lengths + // starting from this header until (and not including) the first endpoint + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + if (commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) + break; + uCount += commonDesc->bLength; + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + return (uCount); +} + +/***************************************************************************** + +ValidateTerminalID() + +*****************************************************************************/ + +BOOL +ValidateTerminalID( + UINT uTerminalID + ) +{ + UNREFERENCED_PARAMETER(uTerminalID); + return (TRUE); +} diff --git a/tests/projects/windows/winsdk/usbview/enum.c b/tests/projects/windows/winsdk/usbview/enum.c new file mode 100644 index 000000000..314a08806 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/enum.c @@ -0,0 +1,3366 @@ +/*++ + +Copyright (c) 1997-2011 Microsoft Corporation + +Module Name: + + ENUM.C + +Abstract: + + This source file contains the routines which enumerate the USB bus + and populate the TreeView control. + + The enumeration process goes like this: + + (1) Enumerate Host Controllers and Root Hubs + EnumerateHostControllers() + EnumerateHostController() + Host controllers currently have symbolic link names of the form HCDx, + where x starts at 0. Use CreateFile() to open each host controller + symbolic link. Create a node in the TreeView to represent each host + controller. + + GetRootHubName() + After a host controller has been opened, send the host controller an + IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of + the root hub that is part of the host controller. + + (2) Enumerate Hubs (Root Hubs and External Hubs) + EnumerateHub() + Given the name of a hub, use CreateFile() to map the hub. Send the + hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the + hub, such as the number of downstream ports. Create a node in the + TreeView to represent each hub. + + (3) Enumerate Downstream Ports + EnumerateHubPorts() + Given an handle to an open hub and the number of downstream ports on + the hub, send the hub an IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX + request for each downstream port of the hub to get info about the + device (if any) attached to each port. If there is a device attached + to a port, send the hub an IOCTL_USB_GET_NODE_CONNECTION_NAME request + to get the symbolic link name of the hub attached to the downstream + port. If there is a hub attached to the downstream port, recurse to + step (2). + + GetAllStringDescriptors() + GetConfigDescriptor() + Create a node in the TreeView to represent each hub port + and attached device. + + +Environment: + + user mode + +Revision History: + + 04-25-97 : created + +--*/ + +//***************************************************************************** +// I N C L U D E S +//***************************************************************************** + +#include "uvcview.h" + +//***************************************************************************** +// D E F I N E S +//***************************************************************************** + +#define NUM_STRING_DESC_TO_GET 32 + +//***************************************************************************** +// L O C A L F U N C T I O N P R O T O T Y P E S +//***************************************************************************** + +VOID +EnumerateHostControllers ( + HTREEITEM hTreeParent, + ULONG *DevicesConnected +); + +VOID +EnumerateHostController ( + HTREEITEM hTreeParent, + HANDLE hHCDev, + _Inout_ PCHAR leafName, + _In_ HANDLE deviceInfo, + _In_ PSP_DEVINFO_DATA deviceInfoData +); + +VOID +EnumerateHub ( + HTREEITEM hTreeParent, + _In_reads_(cbHubName) PCHAR HubName, + _In_ size_t cbHubName, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2, + _In_opt_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, + _In_opt_ PUSB_DESCRIPTOR_REQUEST ConfigDesc, + _In_opt_ PUSB_DESCRIPTOR_REQUEST BosDesc, + _In_opt_ PSTRING_DESCRIPTOR_NODE StringDescs, + _In_opt_ PUSB_DEVICE_PNP_STRINGS DevProps +); + +VOID +EnumerateHubPorts ( + HTREEITEM hTreeParent, + HANDLE hHubDevice, + ULONG NumPorts +); + +PCHAR GetRootHubName ( + HANDLE HostController +); + +PCHAR GetExternalHubName ( + HANDLE Hub, + ULONG ConnectionIndex +); + +PCHAR GetHCDDriverKeyName ( + HANDLE HCD +); + +PCHAR GetDriverKeyName ( + HANDLE Hub, + ULONG ConnectionIndex +); + +PUSB_DESCRIPTOR_REQUEST +GetConfigDescriptor ( + HANDLE hHubDevice, + ULONG ConnectionIndex, + UCHAR DescriptorIndex + ); + +PUSB_DESCRIPTOR_REQUEST +GetBOSDescriptor ( + HANDLE hHubDevice, + ULONG ConnectionIndex + ); + +DWORD +GetHostControllerPowerMap( + HANDLE hHCDev, + PUSBHOSTCONTROLLERINFO hcInfo); + +DWORD +GetHostControllerInfo( + HANDLE hHCDev, + PUSBHOSTCONTROLLERINFO hcInfo); + +PCHAR WideStrToMultiStr ( + _In_reads_bytes_(cbWideStr) PWCHAR WideStr, + _In_ size_t cbWideStr + ); + +BOOL +AreThereStringDescriptors ( + PUSB_DEVICE_DESCRIPTOR DeviceDesc, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc +); + +PSTRING_DESCRIPTOR_NODE +GetAllStringDescriptors ( + HANDLE hHubDevice, + ULONG ConnectionIndex, + PUSB_DEVICE_DESCRIPTOR DeviceDesc, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc +); + +PSTRING_DESCRIPTOR_NODE +GetStringDescriptor ( + HANDLE hHubDevice, + ULONG ConnectionIndex, + UCHAR DescriptorIndex, + USHORT LanguageID +); + +HRESULT +GetStringDescriptors ( + _In_ HANDLE hHubDevice, + _In_ ULONG ConnectionIndex, + _In_ UCHAR DescriptorIndex, + _In_ ULONG NumLanguageIDs, + _In_reads_(NumLanguageIDs) USHORT *LanguageIDs, + _In_ PSTRING_DESCRIPTOR_NODE StringDescNodeHead +); + +void +EnumerateAllDevices(); + + +void +EnumerateAllDevicesWithGuid( + PDEVICE_GUID_LIST DeviceList, + LPGUID Guid + ); + +void +FreeDeviceInfoNode( + _In_ PDEVICE_INFO_NODE *ppNode + ); + +PDEVICE_INFO_NODE +FindMatchingDeviceNodeForDriverName( + _In_ PSTR DriverKeyName, + _In_ BOOLEAN IsHub + ); + + +//***************************************************************************** +// G L O B A L S +//***************************************************************************** + +// List of enumerated host controllers. +// +LIST_ENTRY EnumeratedHCListHead = +{ + &EnumeratedHCListHead, + &EnumeratedHCListHead +}; + +DEVICE_GUID_LIST gHubList; +DEVICE_GUID_LIST gDeviceList; + + +//***************************************************************************** +// G L O B A L S P R I V A T E T O T H I S F I L E +//***************************************************************************** + +PCHAR ConnectionStatuses[] = +{ + "", // 0 - NoDeviceConnected + "", // 1 - DeviceConnected + "FailedEnumeration", // 2 - DeviceFailedEnumeration + "GeneralFailure", // 3 - DeviceGeneralFailure + "Overcurrent", // 4 - DeviceCausedOvercurrent + "NotEnoughPower", // 5 - DeviceNotEnoughPower + "NotEnoughBandwidth", // 6 - DeviceNotEnoughBandwidth + "HubNestedTooDeeply", // 7 - DeviceHubNestedTooDeeply + "InLegacyHub", // 8 - DeviceInLegacyHub + "Enumerating", // 9 - DeviceEnumerating + "Reset" // 10 - DeviceReset +}; + +ULONG TotalDevicesConnected; + + +//***************************************************************************** +// +// EnumerateHostControllers() +// +// hTreeParent - Handle of the TreeView item under which host controllers +// should be added. +// +//***************************************************************************** + +VOID +EnumerateHostControllers ( + HTREEITEM hTreeParent, + ULONG *DevicesConnected +) +{ + HANDLE hHCDev = NULL; + HDEVINFO deviceInfo = NULL; + SP_DEVINFO_DATA deviceInfoData; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData = NULL; + ULONG index = 0; + ULONG requiredLength = 0; + BOOL success; + + TotalDevicesConnected = 0; + TotalHubs = 0; + + EnumerateAllDevices(); + + // Iterate over host controllers using the new GUID based interface + // + deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER, + NULL, + NULL, + (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); + + deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + for (index=0; + SetupDiEnumDeviceInfo(deviceInfo, + index, + &deviceInfoData); + index++) + { + deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + success = SetupDiEnumDeviceInterfaces(deviceInfo, + 0, + (LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER, + index, + &deviceInterfaceData); + + if (!success) + { + OOPS(); + break; + } + + success = SetupDiGetDeviceInterfaceDetail(deviceInfo, + &deviceInterfaceData, + NULL, + 0, + &requiredLength, + NULL); + + if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + OOPS(); + break; + } + + deviceDetailData = ALLOC(requiredLength); + if (deviceDetailData == NULL) + { + OOPS(); + break; + } + + deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + success = SetupDiGetDeviceInterfaceDetail(deviceInfo, + &deviceInterfaceData, + deviceDetailData, + requiredLength, + &requiredLength, + NULL); + + if (!success) + { + OOPS(); + break; + } + + hHCDev = CreateFile(deviceDetailData->DevicePath, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + // If the handle is valid, then we've successfully opened a Host + // Controller. Display some info about the Host Controller itself, + // then enumerate the Root Hub attached to the Host Controller. + // + if (hHCDev != INVALID_HANDLE_VALUE) + { + EnumerateHostController(hTreeParent, + hHCDev, + deviceDetailData->DevicePath, + deviceInfo, + &deviceInfoData); + + CloseHandle(hHCDev); + } + + FREE(deviceDetailData); + } + + SetupDiDestroyDeviceInfoList(deviceInfo); + + *DevicesConnected = TotalDevicesConnected; + + return; +} + +//***************************************************************************** +// +// EnumerateHostController() +// +// hTreeParent - Handle of the TreeView item under which host controllers +// should be added. +// +//***************************************************************************** + +VOID +EnumerateHostController ( + HTREEITEM hTreeParent, + HANDLE hHCDev, _Inout_ PCHAR leafName, + _In_ HANDLE deviceInfo, + _In_ PSP_DEVINFO_DATA deviceInfoData +) +{ + PCHAR driverKeyName = NULL; + HTREEITEM hHCItem = NULL; + PCHAR rootHubName = NULL; + PLIST_ENTRY listEntry = NULL; + PUSBHOSTCONTROLLERINFO hcInfo = NULL; + PUSBHOSTCONTROLLERINFO hcInfoInList = NULL; + DWORD dwSuccess; + BOOL success = FALSE; + ULONG deviceAndFunction = 0; + PUSB_DEVICE_PNP_STRINGS DevProps = NULL; + + + // Allocate a structure to hold information about this host controller. + // + hcInfo = (PUSBHOSTCONTROLLERINFO)ALLOC(sizeof(USBHOSTCONTROLLERINFO)); + + // just return if could not alloc memory + if (NULL == hcInfo) + return; + + hcInfo->DeviceInfoType = HostControllerInfo; + + // Obtain the driver key name for this host controller. + // + driverKeyName = GetHCDDriverKeyName(hHCDev); + + if (NULL == driverKeyName) + { + // Failure obtaining driver key name. + OOPS(); + FREE(hcInfo); + return; + } + + // Don't enumerate this host controller again if it already + // on the list of enumerated host controllers. + // + listEntry = EnumeratedHCListHead.Flink; + + while (listEntry != &EnumeratedHCListHead) + { + hcInfoInList = CONTAINING_RECORD(listEntry, + USBHOSTCONTROLLERINFO, + ListEntry); + + if (strcmp(driverKeyName, hcInfoInList->DriverKey) == 0) + { + // Already on the list, exit + // + FREE(driverKeyName); + FREE(hcInfo); + return; + } + + listEntry = listEntry->Flink; + } + + // Obtain host controller device properties + { + size_t cbDriverName = 0; + HRESULT hr = S_OK; + + hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName); + if (SUCCEEDED(hr)) + { + DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName); + } + } + + hcInfo->DriverKey = driverKeyName; + + if (DevProps) + { + ULONG ven, dev, subsys, rev; + ven = dev = subsys = rev = 0; + + if (sscanf_s(DevProps->DeviceId, + "PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", + &ven, &dev, &subsys, &rev) != 4) + { + OOPS(); + } + + hcInfo->VendorID = ven; + hcInfo->DeviceID = dev; + hcInfo->SubSysID = subsys; + hcInfo->Revision = rev; + hcInfo->UsbDeviceProperties = DevProps; + } + else + { + OOPS(); + } + + if (DevProps != NULL && DevProps->DeviceDesc != NULL) + { + leafName = DevProps->DeviceDesc; + } + else + { + OOPS(); + } + + // Get the USB Host Controller power map + dwSuccess = GetHostControllerPowerMap(hHCDev, hcInfo); + + if (ERROR_SUCCESS != dwSuccess) + { + OOPS(); + } + + + // Get bus, device, and function + // + hcInfo->BusDeviceFunctionValid = FALSE; + + success = SetupDiGetDeviceRegistryProperty(deviceInfo, + deviceInfoData, + SPDRP_BUSNUMBER, + NULL, + (PBYTE)&hcInfo->BusNumber, + sizeof(hcInfo->BusNumber), + NULL); + + if (success) + { + success = SetupDiGetDeviceRegistryProperty(deviceInfo, + deviceInfoData, + SPDRP_ADDRESS, + NULL, + (PBYTE)&deviceAndFunction, + sizeof(deviceAndFunction), + NULL); + } + + if (success) + { + hcInfo->BusDevice = deviceAndFunction >> 16; + hcInfo->BusFunction = deviceAndFunction & 0xffff; + hcInfo->BusDeviceFunctionValid = TRUE; + } + + // Get the USB Host Controller info + dwSuccess = GetHostControllerInfo(hHCDev, hcInfo); + + if (ERROR_SUCCESS != dwSuccess) + { + OOPS(); + } + + // Add this host controller to the USB device tree view. + // + hHCItem = AddLeaf(hTreeParent, + (LPARAM)hcInfo, + leafName, + hcInfo->Revision == UsbSuperSpeed ? GoodSsDeviceIcon : GoodDeviceIcon); + + if (NULL == hHCItem) + { + // Failure adding host controller to USB device tree + // view. + + OOPS(); + FREE(driverKeyName); + FREE(hcInfo); + return; + } + + // Add this host controller to the list of enumerated + // host controllers. + // + InsertTailList(&EnumeratedHCListHead, + &hcInfo->ListEntry); + + // Get the name of the root hub for this host + // controller and then enumerate the root hub. + // + rootHubName = GetRootHubName(hHCDev); + + if (rootHubName != NULL) + { + size_t cbHubName = 0; + HRESULT hr = S_OK; + + hr = StringCbLength(rootHubName, MAX_DRIVER_KEY_NAME, &cbHubName); + if (SUCCEEDED(hr)) + { + EnumerateHub(hHCItem, + rootHubName, + cbHubName, + NULL, // ConnectionInfo + NULL, // ConnectionInfoV2 + NULL, // PortConnectorProps + NULL, // ConfigDesc + NULL, // BosDesc + NULL, // StringDescs + NULL); // We do not pass DevProps for RootHub + } + } + else + { + // Failure obtaining root hub name. + + OOPS(); + } + + return; +} + + +//***************************************************************************** +// +// EnumerateHub() +// +// hTreeParent - Handle of the TreeView item under which this hub should be +// added. +// +// HubName - Name of this hub. This pointer is kept so the caller can neither +// free nor reuse this memory. +// +// ConnectionInfo - NULL if this is a root hub, else this is the connection +// info for an external hub. This pointer is kept so the caller can neither +// free nor reuse this memory. +// +// ConfigDesc - NULL if this is a root hub, else this is the Configuration +// Descriptor for an external hub. This pointer is kept so the caller can +// neither free nor reuse this memory. +// +// StringDescs - NULL if this is a root hub. +// +// DevProps - Device properties of the hub +// +//***************************************************************************** + +VOID +EnumerateHub ( + HTREEITEM hTreeParent, + _In_reads_(cbHubName) PCHAR HubName, + _In_ size_t cbHubName, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo, + _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2, + _In_opt_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, + _In_opt_ PUSB_DESCRIPTOR_REQUEST ConfigDesc, + _In_opt_ PUSB_DESCRIPTOR_REQUEST BosDesc, + _In_opt_ PSTRING_DESCRIPTOR_NODE StringDescs, + _In_opt_ PUSB_DEVICE_PNP_STRINGS DevProps + ) +{ + // Initialize locals to not allocated state so the error cleanup routine + // only tries to cleanup things that were successfully allocated. + // + PUSB_NODE_INFORMATION hubInfo = NULL; + PUSB_HUB_INFORMATION_EX hubInfoEx = NULL; + PUSB_HUB_CAPABILITIES_EX hubCapabilityEx = NULL; + HANDLE hHubDevice = INVALID_HANDLE_VALUE; + HTREEITEM hItem = NULL; + PVOID info = NULL; + PCHAR deviceName = NULL; + ULONG nBytes = 0; + BOOL success = 0; + DWORD dwSizeOfLeafName = 0; + CHAR leafName[512] = {0}; + HRESULT hr = S_OK; + size_t cchHeader = 0; + size_t cchFullHubName = 0; + + // Allocate some space for a USBDEVICEINFO structure to hold the + // hub info, hub name, and connection info pointers. GPTR zero + // initializes the structure for us. + // + info = ALLOC(sizeof(USBEXTERNALHUBINFO)); + if (info == NULL) + { + OOPS(); + goto EnumerateHubError; + } + + // Allocate some space for a USB_NODE_INFORMATION structure for this Hub + // + hubInfo = (PUSB_NODE_INFORMATION)ALLOC(sizeof(USB_NODE_INFORMATION)); + if (hubInfo == NULL) + { + OOPS(); + goto EnumerateHubError; + } + + hubInfoEx = (PUSB_HUB_INFORMATION_EX)ALLOC(sizeof(USB_HUB_INFORMATION_EX)); + if (hubInfoEx == NULL) + { + OOPS(); + goto EnumerateHubError; + } + + hubCapabilityEx = (PUSB_HUB_CAPABILITIES_EX)ALLOC(sizeof(USB_HUB_CAPABILITIES_EX)); + if(hubCapabilityEx == NULL) + { + OOPS(); + goto EnumerateHubError; + } + + // Keep copies of the Hub Name, Connection Info, and Configuration + // Descriptor pointers + // + ((PUSBROOTHUBINFO)info)->HubInfo = hubInfo; + ((PUSBROOTHUBINFO)info)->HubName = HubName; + + if (ConnectionInfo != NULL) + { + ((PUSBEXTERNALHUBINFO)info)->DeviceInfoType = ExternalHubInfo; + ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo = ConnectionInfo; + ((PUSBEXTERNALHUBINFO)info)->ConfigDesc = ConfigDesc; + ((PUSBEXTERNALHUBINFO)info)->StringDescs = StringDescs; + ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps = PortConnectorProps; + ((PUSBEXTERNALHUBINFO)info)->HubInfoEx = hubInfoEx; + ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx = hubCapabilityEx; + ((PUSBEXTERNALHUBINFO)info)->BosDesc = BosDesc; + ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2 = ConnectionInfoV2; + ((PUSBEXTERNALHUBINFO)info)->UsbDeviceProperties = DevProps; + } + else + { + ((PUSBROOTHUBINFO)info)->DeviceInfoType = RootHubInfo; + ((PUSBROOTHUBINFO)info)->HubInfoEx = hubInfoEx; + ((PUSBROOTHUBINFO)info)->HubCapabilityEx = hubCapabilityEx; + ((PUSBROOTHUBINFO)info)->PortConnectorProps = PortConnectorProps; + ((PUSBROOTHUBINFO)info)->UsbDeviceProperties = DevProps; + } + + // Allocate a temp buffer for the full hub device name. + // + hr = StringCbLength("\\\\.\\", MAX_DEVICE_PROP, &cchHeader); + if (FAILED(hr)) + { + goto EnumerateHubError; + } + cchFullHubName = cchHeader + cbHubName + 1; + deviceName = (PCHAR)ALLOC((DWORD) cchFullHubName); + if (deviceName == NULL) + { + OOPS(); + goto EnumerateHubError; + } + + // Create the full hub device name + // + hr = StringCchCopyN(deviceName, cchFullHubName, "\\\\.\\", cchHeader); + if (FAILED(hr)) + { + goto EnumerateHubError; + } + hr = StringCchCatN(deviceName, cchFullHubName, HubName, cbHubName); + if (FAILED(hr)) + { + goto EnumerateHubError; + } + + // Try to hub the open device + // + hHubDevice = CreateFile(deviceName, + GENERIC_WRITE, + FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + + // Done with temp buffer for full hub device name + // + FREE(deviceName); + + if (hHubDevice == INVALID_HANDLE_VALUE) + { + OOPS(); + goto EnumerateHubError; + } + + // + // Now query USBHUB for the USB_NODE_INFORMATION structure for this hub. + // This will tell us the number of downstream ports to enumerate, among + // other things. + // + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_NODE_INFORMATION, + hubInfo, + sizeof(USB_NODE_INFORMATION), + hubInfo, + sizeof(USB_NODE_INFORMATION), + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto EnumerateHubError; + } + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_HUB_INFORMATION_EX, + hubInfoEx, + sizeof(USB_HUB_INFORMATION_EX), + hubInfoEx, + sizeof(USB_HUB_INFORMATION_EX), + &nBytes, + NULL); + + // + // Fail gracefully for downlevel OS's from Win8 + // + if (!success || nBytes < sizeof(USB_HUB_INFORMATION_EX)) + { + FREE(hubInfoEx); + hubInfoEx = NULL; + if (ConnectionInfo != NULL) + { + ((PUSBEXTERNALHUBINFO)info)->HubInfoEx = NULL; + } + else + { + ((PUSBROOTHUBINFO)info)->HubInfoEx = NULL; + } + } + + // + // Obtain Hub Capabilities + // + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_HUB_CAPABILITIES_EX, + hubCapabilityEx, + sizeof(USB_HUB_CAPABILITIES_EX), + hubCapabilityEx, + sizeof(USB_HUB_CAPABILITIES_EX), + &nBytes, + NULL); + + // + // Fail gracefully + // + if (!success || nBytes < sizeof(USB_HUB_CAPABILITIES_EX)) + { + FREE(hubCapabilityEx); + hubCapabilityEx = NULL; + if (ConnectionInfo != NULL) + { + ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx = NULL; + } + else + { + ((PUSBROOTHUBINFO)info)->HubCapabilityEx = NULL; + } + } + + // Build the leaf name from the port number and the device description + // + dwSizeOfLeafName = sizeof(leafName); + if (ConnectionInfo) + { + StringCchPrintf(leafName, dwSizeOfLeafName, "[Port%d] ", ConnectionInfo->ConnectionIndex); + StringCchCat(leafName, + dwSizeOfLeafName, + ConnectionStatuses[ConnectionInfo->ConnectionStatus]); + StringCchCatN(leafName, + dwSizeOfLeafName, + " : ", + sizeof(" : ")); + } + + if (DevProps) + { + size_t cbDeviceDesc = 0; + hr = StringCbLength(DevProps->DeviceDesc, MAX_DRIVER_KEY_NAME, &cbDeviceDesc); + if(SUCCEEDED(hr)) + { + StringCchCatN(leafName, + dwSizeOfLeafName, + DevProps->DeviceDesc, + cbDeviceDesc); + } + } + else + { + if(ConnectionInfo != NULL) + { + // External hub + StringCchCatN(leafName, + dwSizeOfLeafName, + HubName, + cbHubName); + } + else + { + // Root hub + StringCchCatN(leafName, + dwSizeOfLeafName, + "RootHub", + sizeof("RootHub")); + } + } + + // Now add an item to the TreeView with the PUSBDEVICEINFO pointer info + // as the LPARAM reference value containing everything we know about the + // hub. + // + hItem = AddLeaf(hTreeParent, + (LPARAM)info, + leafName, + HubIcon); + + if (hItem == NULL) + { + OOPS(); + goto EnumerateHubError; + } + + // Now recursively enumerate the ports of this hub. + // + EnumerateHubPorts( + hItem, + hHubDevice, + hubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts + ); + + + CloseHandle(hHubDevice); + return; + +EnumerateHubError: + // + // Clean up any stuff that got allocated + // + + if (hHubDevice != INVALID_HANDLE_VALUE) + { + CloseHandle(hHubDevice); + hHubDevice = INVALID_HANDLE_VALUE; + } + + if (hubInfo) + { + FREE(hubInfo); + } + + if (hubInfoEx) + { + FREE(hubInfoEx); + } + + if (info) + { + FREE(info); + } + + if (HubName) + { + FREE(HubName); + } + + if (ConnectionInfo) + { + FREE(ConnectionInfo); + } + + if (ConfigDesc) + { + FREE(ConfigDesc); + } + + if (BosDesc) + { + FREE(BosDesc); + } + + if (StringDescs != NULL) + { + PSTRING_DESCRIPTOR_NODE Next; + + do { + + Next = StringDescs->Next; + FREE(StringDescs); + StringDescs = Next; + + } while (StringDescs != NULL); + } +} + +//***************************************************************************** +// +// EnumerateHubPorts() +// +// hTreeParent - Handle of the TreeView item under which the hub port should +// be added. +// +// hHubDevice - Handle of the hub device to enumerate. +// +// NumPorts - Number of ports on the hub. +// +//***************************************************************************** + +VOID +EnumerateHubPorts ( + HTREEITEM hTreeParent, + HANDLE hHubDevice, + ULONG NumPorts +) +{ + ULONG index = 0; + BOOL success = 0; + HRESULT hr = S_OK; + PCHAR driverKeyName = NULL; + PUSB_DEVICE_PNP_STRINGS DevProps; + DWORD dwSizeOfLeafName = 0; + CHAR leafName[512]; + int icon = 0; + + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx; + PUSB_PORT_CONNECTOR_PROPERTIES pPortConnectorProps; + USB_PORT_CONNECTOR_PROPERTIES portConnectorProps; + PUSB_DESCRIPTOR_REQUEST configDesc; + PUSB_DESCRIPTOR_REQUEST bosDesc; + PSTRING_DESCRIPTOR_NODE stringDescs; + PUSBDEVICEINFO info; + PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfoExV2; + PDEVICE_INFO_NODE pNode; + + // Loop over all ports of the hub. + // + // Port indices are 1 based, not 0 based. + // + for (index = 1; index <= NumPorts; index++) + { + ULONG nBytesEx; + ULONG nBytes = 0; + + connectionInfoEx = NULL; + pPortConnectorProps = NULL; + ZeroMemory(&portConnectorProps, sizeof(portConnectorProps)); + configDesc = NULL; + bosDesc = NULL; + stringDescs = NULL; + info = NULL; + connectionInfoExV2 = NULL; + pNode = NULL; + DevProps = NULL; + ZeroMemory(leafName, sizeof(leafName)); + + // + // Allocate space to hold the connection info for this port. + // For now, allocate it big enough to hold info for 30 pipes. + // + // Endpoint numbers are 0-15. Endpoint number 0 is the standard + // control endpoint which is not explicitly listed in the Configuration + // Descriptor. There can be an IN endpoint and an OUT endpoint at + // endpoint numbers 1-15 so there can be a maximum of 30 endpoints + // per device configuration. + // + // Should probably size this dynamically at some point. + // + + nBytesEx = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + + (sizeof(USB_PIPE_INFO) * 30); + + connectionInfoEx = (PUSB_NODE_CONNECTION_INFORMATION_EX)ALLOC(nBytesEx); + + if (connectionInfoEx == NULL) + { + OOPS(); + break; + } + + connectionInfoExV2 = (PUSB_NODE_CONNECTION_INFORMATION_EX_V2) + ALLOC(sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2)); + + if (connectionInfoExV2 == NULL) + { + OOPS(); + FREE(connectionInfoEx); + break; + } + + // + // Now query USBHUB for the structures + // for this port. This will tell us if a device is attached to this + // port, among other things. + // The fault tolerate code is executed first. + // + + portConnectorProps.ConnectionIndex = index; + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES, + &portConnectorProps, + sizeof(USB_PORT_CONNECTOR_PROPERTIES), + &portConnectorProps, + sizeof(USB_PORT_CONNECTOR_PROPERTIES), + &nBytes, + NULL); + + if (success && nBytes == sizeof(USB_PORT_CONNECTOR_PROPERTIES)) + { + pPortConnectorProps = (PUSB_PORT_CONNECTOR_PROPERTIES) + ALLOC(portConnectorProps.ActualLength); + + if (pPortConnectorProps != NULL) + { + pPortConnectorProps->ConnectionIndex = index; + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES, + pPortConnectorProps, + portConnectorProps.ActualLength, + pPortConnectorProps, + portConnectorProps.ActualLength, + &nBytes, + NULL); + + if (!success || nBytes < portConnectorProps.ActualLength) + { + FREE(pPortConnectorProps); + pPortConnectorProps = NULL; + } + } + } + + connectionInfoExV2->ConnectionIndex = index; + connectionInfoExV2->Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2); + connectionInfoExV2->SupportedUsbProtocols.Usb300 = 1; + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, + connectionInfoExV2, + sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2), + connectionInfoExV2, + sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2), + &nBytes, + NULL); + + if (!success || nBytes < sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2)) + { + FREE(connectionInfoExV2); + connectionInfoExV2 = NULL; + } + + connectionInfoEx->ConnectionIndex = index; + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, + connectionInfoEx, + nBytesEx, + connectionInfoEx, + nBytesEx, + &nBytesEx, + NULL); + + if (success) + { + // + // Since the USB_NODE_CONNECTION_INFORMATION_EX is used to display + // the device speed, but the hub driver doesn't support indication + // of superspeed, we overwrite the value if the super speed + // data structures are available and indicate the device is operating + // at SuperSpeed. + // + + if (connectionInfoEx->Speed == UsbHighSpeed + && connectionInfoExV2 != NULL + && (connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher || + connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher)) + { + connectionInfoEx->Speed = UsbSuperSpeed; + } + } + else + { + PUSB_NODE_CONNECTION_INFORMATION connectionInfo = NULL; + + // Try using IOCTL_USB_GET_NODE_CONNECTION_INFORMATION + // instead of IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX + // + + nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) + + sizeof(USB_PIPE_INFO) * 30; + + connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)ALLOC(nBytes); + + if (connectionInfo == NULL) + { + OOPS(); + + FREE(connectionInfoEx); + if (pPortConnectorProps != NULL) + { + FREE(pPortConnectorProps); + } + if (connectionInfoExV2 != NULL) + { + FREE(connectionInfoExV2); + } + continue; + } + + connectionInfo->ConnectionIndex = index; + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, + connectionInfo, + nBytes, + connectionInfo, + nBytes, + &nBytes, + NULL); + + if (!success) + { + OOPS(); + + FREE(connectionInfo); + FREE(connectionInfoEx); + if (pPortConnectorProps != NULL) + { + FREE(pPortConnectorProps); + } + if (connectionInfoExV2 != NULL) + { + FREE(connectionInfoExV2); + } + continue; + } + + // Copy IOCTL_USB_GET_NODE_CONNECTION_INFORMATION into + // IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX structure. + // + connectionInfoEx->ConnectionIndex = connectionInfo->ConnectionIndex; + connectionInfoEx->DeviceDescriptor = connectionInfo->DeviceDescriptor; + connectionInfoEx->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue; + connectionInfoEx->Speed = connectionInfo->LowSpeed ? UsbLowSpeed : UsbFullSpeed; + connectionInfoEx->DeviceIsHub = connectionInfo->DeviceIsHub; + connectionInfoEx->DeviceAddress = connectionInfo->DeviceAddress; + connectionInfoEx->NumberOfOpenPipes = connectionInfo->NumberOfOpenPipes; + connectionInfoEx->ConnectionStatus = connectionInfo->ConnectionStatus; + + memcpy(&connectionInfoEx->PipeList[0], + &connectionInfo->PipeList[0], + sizeof(USB_PIPE_INFO) * 30); + + FREE(connectionInfo); + } + + // Update the count of connected devices + // + if (connectionInfoEx->ConnectionStatus == DeviceConnected) + { + TotalDevicesConnected++; + } + + if (connectionInfoEx->DeviceIsHub) + { + TotalHubs++; + } + + // If there is a device connected, get the Device Description + // + if (connectionInfoEx->ConnectionStatus != NoDeviceConnected) + { + driverKeyName = GetDriverKeyName(hHubDevice, index); + + if (driverKeyName) + { + size_t cbDriverName = 0; + + hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName); + if (SUCCEEDED(hr)) + { + DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName); + pNode = FindMatchingDeviceNodeForDriverName(driverKeyName, connectionInfoEx->DeviceIsHub); + } + FREE(driverKeyName); + } + + } + + // If there is a device connected to the port, try to retrieve the + // Configuration Descriptor from the device. + // + if (gDoConfigDesc && + connectionInfoEx->ConnectionStatus == DeviceConnected) + { + configDesc = GetConfigDescriptor(hHubDevice, + index, + 0); + } + else + { + configDesc = NULL; + } + + if (configDesc != NULL && + connectionInfoEx->DeviceDescriptor.bcdUSB > 0x0200) + { + bosDesc = GetBOSDescriptor(hHubDevice, + index); + } + else + { + bosDesc = NULL; + } + + if (configDesc != NULL && + AreThereStringDescriptors(&connectionInfoEx->DeviceDescriptor, + (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1))) + { + stringDescs = GetAllStringDescriptors ( + hHubDevice, + index, + &connectionInfoEx->DeviceDescriptor, + (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1)); + } + else + { + stringDescs = NULL; + } + + // If the device connected to the port is an external hub, get the + // name of the external hub and recursively enumerate it. + // + if (connectionInfoEx->DeviceIsHub) + { + PCHAR extHubName; + size_t cbHubName = 0; + + extHubName = GetExternalHubName(hHubDevice, index); + if (extHubName != NULL) + { + hr = StringCbLength(extHubName, MAX_DRIVER_KEY_NAME, &cbHubName); + if (SUCCEEDED(hr)) + { + EnumerateHub(hTreeParent, //hPortItem, + extHubName, + cbHubName, + connectionInfoEx, + connectionInfoExV2, + pPortConnectorProps, + configDesc, + bosDesc, + stringDescs, + DevProps); + } + } + } + else + { + // Allocate some space for a USBDEVICEINFO structure to hold the + // hub info, hub name, and connection info pointers. GPTR zero + // initializes the structure for us. + // + info = (PUSBDEVICEINFO) ALLOC(sizeof(USBDEVICEINFO)); + + if (info == NULL) + { + OOPS(); + if (configDesc != NULL) + { + FREE(configDesc); + } + if (bosDesc != NULL) + { + FREE(bosDesc); + } + FREE(connectionInfoEx); + + if (pPortConnectorProps != NULL) + { + FREE(pPortConnectorProps); + } + if (connectionInfoExV2 != NULL) + { + FREE(connectionInfoExV2); + } + break; + } + + info->DeviceInfoType = DeviceInfo; + info->ConnectionInfo = connectionInfoEx; + info->PortConnectorProps = pPortConnectorProps; + info->ConfigDesc = configDesc; + info->StringDescs = stringDescs; + info->BosDesc = bosDesc; + info->ConnectionInfoV2 = connectionInfoExV2; + info->UsbDeviceProperties = DevProps; + info->DeviceInfoNode = pNode; + + StringCchPrintf(leafName, sizeof(leafName), "[Port%d] ", index); + + // Add error description if ConnectionStatus is other than NoDeviceConnected / DeviceConnected + StringCchCat(leafName, + sizeof(leafName), + ConnectionStatuses[connectionInfoEx->ConnectionStatus]); + + if (DevProps) + { + size_t cchDeviceDesc = 0; + + hr = StringCbLength(DevProps->DeviceDesc, MAX_DEVICE_PROP, &cchDeviceDesc); + if (FAILED(hr)) + { + OOPS(); + } + dwSizeOfLeafName = sizeof(leafName); + StringCchCatN(leafName, + dwSizeOfLeafName - 1, + " : ", + sizeof(" : ")); + StringCchCatN(leafName, + dwSizeOfLeafName - 1, + DevProps->DeviceDesc, + cchDeviceDesc ); + } + + if (connectionInfoEx->ConnectionStatus == NoDeviceConnected) + { + if (connectionInfoExV2 != NULL && + connectionInfoExV2->SupportedUsbProtocols.Usb300 == 1) + { + icon = NoSsDeviceIcon; + } + else + { + icon = NoDeviceIcon; + } + } + else if (connectionInfoEx->CurrentConfigurationValue) + { + if (connectionInfoEx->Speed == UsbSuperSpeed) + { + icon = GoodSsDeviceIcon; + } + else + { + icon = GoodDeviceIcon; + } + } + else + { + icon = BadDeviceIcon; + } + + AddLeaf(hTreeParent, //hPortItem, + (LPARAM)info, + leafName, + icon); + } + } // for +} + + +//***************************************************************************** +// +// WideStrToMultiStr() +// +//***************************************************************************** + +PCHAR WideStrToMultiStr ( + _In_reads_bytes_(cbWideStr) PWCHAR WideStr, + _In_ size_t cbWideStr + ) +{ + ULONG nBytes = 0; + PCHAR MultiStr = NULL; + PWCHAR pWideStr = NULL; + + // Use local string to guarantee zero termination + pWideStr = (PWCHAR) ALLOC((DWORD) cbWideStr + sizeof(WCHAR)); + if (NULL == pWideStr) + { + return NULL; + } + memset(pWideStr, 0, cbWideStr + sizeof(WCHAR)); + memcpy(pWideStr, WideStr, cbWideStr); + + // Get the length of the converted string + // + nBytes = WideCharToMultiByte( + CP_ACP, + WC_NO_BEST_FIT_CHARS, + pWideStr, + -1, + NULL, + 0, + NULL, + NULL); + + if (nBytes == 0) + { + FREE(pWideStr); + return NULL; + } + + // Allocate space to hold the converted string + // + MultiStr = ALLOC(nBytes); + if (MultiStr == NULL) + { + FREE(pWideStr); + return NULL; + } + + // Convert the string + // + nBytes = WideCharToMultiByte( + CP_ACP, + WC_NO_BEST_FIT_CHARS, + pWideStr, + -1, + MultiStr, + nBytes, + NULL, + NULL); + + if (nBytes == 0) + { + FREE(MultiStr); + FREE(pWideStr); + return NULL; + } + + FREE(pWideStr); + return MultiStr; +} + +//***************************************************************************** +// +// GetRootHubName() +// +//***************************************************************************** + +PCHAR GetRootHubName ( + HANDLE HostController +) +{ + BOOL success = 0; + ULONG nBytes = 0; + USB_ROOT_HUB_NAME rootHubName; + PUSB_ROOT_HUB_NAME rootHubNameW = NULL; + PCHAR rootHubNameA = NULL; + + // Get the length of the name of the Root Hub attached to the + // Host Controller + // + success = DeviceIoControl(HostController, + IOCTL_USB_GET_ROOT_HUB_NAME, + 0, + 0, + &rootHubName, + sizeof(rootHubName), + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto GetRootHubNameError; + } + + // Allocate space to hold the Root Hub name + // + nBytes = rootHubName.ActualLength; + + rootHubNameW = ALLOC(nBytes); + if (rootHubNameW == NULL) + { + OOPS(); + goto GetRootHubNameError; + } + + // Get the name of the Root Hub attached to the Host Controller + // + success = DeviceIoControl(HostController, + IOCTL_USB_GET_ROOT_HUB_NAME, + NULL, + 0, + rootHubNameW, + nBytes, + &nBytes, + NULL); + if (!success) + { + OOPS(); + goto GetRootHubNameError; + } + + // Convert the Root Hub name + // + rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName, nBytes - sizeof(USB_ROOT_HUB_NAME) + sizeof(WCHAR)); + + // All done, free the uncoverted Root Hub name and return the + // converted Root Hub name + // + FREE(rootHubNameW); + + return rootHubNameA; + +GetRootHubNameError: + // There was an error, free anything that was allocated + // + if (rootHubNameW != NULL) + { + FREE(rootHubNameW); + rootHubNameW = NULL; + } + return NULL; +} + + +//***************************************************************************** +// +// GetExternalHubName() +// +//***************************************************************************** + +PCHAR GetExternalHubName ( + HANDLE Hub, + ULONG ConnectionIndex +) +{ + BOOL success = 0; + ULONG nBytes = 0; + USB_NODE_CONNECTION_NAME extHubName; + PUSB_NODE_CONNECTION_NAME extHubNameW = NULL; + PCHAR extHubNameA = NULL; + + // Get the length of the name of the external hub attached to the + // specified port. + // + extHubName.ConnectionIndex = ConnectionIndex; + + success = DeviceIoControl(Hub, + IOCTL_USB_GET_NODE_CONNECTION_NAME, + &extHubName, + sizeof(extHubName), + &extHubName, + sizeof(extHubName), + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto GetExternalHubNameError; + } + + // Allocate space to hold the external hub name + // + nBytes = extHubName.ActualLength; + + if (nBytes <= sizeof(extHubName)) + { + OOPS(); + goto GetExternalHubNameError; + } + + extHubNameW = ALLOC(nBytes); + + if (extHubNameW == NULL) + { + OOPS(); + goto GetExternalHubNameError; + } + + // Get the name of the external hub attached to the specified port + // + extHubNameW->ConnectionIndex = ConnectionIndex; + + success = DeviceIoControl(Hub, + IOCTL_USB_GET_NODE_CONNECTION_NAME, + extHubNameW, + nBytes, + extHubNameW, + nBytes, + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto GetExternalHubNameError; + } + + // Convert the External Hub name + // + extHubNameA = WideStrToMultiStr(extHubNameW->NodeName, nBytes - sizeof(USB_NODE_CONNECTION_NAME) + sizeof(WCHAR)); + + // All done, free the uncoverted external hub name and return the + // converted external hub name + // + FREE(extHubNameW); + + return extHubNameA; + + +GetExternalHubNameError: + // There was an error, free anything that was allocated + // + if (extHubNameW != NULL) + { + FREE(extHubNameW); + extHubNameW = NULL; + } + + return NULL; +} + + +//***************************************************************************** +// +// GetDriverKeyName() +// +//***************************************************************************** + +PCHAR GetDriverKeyName ( + HANDLE Hub, + ULONG ConnectionIndex +) +{ + BOOL success = 0; + ULONG nBytes = 0; + USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName; + PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW = NULL; + PCHAR driverKeyNameA = NULL; + + // Get the length of the name of the driver key of the device attached to + // the specified port. + // + driverKeyName.ConnectionIndex = ConnectionIndex; + + success = DeviceIoControl(Hub, + IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, + &driverKeyName, + sizeof(driverKeyName), + &driverKeyName, + sizeof(driverKeyName), + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto GetDriverKeyNameError; + } + + // Allocate space to hold the driver key name + // + nBytes = driverKeyName.ActualLength; + + if (nBytes <= sizeof(driverKeyName)) + { + OOPS(); + goto GetDriverKeyNameError; + } + + driverKeyNameW = ALLOC(nBytes); + if (driverKeyNameW == NULL) + { + OOPS(); + goto GetDriverKeyNameError; + } + + // Get the name of the driver key of the device attached to + // the specified port. + // + driverKeyNameW->ConnectionIndex = ConnectionIndex; + + success = DeviceIoControl(Hub, + IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, + driverKeyNameW, + nBytes, + driverKeyNameW, + nBytes, + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto GetDriverKeyNameError; + } + + // Convert the driver key name + // + driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName, nBytes - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) + sizeof(WCHAR)); + + // All done, free the uncoverted driver key name and return the + // converted driver key name + // + FREE(driverKeyNameW); + + return driverKeyNameA; + + +GetDriverKeyNameError: + // There was an error, free anything that was allocated + // + if (driverKeyNameW != NULL) + { + FREE(driverKeyNameW); + driverKeyNameW = NULL; + } + + return NULL; +} + + +//***************************************************************************** +// +// GetHCDDriverKeyName() +// +//***************************************************************************** + +PCHAR GetHCDDriverKeyName ( + HANDLE HCD +) +{ + BOOL success = 0; + ULONG nBytes = 0; + USB_HCD_DRIVERKEY_NAME driverKeyName = {0}; + PUSB_HCD_DRIVERKEY_NAME driverKeyNameW = NULL; + PCHAR driverKeyNameA = NULL; + + ZeroMemory(&driverKeyName, sizeof(driverKeyName)); + + // Get the length of the name of the driver key of the HCD + // + success = DeviceIoControl(HCD, + IOCTL_GET_HCD_DRIVERKEY_NAME, + &driverKeyName, + sizeof(driverKeyName), + &driverKeyName, + sizeof(driverKeyName), + &nBytes, + NULL); + + if (!success) + { + OOPS(); + goto GetHCDDriverKeyNameError; + } + + // Allocate space to hold the driver key name + // + nBytes = driverKeyName.ActualLength; + if (nBytes <= sizeof(driverKeyName)) + { + OOPS(); + goto GetHCDDriverKeyNameError; + } + + driverKeyNameW = ALLOC(nBytes); + if (driverKeyNameW == NULL) + { + OOPS(); + goto GetHCDDriverKeyNameError; + } + + // Get the name of the driver key of the device attached to + // the specified port. + // + + success = DeviceIoControl(HCD, + IOCTL_GET_HCD_DRIVERKEY_NAME, + driverKeyNameW, + nBytes, + driverKeyNameW, + nBytes, + &nBytes, + NULL); + if (!success) + { + OOPS(); + goto GetHCDDriverKeyNameError; + } + + // + // Convert the driver key name + // Pass the length of the DriverKeyName string + // + + driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName, nBytes - sizeof(USB_HCD_DRIVERKEY_NAME) + sizeof(WCHAR)); + + // All done, free the uncoverted driver key name and return the + // converted driver key name + // + FREE(driverKeyNameW); + + return driverKeyNameA; + +GetHCDDriverKeyNameError: + // There was an error, free anything that was allocated + // + if (driverKeyNameW != NULL) + { + FREE(driverKeyNameW); + driverKeyNameW = NULL; + } + + return NULL; +} + + +//***************************************************************************** +// +// GetConfigDescriptor() +// +// hHubDevice - Handle of the hub device containing the port from which the +// Configuration Descriptor will be requested. +// +// ConnectionIndex - Identifies the port on the hub to which a device is +// attached from which the Configuration Descriptor will be requested. +// +// DescriptorIndex - Configuration Descriptor index, zero based. +// +//***************************************************************************** + +PUSB_DESCRIPTOR_REQUEST +GetConfigDescriptor ( + HANDLE hHubDevice, + ULONG ConnectionIndex, + UCHAR DescriptorIndex +) +{ + BOOL success = 0; + ULONG nBytes = 0; + ULONG nBytesReturned = 0; + + UCHAR configDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + + sizeof(USB_CONFIGURATION_DESCRIPTOR)]; + + PUSB_DESCRIPTOR_REQUEST configDescReq = NULL; + PUSB_CONFIGURATION_DESCRIPTOR configDesc = NULL; + + + // Request the Configuration Descriptor the first time using our + // local buffer, which is just big enough for the Cofiguration + // Descriptor itself. + // + nBytes = sizeof(configDescReqBuf); + + configDescReq = (PUSB_DESCRIPTOR_REQUEST)configDescReqBuf; + configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1); + + // Zero fill the entire request structure + // + memset(configDescReq, 0, nBytes); + + // Indicate the port from which the descriptor will be requested + // + configDescReq->ConnectionIndex = ConnectionIndex; + + // + // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this + // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. + // + // USBD will automatically initialize these fields: + // bmRequest = 0x80 + // bRequest = 0x06 + // + // We must inititialize these fields: + // wValue = Descriptor Type (high) and Descriptor Index (low byte) + // wIndex = Zero (or Language ID for String Descriptors) + // wLength = Length of descriptor buffer + // + configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) + | DescriptorIndex; + + configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); + + // Now issue the get descriptor request. + // + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, + configDescReq, + nBytes, + configDescReq, + nBytes, + &nBytesReturned, + NULL); + + if (!success) + { + OOPS(); + return NULL; + } + + if (nBytes != nBytesReturned) + { + OOPS(); + return NULL; + } + + if (configDesc->wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + OOPS(); + return NULL; + } + + // Now request the entire Configuration Descriptor using a dynamically + // allocated buffer which is sized big enough to hold the entire descriptor + // + nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + configDesc->wTotalLength; + + configDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes); + + if (configDescReq == NULL) + { + OOPS(); + return NULL; + } + + configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1); + + // Indicate the port from which the descriptor will be requested + // + configDescReq->ConnectionIndex = ConnectionIndex; + + // + // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this + // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. + // + // USBD will automatically initialize these fields: + // bmRequest = 0x80 + // bRequest = 0x06 + // + // We must inititialize these fields: + // wValue = Descriptor Type (high) and Descriptor Index (low byte) + // wIndex = Zero (or Language ID for String Descriptors) + // wLength = Length of descriptor buffer + // + configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) + | DescriptorIndex; + + configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); + + // Now issue the get descriptor request. + // + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, + configDescReq, + nBytes, + configDescReq, + nBytes, + &nBytesReturned, + NULL); + + if (!success) + { + OOPS(); + FREE(configDescReq); + return NULL; + } + + if (nBytes != nBytesReturned) + { + OOPS(); + FREE(configDescReq); + return NULL; + } + + if (configDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST))) + { + OOPS(); + FREE(configDescReq); + return NULL; + } + + return configDescReq; +} + + + +//***************************************************************************** +// +// GetBOSDescriptor() +// +// hHubDevice - Handle of the hub device containing the port from which the +// Configuration Descriptor will be requested. +// +// ConnectionIndex - Identifies the port on the hub to which a device is +// attached from which the BOS Descriptor will be requested. +// +//***************************************************************************** + +PUSB_DESCRIPTOR_REQUEST +GetBOSDescriptor ( + HANDLE hHubDevice, + ULONG ConnectionIndex +) +{ + BOOL success = 0; + ULONG nBytes = 0; + ULONG nBytesReturned = 0; + + UCHAR bosDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + + sizeof(USB_BOS_DESCRIPTOR)]; + + PUSB_DESCRIPTOR_REQUEST bosDescReq = NULL; + PUSB_BOS_DESCRIPTOR bosDesc = NULL; + + + // Request the BOS Descriptor the first time using our + // local buffer, which is just big enough for the BOS + // Descriptor itself. + // + nBytes = sizeof(bosDescReqBuf); + + bosDescReq = (PUSB_DESCRIPTOR_REQUEST)bosDescReqBuf; + bosDesc = (PUSB_BOS_DESCRIPTOR)(bosDescReq+1); + + // Zero fill the entire request structure + // + memset(bosDescReq, 0, nBytes); + + // Indicate the port from which the descriptor will be requested + // + bosDescReq->ConnectionIndex = ConnectionIndex; + + // + // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this + // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. + // + // USBD will automatically initialize these fields: + // bmRequest = 0x80 + // bRequest = 0x06 + // + // We must inititialize these fields: + // wValue = Descriptor Type (high) and Descriptor Index (low byte) + // wIndex = Zero (or Language ID for String Descriptors) + // wLength = Length of descriptor buffer + // + bosDescReq->SetupPacket.wValue = (USB_BOS_DESCRIPTOR_TYPE << 8); + + bosDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); + + // Now issue the get descriptor request. + // + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, + bosDescReq, + nBytes, + bosDescReq, + nBytes, + &nBytesReturned, + NULL); + + if (!success) + { + OOPS(); + return NULL; + } + + if (nBytes != nBytesReturned) + { + OOPS(); + return NULL; + } + + if (bosDesc->wTotalLength < sizeof(USB_BOS_DESCRIPTOR)) + { + OOPS(); + return NULL; + } + + // Now request the entire BOS Descriptor using a dynamically + // allocated buffer which is sized big enough to hold the entire descriptor + // + nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + bosDesc->wTotalLength; + + bosDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes); + + if (bosDescReq == NULL) + { + OOPS(); + return NULL; + } + + bosDesc = (PUSB_BOS_DESCRIPTOR)(bosDescReq+1); + + // Indicate the port from which the descriptor will be requested + // + bosDescReq->ConnectionIndex = ConnectionIndex; + + // + // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this + // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. + // + // USBD will automatically initialize these fields: + // bmRequest = 0x80 + // bRequest = 0x06 + // + // We must inititialize these fields: + // wValue = Descriptor Type (high) and Descriptor Index (low byte) + // wIndex = Zero (or Language ID for String Descriptors) + // wLength = Length of descriptor buffer + // + bosDescReq->SetupPacket.wValue = (USB_BOS_DESCRIPTOR_TYPE << 8); + + bosDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); + + // Now issue the get descriptor request. + // + + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, + bosDescReq, + nBytes, + bosDescReq, + nBytes, + &nBytesReturned, + NULL); + + if (!success) + { + OOPS(); + FREE(bosDescReq); + return NULL; + } + + if (nBytes != nBytesReturned) + { + OOPS(); + FREE(bosDescReq); + return NULL; + } + + if (bosDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST))) + { + OOPS(); + FREE(bosDescReq); + return NULL; + } + + return bosDescReq; +} + + +//***************************************************************************** +// +// AreThereStringDescriptors() +// +// DeviceDesc - Device Descriptor for which String Descriptors should be +// checked. +// +// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor) +// for which String Descriptors should be checked. +// +//***************************************************************************** + +BOOL +AreThereStringDescriptors ( + PUSB_DEVICE_DESCRIPTOR DeviceDesc, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc +) +{ + PUCHAR descEnd = NULL; + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + + // + // Check Device Descriptor strings + // + + if (DeviceDesc->iManufacturer || + DeviceDesc->iProduct || + DeviceDesc->iSerialNumber + ) + { + return TRUE; + } + + + // + // Check the Configuration and Interface Descriptor strings + // + + descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + switch (commonDesc->bDescriptorType) + { + case USB_CONFIGURATION_DESCRIPTOR_TYPE: + case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + OOPS(); + break; + } + if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration) + { + return TRUE; + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + + case USB_INTERFACE_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) && + commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2)) + { + OOPS(); + break; + } + if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface) + { + return TRUE; + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + + default: + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + } + break; + } + + return FALSE; +} + + +//***************************************************************************** +// +// GetAllStringDescriptors() +// +// hHubDevice - Handle of the hub device containing the port from which the +// String Descriptors will be requested. +// +// ConnectionIndex - Identifies the port on the hub to which a device is +// attached from which the String Descriptors will be requested. +// +// DeviceDesc - Device Descriptor for which String Descriptors should be +// requested. +// +// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor) +// for which String Descriptors should be requested. +// +//***************************************************************************** + +PSTRING_DESCRIPTOR_NODE +GetAllStringDescriptors ( + HANDLE hHubDevice, + ULONG ConnectionIndex, + PUSB_DEVICE_DESCRIPTOR DeviceDesc, + PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc +) +{ + PSTRING_DESCRIPTOR_NODE supportedLanguagesString = NULL; + ULONG numLanguageIDs = 0; + USHORT *languageIDs = NULL; + + PUCHAR descEnd = NULL; + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + UCHAR uIndex = 1; + UCHAR bInterfaceClass = 0; + BOOL getMoreStrings = FALSE; + HRESULT hr = S_OK; + + // + // Get the array of supported Language IDs, which is returned + // in String Descriptor 0 + // + supportedLanguagesString = GetStringDescriptor(hHubDevice, + ConnectionIndex, + 0, + 0); + + if (supportedLanguagesString == NULL) + { + return NULL; + } + + numLanguageIDs = (supportedLanguagesString->StringDescriptor->bLength - 2) / 2; + + languageIDs = &supportedLanguagesString->StringDescriptor->bString[0]; + + // + // Get the Device Descriptor strings + // + + if (DeviceDesc->iManufacturer) + { + GetStringDescriptors(hHubDevice, + ConnectionIndex, + DeviceDesc->iManufacturer, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + + if (DeviceDesc->iProduct) + { + GetStringDescriptors(hHubDevice, + ConnectionIndex, + DeviceDesc->iProduct, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + + if (DeviceDesc->iSerialNumber) + { + GetStringDescriptors(hHubDevice, + ConnectionIndex, + DeviceDesc->iSerialNumber, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + + // + // Get the Configuration and Interface Descriptor strings + // + + descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; + + commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; + + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + switch (commonDesc->bDescriptorType) + { + case USB_CONFIGURATION_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + OOPS(); + break; + } + if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration) + { + GetStringDescriptors(hHubDevice, + ConnectionIndex, + ((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + + case USB_IAD_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR)) + { + OOPS(); + break; + } + if (((PUSB_IAD_DESCRIPTOR)commonDesc)->iFunction) + { + GetStringDescriptors(hHubDevice, + ConnectionIndex, + ((PUSB_IAD_DESCRIPTOR)commonDesc)->iFunction, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + + case USB_INTERFACE_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) && + commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2)) + { + OOPS(); + break; + } + if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface) + { + GetStringDescriptors(hHubDevice, + ConnectionIndex, + ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + + // + // We need to display more string descriptors for the following + // interface classes + // + bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass; + if (bInterfaceClass == USB_DEVICE_CLASS_VIDEO) + { + getMoreStrings = TRUE; + } + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + + default: + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + continue; + } + break; + } + + if (getMoreStrings) + { + // + // We might need to display strings later that are referenced only in + // class-specific descriptors. Get String Descriptors 1 through 32 (an + // arbitrary upper limit for Strings needed due to "bad devices" + // returning an infinite repeat of Strings 0 through 4) until one is not + // found. + // + // There are also "bad devices" that have issues even querying 1-32, but + // historically USBView made this query, so the query should be safe for + // video devices. + // + for (uIndex = 1; SUCCEEDED(hr) && (uIndex < NUM_STRING_DESC_TO_GET); uIndex++) + { + hr = GetStringDescriptors(hHubDevice, + ConnectionIndex, + uIndex, + numLanguageIDs, + languageIDs, + supportedLanguagesString); + } + } + + return supportedLanguagesString; +} + + + +//***************************************************************************** +// +// GetStringDescriptor() +// +// hHubDevice - Handle of the hub device containing the port from which the +// String Descriptor will be requested. +// +// ConnectionIndex - Identifies the port on the hub to which a device is +// attached from which the String Descriptor will be requested. +// +// DescriptorIndex - String Descriptor index. +// +// LanguageID - Language in which the string should be requested. +// +//***************************************************************************** + +PSTRING_DESCRIPTOR_NODE +GetStringDescriptor ( + HANDLE hHubDevice, + ULONG ConnectionIndex, + UCHAR DescriptorIndex, + USHORT LanguageID +) +{ + BOOL success = 0; + ULONG nBytes = 0; + ULONG nBytesReturned = 0; + + UCHAR stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + + MAXIMUM_USB_STRING_LENGTH]; + + PUSB_DESCRIPTOR_REQUEST stringDescReq = NULL; + PUSB_STRING_DESCRIPTOR stringDesc = NULL; + PSTRING_DESCRIPTOR_NODE stringDescNode = NULL; + + nBytes = sizeof(stringDescReqBuf); + + stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf; + stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1); + + // Zero fill the entire request structure + // + memset(stringDescReq, 0, nBytes); + + // Indicate the port from which the descriptor will be requested + // + stringDescReq->ConnectionIndex = ConnectionIndex; + + // + // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this + // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. + // + // USBD will automatically initialize these fields: + // bmRequest = 0x80 + // bRequest = 0x06 + // + // We must inititialize these fields: + // wValue = Descriptor Type (high) and Descriptor Index (low byte) + // wIndex = Zero (or Language ID for String Descriptors) + // wLength = Length of descriptor buffer + // + stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) + | DescriptorIndex; + + stringDescReq->SetupPacket.wIndex = LanguageID; + + stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); + + // Now issue the get descriptor request. + // + success = DeviceIoControl(hHubDevice, + IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, + stringDescReq, + nBytes, + stringDescReq, + nBytes, + &nBytesReturned, + NULL); + + // + // Do some sanity checks on the return from the get descriptor request. + // + + if (!success) + { + OOPS(); + return NULL; + } + + if (nBytesReturned < 2) + { + OOPS(); + return NULL; + } + + if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE) + { + OOPS(); + return NULL; + } + + if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST)) + { + OOPS(); + return NULL; + } + + if (stringDesc->bLength % 2 != 0) + { + OOPS(); + return NULL; + } + + // + // Looks good, allocate some (zero filled) space for the string descriptor + // node and copy the string descriptor to it. + // + + stringDescNode = (PSTRING_DESCRIPTOR_NODE)ALLOC(sizeof(STRING_DESCRIPTOR_NODE) + + stringDesc->bLength); + + if (stringDescNode == NULL) + { + OOPS(); + return NULL; + } + + stringDescNode->DescriptorIndex = DescriptorIndex; + stringDescNode->LanguageID = LanguageID; + + memcpy(stringDescNode->StringDescriptor, + stringDesc, + stringDesc->bLength); + + return stringDescNode; +} + + +//***************************************************************************** +// +// GetStringDescriptors() +// +// hHubDevice - Handle of the hub device containing the port from which the +// String Descriptor will be requested. +// +// ConnectionIndex - Identifies the port on the hub to which a device is +// attached from which the String Descriptor will be requested. +// +// DescriptorIndex - String Descriptor index. +// +// NumLanguageIDs - Number of languages in which the string should be +// requested. +// +// LanguageIDs - Languages in which the string should be requested. +// +// StringDescNodeHead - First node in linked list of device's string descriptors +// +// Return Value: HRESULT indicating whether the string is on the list +// +//***************************************************************************** + +HRESULT +GetStringDescriptors ( + _In_ HANDLE hHubDevice, + _In_ ULONG ConnectionIndex, + _In_ UCHAR DescriptorIndex, + _In_ ULONG NumLanguageIDs, + _In_reads_(NumLanguageIDs) USHORT *LanguageIDs, + _In_ PSTRING_DESCRIPTOR_NODE StringDescNodeHead +) +{ + PSTRING_DESCRIPTOR_NODE tail = NULL; + PSTRING_DESCRIPTOR_NODE trailing = NULL; + ULONG i = 0; + + // + // Go to the end of the linked list, searching for the requested index to + // see if we've already retrieved it + // + for (tail = StringDescNodeHead; tail != NULL; tail = tail->Next) + { + if (tail->DescriptorIndex == DescriptorIndex) + { + return S_OK; + } + + trailing = tail; + } + + tail = trailing; + + // + // Get the next String Descriptor. If this is NULL, then we're done (return) + // Otherwise, loop through all Language IDs + // + for (i = 0; (tail != NULL) && (i < NumLanguageIDs); i++) + { + tail->Next = GetStringDescriptor(hHubDevice, + ConnectionIndex, + DescriptorIndex, + LanguageIDs[i]); + + tail = tail->Next; + } + + if (tail == NULL) + { + return E_FAIL; + } else { + return S_OK; + } +} + + +//***************************************************************************** +// +// CleanupItem() +// +//***************************************************************************** + +VOID +CleanupItem ( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext +) +{ + TV_ITEM tvi; + PVOID info = NULL; + + UNREFERENCED_PARAMETER(pContext); + + tvi.mask = TVIF_HANDLE | TVIF_PARAM; + tvi.hItem = hTreeItem; + + TreeView_GetItem(hTreeWnd, + &tvi); + + info = (PVOID)tvi.lParam; + + if (info) + { + PCHAR DriverKey = NULL; + PUSB_NODE_INFORMATION HubInfo = NULL; + PCHAR HubName = NULL; + PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfoEx = NULL; + PUSB_DESCRIPTOR_REQUEST ConfigDesc = NULL; + PUSB_DESCRIPTOR_REQUEST BosDesc = NULL; + PSTRING_DESCRIPTOR_NODE StringDescs = NULL; + PUSB_HUB_INFORMATION_EX HubInfoEx = NULL; + PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps = NULL; + PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 = NULL; + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx = NULL; + PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties = NULL; + PUSB_CONTROLLER_INFO_0 ControllerInfo = NULL; + + // + // All structures except DEVICE_INFO_NODE are free'd up here. DEVICE_INFO_NODE structures are free'd while + // destroying device info lists (ClearDeviceList()) + // + switch (*(PUSBDEVICEINFOTYPE)info) + { + case HostControllerInfo: + // + // Remove this host controller from the list of enumerated + // host controllers. + // + RemoveEntryList(&((PUSBHOSTCONTROLLERINFO)info)->ListEntry); + DriverKey = ((PUSBHOSTCONTROLLERINFO)info)->DriverKey; + ControllerInfo = ((PUSBHOSTCONTROLLERINFO)info)->ControllerInfo; + UsbDeviceProperties = ((PUSBHOSTCONTROLLERINFO)info)->UsbDeviceProperties; + break; + + case RootHubInfo: + HubInfo = ((PUSBROOTHUBINFO)info)->HubInfo; + HubInfoEx = ((PUSBROOTHUBINFO)info)->HubInfoEx; + HubName = ((PUSBROOTHUBINFO)info)->HubName; + PortConnectorProps = ((PUSBROOTHUBINFO)info)->PortConnectorProps; + UsbDeviceProperties = ((PUSBROOTHUBINFO)info)->UsbDeviceProperties; + HubCapabilityEx = ((PUSBROOTHUBINFO)info)->HubCapabilityEx; + break; + + case ExternalHubInfo: + HubInfo = ((PUSBEXTERNALHUBINFO)info)->HubInfo; + HubInfoEx = ((PUSBEXTERNALHUBINFO)info)->HubInfoEx; + HubName = ((PUSBEXTERNALHUBINFO)info)->HubName; + ConnectionInfoEx = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo; + PortConnectorProps = ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps; + ConfigDesc = ((PUSBEXTERNALHUBINFO)info)->ConfigDesc; + BosDesc = ((PUSBEXTERNALHUBINFO)info)->BosDesc; + StringDescs = ((PUSBEXTERNALHUBINFO)info)->StringDescs; + ConnectionInfoV2 = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2; + UsbDeviceProperties = ((PUSBEXTERNALHUBINFO)info)->UsbDeviceProperties; + HubCapabilityEx = ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx; + break; + + case DeviceInfo: + ConnectionInfoEx = ((PUSBDEVICEINFO)info)->ConnectionInfo; + PortConnectorProps = ((PUSBDEVICEINFO)info)->PortConnectorProps; + ConfigDesc = ((PUSBDEVICEINFO)info)->ConfigDesc; + BosDesc = ((PUSBDEVICEINFO)info)->BosDesc; + StringDescs = ((PUSBDEVICEINFO)info)->StringDescs; + ConnectionInfoV2 = ((PUSBDEVICEINFO)info)->ConnectionInfoV2; + UsbDeviceProperties = ((PUSBDEVICEINFO)info)->UsbDeviceProperties; + break; + } + + if(UsbDeviceProperties) + { + FreeDeviceProperties(&UsbDeviceProperties); + } + + if(ControllerInfo) + { + FREE(ControllerInfo); + } + + if(HubCapabilityEx) + { + FREE(HubCapabilityEx); + } + + if (DriverKey) + { + FREE(DriverKey); + } + + if (HubInfo) + { + FREE(HubInfo); + } + + if (HubName) + { + FREE(HubName); + } + + if (ConfigDesc) + { + FREE(ConfigDesc); + } + + if (BosDesc) + { + FREE(BosDesc); + } + + if (StringDescs) + { + PSTRING_DESCRIPTOR_NODE Next; + + do { + + Next = StringDescs->Next; + FREE(StringDescs); + StringDescs = Next; + + } while (StringDescs); + } + + if (ConnectionInfoEx) + { + FREE(ConnectionInfoEx); + } + + if (HubInfoEx) + { + FREE(HubInfoEx); + } + + if (PortConnectorProps) + { + FREE(PortConnectorProps); + } + + if (ConnectionInfoV2) + { + FREE(ConnectionInfoV2); + } + + FREE(info); + } +} + +//***************************************************************************** +// +// GetHostControllerPowerMap() +// +// HANDLE hHCDev +// - handle to USB Host Controller +// +// PUSBHOSTCONTROLLERINFO hcInfo +// - data structure to receive the Power Map Info +// +// return DWORD dwError +// - return ERROR_SUCCESS or last error +// +//***************************************************************************** + +DWORD +GetHostControllerPowerMap( + HANDLE hHCDev, + PUSBHOSTCONTROLLERINFO hcInfo) +{ + USBUSER_POWER_INFO_REQUEST UsbPowerInfoRequest; + PUSB_POWER_INFO pUPI = &UsbPowerInfoRequest.PowerInformation ; + DWORD dwError = 0; + DWORD dwBytes = 0; + BOOL bSuccess = FALSE; + int nIndex = 0; + int nPowerState = WdmUsbPowerSystemWorking; + + for ( ; nPowerState <= WdmUsbPowerSystemShutdown; nIndex++, nPowerState++) + { + // zero initialize our request + memset(&UsbPowerInfoRequest, 0, sizeof(UsbPowerInfoRequest)); + + // set the header and request sizes + UsbPowerInfoRequest.Header.UsbUserRequest = USBUSER_GET_POWER_STATE_MAP; + UsbPowerInfoRequest.Header.RequestBufferLength = sizeof(UsbPowerInfoRequest); + UsbPowerInfoRequest.PowerInformation.SystemState = nPowerState; + + // + // Now query USBHUB for the USB_POWER_INFO structure for this hub. + // For Selective Suspend support + // + bSuccess = DeviceIoControl(hHCDev, + IOCTL_USB_USER_REQUEST, + &UsbPowerInfoRequest, + sizeof(UsbPowerInfoRequest), + &UsbPowerInfoRequest, + sizeof(UsbPowerInfoRequest), + &dwBytes, + NULL); + + if (!bSuccess) + { + dwError = GetLastError(); + OOPS(); + } + else + { + // copy the data into our USB Host Controller's info structure + memcpy( &(hcInfo->USBPowerInfo[nIndex]), pUPI, sizeof(USB_POWER_INFO)); + } + } + + return dwError; +} + +void +EnumerateAllDevices() +{ + EnumerateAllDevicesWithGuid(&gDeviceList, + (LPGUID)&GUID_DEVINTERFACE_USB_DEVICE); + + EnumerateAllDevicesWithGuid(&gHubList, + (LPGUID)&GUID_DEVINTERFACE_USB_HUB); +} + + +//***************************************************************************** +// +// GetHostControllerInfo() +// +// HANDLE hHCDev +// - handle to USB Host Controller +// +// PUSBHOSTCONTROLLERINFO hcInfo +// - data structure to receive the Power Map Info +// +// return DWORD dwError +// - return ERROR_SUCCESS or last error +// +//***************************************************************************** + +DWORD +GetHostControllerInfo( + HANDLE hHCDev, + PUSBHOSTCONTROLLERINFO hcInfo) +{ + USBUSER_CONTROLLER_INFO_0 UsbControllerInfo; + DWORD dwError = 0; + DWORD dwBytes = 0; + BOOL bSuccess = FALSE; + + memset(&UsbControllerInfo, 0, sizeof(UsbControllerInfo)); + + // set the header and request sizes + UsbControllerInfo.Header.UsbUserRequest = USBUSER_GET_CONTROLLER_INFO_0; + UsbControllerInfo.Header.RequestBufferLength = sizeof(UsbControllerInfo); + + // + // Query for the USB_CONTROLLER_INFO_0 structure + // + bSuccess = DeviceIoControl(hHCDev, + IOCTL_USB_USER_REQUEST, + &UsbControllerInfo, + sizeof(UsbControllerInfo), + &UsbControllerInfo, + sizeof(UsbControllerInfo), + &dwBytes, + NULL); + + if (!bSuccess) + { + dwError = GetLastError(); + OOPS(); + } + else + { + hcInfo->ControllerInfo = (PUSB_CONTROLLER_INFO_0) ALLOC(sizeof(USB_CONTROLLER_INFO_0)); + if(NULL == hcInfo->ControllerInfo) + { + dwError = GetLastError(); + OOPS(); + } + else + { + // copy the data into our USB Host Controller's info structure + memcpy(hcInfo->ControllerInfo, &UsbControllerInfo.Info0, sizeof(USB_CONTROLLER_INFO_0)); + } + } + return dwError; +} + +_Success_(return == TRUE) +BOOL +GetDeviceProperty( + _In_ HDEVINFO DeviceInfoSet, + _In_ PSP_DEVINFO_DATA DeviceInfoData, + _In_ DWORD Property, + _Outptr_ LPTSTR *ppBuffer + ) +{ + BOOL bResult; + DWORD requiredLength = 0; + DWORD lastError; + + if (ppBuffer == NULL) + { + return FALSE; + } + + *ppBuffer = NULL; + + bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet, + DeviceInfoData, + Property , + NULL, + NULL, + 0, + &requiredLength); + lastError = GetLastError(); + + if ((requiredLength == 0) || (bResult != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER)) + { + return FALSE; + } + + *ppBuffer = ALLOC(requiredLength); + + if (*ppBuffer == NULL) + { + return FALSE; + } + + bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet, + DeviceInfoData, + Property , + NULL, + (PBYTE) *ppBuffer, + requiredLength, + &requiredLength); + if(bResult == FALSE) + { + FREE(*ppBuffer); + *ppBuffer = NULL; + return FALSE; + } + + return TRUE; +} + + +void +EnumerateAllDevicesWithGuid( + PDEVICE_GUID_LIST DeviceList, + LPGUID Guid + ) +{ + if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE) + { + ClearDeviceList(DeviceList); + } + + DeviceList->DeviceInfo = SetupDiGetClassDevs(Guid, + NULL, + NULL, + (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); + + if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE) + { + ULONG index; + DWORD error; + + error = 0; + index = 0; + + while (error != ERROR_NO_MORE_ITEMS) + { + BOOL success; + PDEVICE_INFO_NODE pNode; + + pNode = ALLOC(sizeof(DEVICE_INFO_NODE)); + if (pNode == NULL) + { + OOPS(); + break; + } + pNode->DeviceInfo = DeviceList->DeviceInfo; + pNode->DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + pNode->DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + success = SetupDiEnumDeviceInfo(DeviceList->DeviceInfo, + index, + &pNode->DeviceInfoData); + + index++; + + if (success == FALSE) + { + error = GetLastError(); + + if (error != ERROR_NO_MORE_ITEMS) + { + OOPS(); + } + + FreeDeviceInfoNode(&pNode); + } + else + { + BOOL bResult; + ULONG requiredLength; + + bResult = GetDeviceProperty(DeviceList->DeviceInfo, + &pNode->DeviceInfoData, + SPDRP_DEVICEDESC, + &pNode->DeviceDescName); + if (bResult == FALSE) + { + FreeDeviceInfoNode(&pNode); + OOPS(); + break; + } + + bResult = GetDeviceProperty(DeviceList->DeviceInfo, + &pNode->DeviceInfoData, + SPDRP_DRIVER, + &pNode->DeviceDriverName); + if (bResult == FALSE) + { + FreeDeviceInfoNode(&pNode); + OOPS(); + break; + } + + pNode->DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + success = SetupDiEnumDeviceInterfaces(DeviceList->DeviceInfo, + 0, + Guid, + index-1, + &pNode->DeviceInterfaceData); + if (!success) + { + FreeDeviceInfoNode(&pNode); + OOPS(); + break; + } + + success = SetupDiGetDeviceInterfaceDetail(DeviceList->DeviceInfo, + &pNode->DeviceInterfaceData, + NULL, + 0, + &requiredLength, + NULL); + + error = GetLastError(); + + if (!success && error != ERROR_INSUFFICIENT_BUFFER) + { + FreeDeviceInfoNode(&pNode); + OOPS(); + break; + } + + pNode->DeviceDetailData = ALLOC(requiredLength); + + if (pNode->DeviceDetailData == NULL) + { + FreeDeviceInfoNode(&pNode); + OOPS(); + break; + } + + pNode->DeviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); + + success = SetupDiGetDeviceInterfaceDetail(DeviceList->DeviceInfo, + &pNode->DeviceInterfaceData, + pNode->DeviceDetailData, + requiredLength, + &requiredLength, + NULL); + if (!success) + { + FreeDeviceInfoNode(&pNode); + OOPS(); + break; + } + + InsertTailList(&DeviceList->ListHead, &pNode->ListEntry); + } + } + } +} + +DEVICE_POWER_STATE +AcquireDevicePowerState( + _Inout_ PDEVICE_INFO_NODE pNode + ) +{ + CM_POWER_DATA cmPowerData = {0}; + BOOL bResult; + + bResult = SetupDiGetDeviceRegistryProperty(pNode->DeviceInfo, + &pNode->DeviceInfoData, + SPDRP_DEVICE_POWER_DATA, + NULL, + (PBYTE)&cmPowerData, + sizeof(cmPowerData), + NULL); + + pNode->LatestDevicePowerState = bResult ? cmPowerData.PD_MostRecentPowerState : PowerDeviceUnspecified; + + return pNode->LatestDevicePowerState; +} + + +void +ClearDeviceList( + PDEVICE_GUID_LIST DeviceList + ) +{ + if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE) + { + SetupDiDestroyDeviceInfoList(DeviceList->DeviceInfo); + DeviceList->DeviceInfo = INVALID_HANDLE_VALUE; + } + + while (!IsListEmpty(&DeviceList->ListHead)) + { + PDEVICE_INFO_NODE pNode = NULL; + PLIST_ENTRY pEntry; + + pEntry = RemoveHeadList(&DeviceList->ListHead); + + pNode = CONTAINING_RECORD(pEntry, + DEVICE_INFO_NODE, + ListEntry); + + FreeDeviceInfoNode(&pNode); + } +} + +VOID +FreeDeviceInfoNode( + _In_ PDEVICE_INFO_NODE *ppNode + ) +{ + if (ppNode == NULL) + { + return; + } + + if (*ppNode == NULL) + { + return; + } + + if ((*ppNode)->DeviceDetailData != NULL) + { + FREE((*ppNode)->DeviceDetailData); + } + + if ((*ppNode)->DeviceDescName != NULL) + { + FREE((*ppNode)->DeviceDescName); + } + + if ((*ppNode)->DeviceDriverName != NULL) + { + FREE((*ppNode)->DeviceDriverName); + } + + FREE(*ppNode); + *ppNode = NULL; +} + +PDEVICE_INFO_NODE +FindMatchingDeviceNodeForDriverName( + _In_ PSTR DriverKeyName, + _In_ BOOLEAN IsHub + ) +{ + PDEVICE_INFO_NODE pNode = NULL; + PDEVICE_GUID_LIST pList = NULL; + PLIST_ENTRY pEntry = NULL; + + pList = IsHub ? &gHubList : &gDeviceList; + + pEntry = pList->ListHead.Flink; + + while (pEntry != &pList->ListHead) + { + pNode = CONTAINING_RECORD(pEntry, + DEVICE_INFO_NODE, + ListEntry); + if (_stricmp(DriverKeyName, pNode->DeviceDriverName) == 0) + { + return pNode; + } + + pEntry = pEntry->Flink; + } + + return NULL; +} + diff --git a/tests/projects/windows/winsdk/usbview/h264.c b/tests/projects/windows/winsdk/usbview/h264.c new file mode 100644 index 000000000..108a1d540 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/h264.c @@ -0,0 +1,750 @@ +//***************************************************************************** +// I N C L U D E S +//***************************************************************************** + +#include "uvcview.h" +#include "h264.h" + +#ifdef H264_SUPPORT + +//***************************************************************************** +// G L O B A L S +//***************************************************************************** +// H.264 format +UCHAR g_expectedNumberOfH264FrameDescriptors = 0; +UCHAR g_numberOfH264FrameDescriptors = 0; + +// MJPEG format +UCHAR g_expectedNumberOfMJPEGFrameDescriptors = 0; +UCHAR g_numberOfMJPEGFrameDescriptors = 0; + +// Uncompressed frame format +UCHAR g_expectedNumberOfUncompressedFrameFrameDescriptors = 0; +UCHAR g_numberOfUncompressedFrameFrameDescriptors = 0; + +//***************************************************************************** +// +// external function prototypes +// +//***************************************************************************** +extern VOID VDisplayBytes (PUCHAR Data, USHORT Len ); + +//***************************************************************************** +// +// H.264 video format descriptor string tables +// +//***************************************************************************** +STRINGLIST slSliceModes[]= +{ + {1, "Maximum number of Macroblocks per slice mode", ""}, + {2, "Target compressed size per slice mode", ""}, + {4, "Number of slices per frame mode", ""}, + {8, "Number of Macroblock rows per slice mode", ""}, + {0x10, "Reserved", ""}, + {0x20, "Reserved", ""}, + {0x40, "Reserved", ""}, + {0x80, "Reserved", ""}, +}; + + +STRINGLIST slSyncFrameTypes[]= +{ + {1, "Reset" , ""}, + {2, "IDR frame with SPS and PPS", ""}, + {4, "IDR frame (with SPS and PPS) that is a long-term reference frame", ""}, + {8, "Non-IDR random-access I frame (with SPS and PPS)", ""}, + {0x10, "Non-IDR random-access I frame (with SPS and PPS) that is a long-term reference frame", ""}, + {0x20, "P frame that is a long-term reference frame", ""}, + {0x40, "Gradual Decoder Refresh frames", ""}, + {0x80, "Reserved", ""}, +}; + + +//***************************************************************************** +// +// H.264 video frame rate descriptor string tables +// +//***************************************************************************** +STRINGLIST slUsage[]= +{ + {0x00000001, "Real-time/UCConfig mode 0", ""}, // 0 + {0x00000002, "Real-time/UCConfig mode 1", ""}, + {0x00000004, "Real-time/UCConfig mode 2Q" ""}, + {0x00000008, "Real-time/UCConfig mode 2S" ""}, + {0x00000010, "Real-time/UCConfig mode 3", ""}, + {0x00000020, "Reserved", ""}, + {0x00000040, "Reserved", ""}, + {0x00000080, "Reserved", ""}, + + {0x00000100, "Broadcast mode 0", ""}, // 8 + {0x00000200, "Broadcast mode 1", ""}, + {0x00000400, "Broadcast mode 2", ""}, + {0x00000800, "Broadcast mode 3", ""}, + {0x00001000, "Broadcast mode 4", ""}, + {0x00002000, "Broadcast mode 5", ""}, + {0x00004000, "Broadcast mode 6", ""}, + {0x00008000, "Broadcast mode 7", ""}, + + {0x00010000, "File Storage mode with I and P slices (e.g. IPPP)", ""}, // 16 + {0x00020000, "File Storage mode with I, P, and B slices (e.g. IB...BP)", ""}, // 17 + {0x00040000, "File storage all I frame mode", ""}, // 18 + {0x00080000, "Reserved", ""}, // 19 + {0x00100000, "Reserved", ""}, // 20 + {0x00200000, "Reserved", ""}, // 21 + {0x00400000, "Reserved", ""}, // 22 + {0x00800000, "Reserved", ""}, // 23 + + {0x01000000, "MVC Stereo High Mode", ""}, // 24 + {0x02000000, "MVC Multiview Mode", ""}, // 25 + {0x04000000, "Reserved", ""}, // 26 + {0x08000000, "Reserved", ""}, // 27 + {0x10000000, "Reserved", ""}, // 28 + {0x20000000, "Reserved", ""}, // 29 + {0x40000000, "Reserved", ""}, // 30 + {0x80000000, "Reserved", ""}, // 31 + + }; +STRINGLIST slCapabilities[]= +{ + {0x0001, "CAVLC only", ""}, + {0x0002, "CABAC only", ""}, + {0x0004, "Constant frame rate", ""}, + {0x0008, "Separate QP for luma/chroma", ""}, + {0x0010, "Separate QP for Cb/Cr", ""}, + {0x0020, "No picture reordering", ""}, + {0x0040, "Long-term reference frame", ""}, + {0x0080, "Reserved", ""}, + {0x0100, "Reserved", ""}, + {0x0200, "Reserved", ""}, + {0x0400, "Reserved", ""}, + {0x0800, "Reserved", ""}, + {0x1000, "Reserved", ""}, + {0x2000, "Reserved", ""}, + {0x4000, "Reserved", ""}, + {0x8000, "Reserved", ""}, + }; + + + +STRINGLIST slRateControlModes[]= +{ + {1, "Variable Bit Rate (VBR) with underflow allowed (H.264 low_delay_hrd_flag = 1)", ""}, + {2, "Constant Bit Rate (CBR) (H.264 low_delay_hrd_flag = 0)", ""}, + {4, "Constant QP", ""}, + {8, "Global VBR with underflow allowed (H.264 low_delay_hrd_flag = 1)", ""}, + {0x10, "VBR without underflow (H.264 low_delay_hrd_flag = 0)", ""}, + {0x20, "Global VBR without underflow (H.264 low_delay_hrd_flag = 0)", ""}, + {0x40, "Reserved", ""}, + {0x80, "Reserved", ""}, +}; + + +STRINGLIST slProfiles[]= +{ + {0x4200, "Baseline Profile", ""}, + {0x4240, "Constrained Baseline Profile", ""}, + {0x4D00, "Main Profile", ""}, + {0x5300, "Scalable Baseline Profile", ""}, + {0x5304, "Scalable Constrained Baseline Profile", ""}, + {0x5600, "Scalable High Profile", ""}, + {0x5604, "Scalable Constrained High Profile", ""}, + {0x6400, "High Profile", ""}, + {0x640C, "Constrained High Profile", ""}, + {0x7600, "Multiview High Profile", ""}, + {0x8000, "Stereo High Profile", ""}, + }; + +//***************************************************************************** +// +// H.264 video encoding unit descriptor string tables +// +//***************************************************************************** + +STRINGLIST slEncodingUnitControls[]= +{ + {0x000001, "Select Layer", ""}, // D0 + {0x000002, "Profile and Toolset", ""}, // D1 + {0x000004, "Video Resolution", ""}, // D2 + {0x000008, "Minimum Frame Interval", ""}, // D3 + {0x000010, "Slice Mode", ""}, // D4 + {0x000020, "Rate Control Mode", ""}, // D5 + {0x000040, "Average Bit Rate", ""}, // D6 + {0x000080, "CPB Size ", ""}, // D7 + {0x000100, "Peak Bit Rate", ""}, // D8 + {0x000200, "Quantization Parameter", ""}, // D9 + {0x000400, "Synchronization and Long-Term Reference Frame", ""}, // D10 + {0x000800, "Long-Term Buffer Size", ""}, // D11 + {0x001000, "Picture Long-Term Reference", ""}, // D12 + {0x002000, "Valid LTR", ""}, // D13 + {0x004000, "Level IDC", ""}, // D14 + {0x008000, "SEI Message", ""}, // D15 + {0x010000, "QP Range", ""}, // D16 + {0x020000, "Priority ID", ""}, // D17 + {0x040000, "Start or Stop Layer/View", ""}, // D18 + {0x080000, "Error Resiliency", ""}, // D19 + {0x100000, "Reserved", ""}, // D20 + {0x200000, "Reserved", ""}, // D21 + {0x400000, "Reserved", ""}, // D22 + {0x800000, "Reserved", ""}, // D23 + }; + +//***************************************************************************** +// +// commaPrintNumber() +// +//***************************************************************************** +char * commaPrintNumber( ULONG number ) +{ + static char comma = ','; + static char retbuf[30]; + int digitCount = 0; + + // null-terminate the string + char * pOutputString = &retbuf[ sizeof(retbuf)-1 ]; + *pOutputString = '\0'; + + do + { + // for every 3rd digit, add a comma to the output string + if ( ( digitCount%3 ) == 0 && ( digitCount != 0 ) ) + { + *--pOutputString = comma; + } + *--pOutputString = '0' + number % 10; + number /= 10; + digitCount++; + } + while( number != 0 ); + + return pOutputString; +} + +//***************************************************************************** +// +// DisplayBitmapData() +// +// Note that USB is always oriented Little Endian (least significant byte +// at the lowest address). +// +// Inputs: +// PUCHAR pData - pointer to least significant byte of the data +// UCHAR byteCount - number of bytes to print in the pData data buffer +// char * stringLabel - string label to print for user's to identify the data type +// +//***************************************************************************** +void DisplayBitmapData(_In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, _In_ char * stringLabel) +{ + UCHAR byteIndex; + UCHAR data; + UCHAR mask; + UCHAR bitIndex; + UCHAR checkBit = 0; // the bit we want to print + + // print the label and all the bytes on the first line + AppendTextBuffer("%s : ", stringLabel); + VDisplayBytes( pData, byteCount ); + + for ( byteIndex = 0; byteIndex < byteCount; byteIndex++ ) + { + data = pData[ byteIndex ]; + checkBit = 0; // the control bit value we are going to print + for ( mask = 1, bitIndex = 0; bitIndex < 8; bitIndex++ ) + { + checkBit = data & mask; + AppendTextBuffer(" D%02d = %d %s\r\n", + bitIndex + 8 * byteIndex, // increment bit count + checkBit ? 1 : 0, + checkBit ? "yes" : " no"); + mask = mask << 1; + } + + } +} + +//***************************************************************************** +// +// DisplayBitmapDataWithStrings() +// +// Note that USB is always oriented Little Endian (least significant byte +// at the lowest address). +// +// This calls GetSTringFromList() to insert a string that corresonds to +// the bit value being print. +// +// Inputs: +// PUCHAR pData - pointer to least significant byte of the data +// UCHAR byteCount - number of bytes to print in the pData data buffer +// char * stringLabel - string label to print for user's to identify the data type +// STRINGLIST stringList - string table in which to look up bitmap strings +// ULONG numEntriesInTable - number of entrys (strings) in the table +//***************************************************************************** +void DisplayBitmapDataWithStrings( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, + _In_ char * stringLabel, _In_ PSTRINGLIST stringList, + ULONG numEntriesInTable) +{ + + UCHAR byteIndex; + UCHAR data; + UCHAR byteMask; + ULONGLONG stringMask; + UCHAR bitIndex; + UCHAR checkBit = 0; // the bit we want to print + + // print the label and all the bytes on the first line + AppendTextBuffer("%s : ", stringLabel); + VDisplayBytes( pData, byteCount ); + + for ( stringMask = 1, byteIndex = 0; byteIndex < byteCount; byteIndex++ ) + { + data = pData[ byteIndex ]; + checkBit = 0; // the control bit value we are going to print + for ( byteMask = 1, bitIndex = 0; bitIndex < 8; bitIndex++ ) + { + checkBit = data & byteMask; + AppendTextBuffer(" D%02d = %d %s %s\r\n", + bitIndex + 8 * byteIndex, // increment bit count + checkBit ? 1 : 0, + checkBit ? "yes - " : " no - ", + GetStringFromList(stringList, + numEntriesInTable, + stringMask, + "Reserved")); + + byteMask = byteMask << 1; + stringMask = stringMask << 1; + } + + } +} + +//***************************************************************************** +// +// DisplayVCH264Format() +// +//***************************************************************************** +BOOL DisplayVCH264Format( _In_reads_(sizeof(VIDEO_FORMAT_H264)) PVIDEO_FORMAT_H264 H264FormatDesc ) +{ + if ( H264FormatDesc->bSimulcastSupport == 0 ) + { + AppendTextBuffer("\r\n ===>Video Streaming H.264 Format Type Descriptor<===\r\n"); + } + else + { + AppendTextBuffer("\r\n ===>Video Streaming H.264 Simulcast Format Type Descriptor<===\r\n"); + } + AppendTextBuffer("bLength: 0x%02X = %d\r\n", H264FormatDesc->bLength, H264FormatDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X \r\n", H264FormatDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X \r\n", H264FormatDesc->bDescriptorSubtype); + AppendTextBuffer("bFormatIndex: 0x%02X = %d\r\n", H264FormatDesc->bFormatIndex, H264FormatDesc->bFormatIndex); + AppendTextBuffer("bNumFrameDescriptors: 0x%02X = %d\r\n", H264FormatDesc->bNumFrameDescriptors, H264FormatDesc->bNumFrameDescriptors); + AppendTextBuffer("bDefaultFrameIndex: 0x%02X = %d\r\n", H264FormatDesc->bDefaultFrameIndex, H264FormatDesc->bDefaultFrameIndex); + AppendTextBuffer("bMaxCodecConfigDelay: 0x%02X = %d frames\r\n", H264FormatDesc->bMaxCodecConfigDelay, H264FormatDesc->bMaxCodecConfigDelay); + DisplayBitmapDataWithStrings( H264FormatDesc->bmSupportedSliceModes, sizeof(H264FormatDesc->bmSupportedSliceModes), "bmSupportedSliceModes", slSliceModes, sizeof(slSliceModes)/sizeof(STRINGLIST) ); + DisplayBitmapDataWithStrings( H264FormatDesc->bmSupportedSyncFrameTypes, sizeof(H264FormatDesc->bmSupportedSyncFrameTypes), "bmSupportedSyncFrameTypes", slSyncFrameTypes, sizeof(slSyncFrameTypes)/sizeof(STRINGLIST) ); + + // handle bResolutionScaling + if ( H264FormatDesc->bResolutionScaling == 0 ) + { + AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Not Supported\r\n", + H264FormatDesc->bResolutionScaling, + H264FormatDesc->bResolutionScaling ); + } + else if ( H264FormatDesc->bResolutionScaling == 1 ) + { + AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Limited to 1.5 or 2.0 scaling in both directions, while maintaining the aspect ratio.\r\n", + H264FormatDesc->bResolutionScaling, + H264FormatDesc->bResolutionScaling ); + } + else if ( H264FormatDesc->bResolutionScaling == 2 ) + { + AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Limited to 1.0, 1.5 or 2.0 scaling in either direction.\r\n", + H264FormatDesc->bResolutionScaling, + H264FormatDesc->bResolutionScaling ); + } + else if ( H264FormatDesc->bResolutionScaling == 3 ) + { + AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Limited to resolutions reported by the associated Frame Descriptors\r\n", + H264FormatDesc->bResolutionScaling, + H264FormatDesc->bResolutionScaling ); + } + else if ( H264FormatDesc->bResolutionScaling == 4 ) + { + AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Arbitrary scaling\r\n", + H264FormatDesc->bResolutionScaling, + H264FormatDesc->bResolutionScaling ); + } + else // 5 ... 255 + { + AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Reserved \r\n", + H264FormatDesc->bResolutionScaling, + H264FormatDesc->bResolutionScaling ); + } + + // handle bSimulcastSupport + if ( H264FormatDesc->bSimulcastSupport == 0 ) + { + AppendTextBuffer("bSimulcastSupport: 0x%02X = %d, one stream\r\n", + H264FormatDesc->bSimulcastSupport, + H264FormatDesc->bSimulcastSupport ); + } + else if ( H264FormatDesc->bSimulcastSupport == 1 ) + { + AppendTextBuffer("bSimulcastSupport: 0x%02X = %d, multiple streams\r\n", + H264FormatDesc->bSimulcastSupport, + H264FormatDesc->bSimulcastSupport ); + } + else // ( H264FormatDesc->bSimulcastSupport > 1 ) + { + AppendTextBuffer("bSimulcastSupport: 0x%02X = %d *!*ERROR: unknown bSimulcastSupport \r\n", + H264FormatDesc->bSimulcastSupport, + H264FormatDesc->bSimulcastSupport, + H264FormatDesc->bSimulcastSupport ); + } + + + DisplayBitmapDataWithStrings( &(H264FormatDesc->bmSupportedRateControlModes), sizeof(H264FormatDesc->bmSupportedRateControlModes), "bmSupportedRateControlModes", slRateControlModes, sizeof(slRateControlModes)/sizeof(STRINGLIST) ); + + // Note that USB is Little Endian according to the UVC 2.0 spec + + + // Resolutions with no scalability + AppendTextBuffer("wMaxMBperSecOneResolutionNoScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecOneResolutionNoScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionNoScalability) ); + + AppendTextBuffer("wMaxMBperSecTwoResolutionsNoScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecTwoResolutionsNoScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsNoScalability) ); + + AppendTextBuffer("wMaxMBperSecThreeResolutionsNoScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecThreeResolutionsNoScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsNoScalability) ); + + AppendTextBuffer("wMaxMBperSecFourResolutionsNoScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecFourResolutionsNoScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsNoScalability) ); + + // Resolutions with temporal scalability + AppendTextBuffer("wMaxMBperSecOneResolutionTemporalScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecOneResolutionTemporalScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalScalability) ); + + AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalScalability) ); + + AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalScalability) ); + + AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecFourResolutionsTemporalScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalScalability) ); + + // Resolutions with temporal and quality scalability + AppendTextBuffer("wMaxMBperSecOneResolutionTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecOneResolutionTemporalQualityScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalQualityScalability) ); + + AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalQualityScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalQualityScalability) ); + + + AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalQualityScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalQualityScalability) ); + + AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecFourResolutionsTemporalQualityScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalQualityScalability) ); + + // Resolutions with temporal and spatial scalability + AppendTextBuffer("wMaxMBperSecOneResolutionTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecOneResolutionTemporalSpatialScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalSpatialScalability) ); + + AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalSpatialScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalSpatialScalability) ); + + + AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalSpatialScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalSpatialScalability) ); + + AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecFourResolutionsTemporalSpatialScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalSpatialScalability) ); + + // Resolutions with full scalability + AppendTextBuffer("wMaxMBperSecOneResolutionFullScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecOneResolutionFullScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionFullScalability) ); + + AppendTextBuffer("wMaxMBperSecTwoResolutionsFullScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecTwoResolutionsFullScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsFullScalability) ); + + AppendTextBuffer("wMaxMBperSecThreeResolutionsFullScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecThreeResolutionsFullScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsFullScalability) ); + + AppendTextBuffer("wMaxMBperSecFourResolutionsFullScalability: 0x%04X (%s MB/sec)\r\n", + H264FormatDesc->wMaxMBperSecFourResolutionsFullScalability, + commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsFullScalability) ); + + + return TRUE; +} + +//***************************************************************************** +// +// DisplayVCH264FrameType() +// +//***************************************************************************** +BOOL DisplayVCH264FrameType( _In_reads_(sizeof(VIDEO_FRAME_H264)) PVIDEO_FRAME_H264 H264FrameDesc ) +{ + + ULONG frameIntervalIndex; + ULONG value; + ULONG i; + + AppendTextBuffer("\r\n ===>Video Streaming H.264 Frame Type Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X = %d\r\n", H264FrameDesc->bLength, H264FrameDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X \r\n", H264FrameDesc->bDescriptorType); + AppendTextBuffer("bDescriptorSubtype: 0x%02X \r\n", H264FrameDesc->bDescriptorSubtype); + AppendTextBuffer("bFrameIndex: 0x%02X = %d\r\n", H264FrameDesc->bFrameIndex, H264FrameDesc->bFrameIndex); + AppendTextBuffer("wWidth: 0x%04X = %d\r\n", H264FrameDesc->wWidth, H264FrameDesc->wWidth); + AppendTextBuffer("wHeight: 0x%04X = %d\r\n", H264FrameDesc->wHeight, H264FrameDesc->wHeight); + AppendTextBuffer("wSARwidth: 0x%04X = %d\r\n", H264FrameDesc->wSARwidth, H264FrameDesc->wSARwidth); + AppendTextBuffer("wSARheight: 0x%04X = %d\r\n", H264FrameDesc->wSARheight, H264FrameDesc->wSARheight); + AppendTextBuffer("wProfile: 0x%04X - %s\r\n", H264FrameDesc->wProfile, + GetStringFromList( slProfiles, // string table + sizeof(slProfiles)/sizeof(STRINGLIST), // number of strings in the table + H264FrameDesc->wProfile, // index of string we want to look up in the string table + "Unknown profile" ) ); // string to use if the lookup fails + + AppendTextBuffer("bLevelIDC: 0x%02X = %d = Level %01.01lf \r\n", + H264FrameDesc->bLevelIDC, H264FrameDesc->bLevelIDC, H264FrameDesc->bLevelIDC/10.0 ); + + AppendTextBuffer("wConstrainedToolset: 0x%04X %s\r\n", H264FrameDesc->wConstrainedToolset, + ((H264FrameDesc->wConstrainedToolset == 0) ? "- Reserved" : "*!*ERROR: field is reserved and should be zero")); + + DisplayBitmapDataWithStrings( H264FrameDesc->bmSupportedUsages, sizeof(H264FrameDesc->bmSupportedUsages), "bmSupportedUsages", slUsage, sizeof(slUsage)/sizeof(STRINGLIST) ); + DisplayBitmapDataWithStrings( H264FrameDesc->bmCapabilities, sizeof(H264FrameDesc->bmCapabilities), "bmCapabilities", slCapabilities, sizeof(slCapabilities)/sizeof(STRINGLIST) ); + + + // bmSVCCapabilities[4] + AppendTextBuffer("%s : ", "bmSVCCapabilities"); + VDisplayBytes( &(H264FrameDesc->bmSVCCapabilities[0]), sizeof(H264FrameDesc->bmSVCCapabilities) ); + AppendTextBuffer(" D2..D0 = %d Maximum number of temporal layers = %d\r\n", + H264FrameDesc->bmSVCCapabilities[0] & 0x7, + (H264FrameDesc->bmSVCCapabilities[0] & 0x7) + 1 ); + AppendTextBuffer(" D3 = %d %s - Rewrite Support\r\n", (H264FrameDesc->bmSVCCapabilities[0] & 0x8) >> 3, + ((H264FrameDesc->bmSVCCapabilities[0] & 0x8) >> 3) ? "yes" : " no" ); + AppendTextBuffer(" D6..D4 = %d Maximum number of CGS layers = %d\r\n", + (H264FrameDesc->bmSVCCapabilities[0] & 0x70) >> 4, + ((H264FrameDesc->bmSVCCapabilities[0] & 0x70) >> 4) + 1 ); + + value = ( H264FrameDesc->bmSVCCapabilities[1] << 8 ) | H264FrameDesc->bmSVCCapabilities[0]; + value >>= 7; // shift bit 7 right so that it ends up in the lsb of value + value &= 0x7; + AppendTextBuffer(" D9..D7 = %d Number of MGS sublayers\r\n", value ); + + AppendTextBuffer(" D10 = %d %s - Additional SNR scalability support in spatial enhancement layers\r\n", + (H264FrameDesc->bmSVCCapabilities[1] & 0x4) >> 2, + ((H264FrameDesc->bmSVCCapabilities[1] & 0x4) >> 2) ? "yes" : " no"); + AppendTextBuffer(" D13..D11 = %d Maximum number of spatial layers = %d\r\n", + (H264FrameDesc->bmSVCCapabilities[1] & 0x38) >> 3, + ((H264FrameDesc->bmSVCCapabilities[1] & 0x38) >> 3) + 1 ); + + value = ( H264FrameDesc->bmSVCCapabilities[3] << 16 ) | ( H264FrameDesc->bmSVCCapabilities[2] << 8 ) | H264FrameDesc->bmSVCCapabilities[1]; + value >>= 6; // get bit 14 at LSB + for ( i = 0; i < 18; i++ ) // bits 31...14 + { + AppendTextBuffer(" D%02d = %d %s - Reserved \r\n", 14 + i, value & 0x1, (value & 0x1) ? "yes" : " no" ); + value >>= 1; + } + + // bmMVCCapabilities[4] + AppendTextBuffer("%s : ", "bmMVCCapabilities"); + VDisplayBytes( &(H264FrameDesc->bmMVCCapabilities[0]), sizeof(H264FrameDesc->bmMVCCapabilities) ); + AppendTextBuffer(" D2..D0 = %d Maximum number of temporal layers = %d\r\n", + H264FrameDesc->bmMVCCapabilities[0] & 0x7, + ((H264FrameDesc->bmMVCCapabilities[0] & 0x7) + 1) ); + + value = (H264FrameDesc->bmMVCCapabilities[1] << 8) | H264FrameDesc->bmMVCCapabilities[0]; + value >>= 3; // shift bit 3 right so that it ends up in the lsb of value + value &= 0xff; + AppendTextBuffer(" D10..D3 = %d Maximum number of view components = %d\r\n", + value, value + 1); + + value = ( (H264FrameDesc->bmMVCCapabilities[3] << 16) | (H264FrameDesc->bmMVCCapabilities[2] << 8) | H264FrameDesc->bmMVCCapabilities[1] ); + value >>= 3; // shift bit 11 right so that it ends up in the lsb of value + for ( i = 0; i < 21; i++ ) // bits 31...11 + { + AppendTextBuffer(" D%02d = %d %s - Reserved \r\n", 11 + i, value & 0x1, (value & 0x1) ? "yes" : " no" ); + value >>= 1; + } + + + AppendTextBuffer("dwMinBitRate: 0x%08X = %s bps\r\n", H264FrameDesc->dwMinBitRate, commaPrintNumber(H264FrameDesc->dwMinBitRate)); + AppendTextBuffer("dwMaxBitRate: 0x%08X = %s bps\r\n", H264FrameDesc->dwMaxBitRate, commaPrintNumber(H264FrameDesc->dwMaxBitRate)); + + // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz) \r\n", + H264FrameDesc->dwDefaultFrameInterval, ((double)H264FrameDesc->dwDefaultFrameInterval)/10000.0, (10000000.0/((double)H264FrameDesc->dwDefaultFrameInterval))); + AppendTextBuffer("bNumFrameIntervals: 0x%02X = %d\r\n", H264FrameDesc->bNumFrameIntervals, H264FrameDesc->bNumFrameIntervals); + + + // frame interval 100 ns units. + + //To convert the frame interval to seconds we would divide by 10,000,000. + // 100 ns = 10^(-7) seconds = 1/10,000,000 + + // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse + + // To convert the frame interval to milliseconds, we divide by 10,000. + // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds + // = 1/10,000 milliseconds + + for ( frameIntervalIndex = 0; frameIntervalIndex < H264FrameDesc->bNumFrameIntervals; frameIntervalIndex++ ) + { + value = (ULONG)H264FrameDesc->dwFrameInterval[ frameIntervalIndex ]; + AppendTextBuffer("dwFrameInterval[%d]: 0x%08x = %lf mSec (%4.2f Hz)\r\n", frameIntervalIndex, value, ((double)value)/10000.0, (10000000.0/((double)value)) ); + + } + + return TRUE; +} + + +//***************************************************************************** +// +// DisplayVCH264EncodingUnit() +// +//***************************************************************************** +BOOL DisplayVCH264EncodingUnit( + _In_reads_(sizeof(VIDEO_ENCODING_UNIT)) PVIDEO_ENCODING_UNIT VidEncodingDesc + ) +{ + + PUCHAR pControlsRunTimeData = NULL; + + AppendTextBuffer("\r\n ===>Video Control Encoding Unit Descriptor<===\r\n"); + AppendTextBuffer("bLength: 0x%02X = %d\r\n", VidEncodingDesc->bLength, VidEncodingDesc->bLength); + AppendTextBuffer("bDescriptorType: 0x%02X \r\n", VidEncodingDesc->bDescriptorType ); + AppendTextBuffer("bDescriptorSubtype: 0x%02X \r\n", VidEncodingDesc->bDescriptorSubtype ); + AppendTextBuffer("bUnitID: 0x%02X = %d\r\n", VidEncodingDesc->bUnitID, VidEncodingDesc->bUnitID); + AppendTextBuffer("bSourceID: 0x%02X = %d\r\n", VidEncodingDesc->bSourceID, VidEncodingDesc->bSourceID); + AppendTextBuffer("iEncoding: 0x%02X = %d\r\n", VidEncodingDesc->iEncoding, VidEncodingDesc->iEncoding); + AppendTextBuffer("bControlSize: 0x%02X = %d\r\n", VidEncodingDesc->bControlSize, VidEncodingDesc->bControlSize); + + if ( VidEncodingDesc->bControlSize > 0) + { + // Encoding Unit Descriptor bmControls field + DisplayBitmapDataWithStrings( VidEncodingDesc->bmControls, VidEncodingDesc->bControlSize /* print bControlSize bytes worth of bitmap info */, + "bmControls", slEncodingUnitControls, sizeof(slEncodingUnitControls)/sizeof(STRINGLIST) ); + + // Encoding Unit Descriptor bmControlsRuntime field + pControlsRunTimeData = ((UCHAR *)(&VidEncodingDesc->bmControls)) + VidEncodingDesc->bControlSize; + DisplayBitmapDataWithStrings( pControlsRunTimeData, VidEncodingDesc->bControlSize /* print bControlSize bytes worth of bitmap info */, + "bmControlsRuntime", slEncodingUnitControls, sizeof(slEncodingUnitControls)/sizeof(STRINGLIST) ); + } + return TRUE; +} + +//***************************************************************************** +// +// DoAdditionalErrorChecks() +// +// Currently this function only checks to see that the number of frame +// descriptors actually found equals the number specified in the corresponding +// format descriptor. +// +// Because this potentially involves parsing multiple frame descriptors, we +// call this routine after the video descriptor has been parsed and displayed. +// +//***************************************************************************** +void DoAdditionalErrorChecks() +{ + if( g_expectedNumberOfH264FrameDescriptors > 0 || g_numberOfH264FrameDescriptors > 0 + || g_expectedNumberOfUncompressedFrameFrameDescriptors > 0 || g_numberOfUncompressedFrameFrameDescriptors > 0 + || g_expectedNumberOfMJPEGFrameDescriptors > 0 || g_numberOfMJPEGFrameDescriptors > 0) + { + AppendTextBuffer("\r\n ===>Additional Error Checking<===\r\n"); + + // H.264 frame descriptor + if( g_expectedNumberOfH264FrameDescriptors > 0 || g_numberOfH264FrameDescriptors > 0) + { + if ( g_expectedNumberOfH264FrameDescriptors == g_numberOfH264FrameDescriptors ) + { + AppendTextBuffer("PASS: number of H.264 frame descriptors (%d) == number of frame descriptors (%d) specified in H.264 format descriptor(s)\r\n", + g_expectedNumberOfH264FrameDescriptors, g_numberOfH264FrameDescriptors ); + } + else + { + AppendTextBuffer("FAIL: number of H.264 frame descriptors (%d) != number of frame descriptors (%d) specified in H.264 format descriptor(s)\r\n", + g_expectedNumberOfH264FrameDescriptors, g_numberOfH264FrameDescriptors ); + } + } + + // uncompressed frame descriptor + if( g_expectedNumberOfUncompressedFrameFrameDescriptors > 0 || g_numberOfUncompressedFrameFrameDescriptors > 0) + { + + if ( g_expectedNumberOfUncompressedFrameFrameDescriptors == g_numberOfUncompressedFrameFrameDescriptors ) + { + AppendTextBuffer("PASS: number of uncompressed-frame frame descriptors (%d) == number of frame descriptors (%d) specified in uncompressed format descriptor(s)\r\n", + g_expectedNumberOfUncompressedFrameFrameDescriptors, g_numberOfUncompressedFrameFrameDescriptors ); + } + else + { + AppendTextBuffer("FAIL: number of uncompressed-frame frame descriptors (%d) != number of frame descriptors (%d) specified in uncompressed format descriptor(s)\r\n", + g_expectedNumberOfUncompressedFrameFrameDescriptors, g_numberOfUncompressedFrameFrameDescriptors ); + } + } + + // MJPEG frame descriptor + if( g_expectedNumberOfMJPEGFrameDescriptors > 0 || g_numberOfMJPEGFrameDescriptors > 0) + { + if ( g_expectedNumberOfMJPEGFrameDescriptors == g_numberOfMJPEGFrameDescriptors ) + { + AppendTextBuffer("PASS: number of MJPEG frame descriptors (%d) == number of frame descriptors (%d) specified in MJPEG format descriptor(s)\r\n", + g_expectedNumberOfMJPEGFrameDescriptors, g_numberOfMJPEGFrameDescriptors ); + } + else + { + AppendTextBuffer("FAIL: number of MJPEG frame descriptors (%d) != number of frame descriptors (%d) specified in MJPEG format descriptor(s)\r\n", + g_expectedNumberOfMJPEGFrameDescriptors, g_numberOfMJPEGFrameDescriptors ); + } + } + } +} + +//***************************************************************************** +// +// ResetErrorCounts() +// +//***************************************************************************** +void ResetErrorCounts() +{ + + // H.264 format + g_expectedNumberOfH264FrameDescriptors = 0; + g_numberOfH264FrameDescriptors = 0; + + // MJPEG format + g_expectedNumberOfMJPEGFrameDescriptors = 0; + g_numberOfMJPEGFrameDescriptors = 0; + + // Uncompressed frame format + g_expectedNumberOfUncompressedFrameFrameDescriptors = 0; + g_numberOfUncompressedFrameFrameDescriptors = 0; +} + +#endif //H264_SUPPORT diff --git a/tests/projects/windows/winsdk/usbview/h264.h b/tests/projects/windows/winsdk/usbview/h264.h new file mode 100644 index 000000000..841318922 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/h264.h @@ -0,0 +1,164 @@ +#pragma once + +#ifdef H264_SUPPORT + +//***************************************************************************** +// +// external variables +// +//***************************************************************************** +extern UCHAR g_expectedNumberOfH264FrameDescriptors; +extern UCHAR g_numberOfH264FrameDescriptors; + +extern UCHAR g_expectedNumberOfMJPEGFrameDescriptors; +extern UCHAR g_numberOfMJPEGFrameDescriptors; + +extern UCHAR g_expectedNumberOfUncompressedFrameFrameDescriptors; +extern UCHAR g_numberOfUncompressedFrameFrameDescriptors; + +#endif + + + +//***************************************************************************** +// +// defines +// +//***************************************************************************** + +//Version information printed at lower left of UI Window and top of output text window +#define USBVIEW_MAJOR_VERSION 2 +#define USBVIEW_MINOR_VERSION 0 +#define UVC_SPEC_MAJOR_VERSION 1 +#define UVC_SPEC_MINOR_VERSION 5 + + +// definitions take from the proposed UVC 1.5 spec +#define VS_FORMAT_H264 0x13 +#define VS_FRAME_H264 0x14 + + +// Video Class-Specific VC Interface Descriptor Subtypes +// Note, this needs to be added to the list already in C:\nt\sdpublic\internal\drivers\inc\uvcdesc.h +// Also, note that MAX_TYPE_UNIT needs to be bumped up by 1 to account for this new subtype.. +#define H264_ENCODING_UNIT 7 + +//***************************************************************************** +// +// struct definitions +// +//***************************************************************************** + +// VideoStreaming H.264 Format Descriptor +#pragma pack(push, 1) // pack on a 1 byte boundary +typedef struct _VIDEO_FORMAT_H264 +{ // offset (in bytes): + UCHAR bLength; // 0 + UCHAR bDescriptorType; // 1 + UCHAR bDescriptorSubtype; // 2 + UCHAR bFormatIndex; // 3 + UCHAR bNumFrameDescriptors; // 4 + UCHAR bDefaultFrameIndex; // 5 + UCHAR bMaxCodecConfigDelay; // 6 + UCHAR bmSupportedSliceModes[1]; // 7 + UCHAR bmSupportedSyncFrameTypes[1]; // 8 + UCHAR bResolutionScaling; // 9 + UCHAR bSimulcastSupport; // 10 + UCHAR bmSupportedRateControlModes; // 11 + + USHORT wMaxMBperSecOneResolutionNoScalability; // 12 + USHORT wMaxMBperSecTwoResolutionsNoScalability; // 14 + USHORT wMaxMBperSecThreeResolutionsNoScalability; // 16 + USHORT wMaxMBperSecFourResolutionsNoScalability; // 18 + + USHORT wMaxMBperSecOneResolutionTemporalScalability; // 20 + USHORT wMaxMBperSecTwoResolutionsTemporalScalability; // 22 + USHORT wMaxMBperSecThreeResolutionsTemporalScalability; // 24 + USHORT wMaxMBperSecFourResolutionsTemporalScalability; // 26 + + USHORT wMaxMBperSecOneResolutionTemporalQualityScalability; // 28 + USHORT wMaxMBperSecTwoResolutionsTemporalQualityScalability; // 30 + USHORT wMaxMBperSecThreeResolutionsTemporalQualityScalability; // 32 + USHORT wMaxMBperSecFourResolutionsTemporalQualityScalability; // 34 + + USHORT wMaxMBperSecOneResolutionTemporalSpatialScalability; // 36 + USHORT wMaxMBperSecTwoResolutionsTemporalSpatialScalability; // 38 + USHORT wMaxMBperSecThreeResolutionsTemporalSpatialScalability; // 40 + USHORT wMaxMBperSecFourResolutionsTemporalSpatialScalability; // 42 + + USHORT wMaxMBperSecOneResolutionFullScalability; // 44 + USHORT wMaxMBperSecTwoResolutionsFullScalability; // 46 + USHORT wMaxMBperSecThreeResolutionsFullScalability; // 48 + USHORT wMaxMBperSecFourResolutionsFullScalability; // 50 +} VIDEO_FORMAT_H264, *PVIDEO_FORMAT_H264; +#pragma pack(pop) + + +// VideoStreaming H.264 Frame Descriptor +#pragma pack(push, 1) // pack on a 1 byte boundary + +// Disable warning on zero sized array in CPP compiler +#pragma warning(push) +#pragma warning(disable:4200) // Zero sized array + +typedef struct _VIDEO_FRAME_H264 +{ // offset (in bytes): + UCHAR bLength; // 0 + UCHAR bDescriptorType; // 1 + UCHAR bDescriptorSubtype; // 2 + UCHAR bFrameIndex; // 3 + USHORT wWidth; // 4 + USHORT wHeight; // 6 + USHORT wSARwidth; // 8 + USHORT wSARheight; // 10 + USHORT wProfile; // 12 + UCHAR bLevelIDC; // 14 + USHORT wConstrainedToolset; // 15 + UCHAR bmSupportedUsages[4]; // 17 + UCHAR bmCapabilities[2]; // 21 + UCHAR bmSVCCapabilities[4]; // 23 + UCHAR bmMVCCapabilities[4]; // 27 + ULONG dwMinBitRate; // 31 + ULONG dwMaxBitRate; // 35 + ULONG dwDefaultFrameInterval; // 39 + UCHAR bNumFrameIntervals; // 43 + ULONG dwFrameInterval[]; // 44 variable-length parameter +} VIDEO_FRAME_H264, *PVIDEO_FRAME_H264; +#pragma warning(pop) +#pragma pack(pop) + + +// VideoControl Encoding Unit Descriptor +#pragma pack(push, 1) // pack on a 1 byte boundary +#pragma warning(push) +#pragma warning(disable:4200) // Zero sized array +typedef struct //_VIDEO_ENCODING_UNIT +{ // offset (in bytes): + UCHAR bLength; // 0 + UCHAR bDescriptorType; // 1 + UCHAR bDescriptorSubtype; // 2 + UCHAR bUnitID; // 3 + UCHAR bSourceID; // 4 + UCHAR iEncoding; // 5 + UCHAR bControlSize; // 6 + UCHAR bmControls[]; // 7 - variable-length parameter (bControlSize specifies the size) +} VIDEO_ENCODING_UNIT, *PVIDEO_ENCODING_UNIT; +// after bmControls[] there is also the variable-length parameter (bControlSize specifies the size: +// UCHAR bmControlsRunTime[] +#pragma warning(pop) +#pragma pack(pop) + + + +//***************************************************************************** +// +// function prototypes +// +//***************************************************************************** +BOOL DisplayVCH264Format( _In_reads_(sizeof(VIDEO_FORMAT_H264)) PVIDEO_FORMAT_H264 H264FormatDesc ); +BOOL DisplayVCH264FrameType( _In_reads_(sizeof(VIDEO_FRAME_H264)) PVIDEO_FRAME_H264 H264FrameDesc ); +BOOL DisplayVCH264EncodingUnit( _In_reads_(sizeof(VIDEO_ENCODING_UNIT)) PVIDEO_ENCODING_UNIT VidEncodingDesc ); +void DisplayBitmapData( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, _In_ char * stringLabel); +void DisplayBitmapDataWithStrings( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, _In_ char * stringLabel, _In_ PSTRINGLIST stringList, ULONG numEntriesInTable ); +void DoAdditionalErrorChecks(); +void ResetErrorCounts(); diff --git a/tests/projects/windows/winsdk/usbview/hub.ico b/tests/projects/windows/winsdk/usbview/hub.ico new file mode 100644 index 000000000..d0620df89 Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/hub.ico differ diff --git a/tests/projects/windows/winsdk/usbview/langidlist.h b/tests/projects/windows/winsdk/usbview/langidlist.h new file mode 100644 index 000000000..0f2d90621 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/langidlist.h @@ -0,0 +1,206 @@ +/*++ + +Copyright (c) 2003-2008 Microsoft Corporation + +Module Name: + + LANGIDLIST.H + +Abstract: + + This file LANGIDLIST.H contains content from USB.org, and was reviewed + by LCA in June 2011. Per discussion with USB consortium counsel their + material is "free to any use". + + This header file contains a list of all currently known USB Language IDs + and the language name associated with each Language ID. + + + +Source: + http://www.usb.org + +Environment: + + Kernel & user mode + +Revision History: + + 03-28-03 : created + +--*/ + +#ifndef __LANGIDLIST_H__ +#define __LANGIDLIST_H__ + +// +// Language ID structure +// +typedef struct { + USHORT usLangID; + PCHAR szLanguage; +} USBLANGID, *PUSBLANGID; + +// +// This list built from information obtained on Nov-30-2000 from +// http://www.usb.org +// +// This information has not been independently verified and no claims +// are made here as to its accuracy. +// + +USBLANGID USBLangIDs[] = +{ + {1078 , /* 0x0436 */ "Afrikaans"}, + {1052 , /* 0x041c */ "Albanian"}, + {1025 , /* 0x0401 */ "Arabic (Saudi Arabia)"}, + {2049 , /* 0x0801 */ "Arabic (Iraq)"}, + {3073 , /* 0x0c01 */ "Arabic (Egypt)"}, + {4097 , /* 0x1001 */ "Arabic (Libya)"}, + {5121 , /* 0x1401 */ "Arabic (Algeria)"}, + {6145 , /* 0x1801 */ "Arabic (Morocco)"}, + {7169 , /* 0x1c01 */ "Arabic (Tunisia)"}, + {8193 , /* 0x2001 */ "Arabic (Oman)"}, + {9217 , /* 0x2401 */ "Arabic (Yemen)"}, + {10241 , /* 0x2801 */ "Arabic (Syria)"}, + {11265 , /* 0x2c01 */ "Arabic (Jordan)"}, + {12289 , /* 0x3001 */ "Arabic (Lebanon)"}, + {13313 , /* 0x3401 */ "Arabic (Kuwait)"}, + {14337 , /* 0x3801 */ "Arabic (U.A.E.)"}, + {15361 , /* 0x3c01 */ "Arabic (Bahrain)"}, + {16385 , /* 0x4001 */ "Arabic (Qatar) "}, + {1067 , /* 0x042b */ "Armenian"}, + {1101 , /* 0x044d */ "Assamese"}, + {1068 , /* 0x042c */ "Azeri (Latin)"}, + {2092 , /* 0x082c */ "Azeri (Cyrillic)"}, + {1069 , /* 0x042d */ "Basque"}, + {1059 , /* 0x0423 */ "Belarussian"}, + {1093 , /* 0x0445 */ "Bengali"}, + {1026 , /* 0x0402 */ "Bulgarian"}, + {1109 , /* 0x0455 */ "Burmese"}, + {1027 , /* 0x0403 */ "Catalan"}, + {1028 , /* 0x0404 */ "Chinese (Taiwan)"}, + {2052 , /* 0x0804 */ "Chinese (PRC)"}, + {3076 , /* 0x0c04 */ "Chinese (Hong Kong SAR, PRC)"}, + {4100 , /* 0x1004 */ "Chinese (Singapore)"}, + {5124 , /* 0x1404 */ "Chinese (MACAO SAR)"}, + {1050 , /* 0x041a */ "Croatian"}, + {1029 , /* 0x0405 */ "Czech"}, + {1030 , /* 0x0406 */ "Danish"}, + {1043 , /* 0x0413 */ "Dutch (Netherlands)"}, + {2067 , /* 0x0813 */ "Dutch (Belgium)"}, + {1033 , /* 0x0409 */ "English (United States)"}, + {2057 , /* 0x0809 */ "English (United Kingdom)"}, + {3081 , /* 0x0c09 */ "English (Australian)"}, + {4105 , /* 0x1009 */ "English (Canadian)"}, + {5129 , /* 0x1409 */ "English (New Zealand)"}, + {6153 , /* 0x1809 */ "English (Ireland)"}, + {7177 , /* 0x1c09 */ "English (South Africa)"}, + {8201 , /* 0x2009 */ "English (Jamaica)"}, + {9225 , /* 0x2409 */ "English (Caribbean)"}, + {10249 , /* 0x2809 */ "English (Belize)"}, + {11273 , /* 0x2c09 */ "English (Trinidad)"}, + {12297 , /* 0x3009 */ "English (Zimbabwe)"}, + {13321 , /* 0x3409 */ "English (Philippines)"}, + {1061 , /* 0x0425 */ "Estonian"}, + {1080 , /* 0x0438 */ "Faeroese"}, + {1065 , /* 0x0429 */ "Farsi "}, + {1035 , /* 0x040b */ "Finnish"}, + {1036 , /* 0x040c */ "French (Standard)"}, + {2060 , /* 0x080c */ "French (Belgian)"}, + {3084 , /* 0x0c0c */ "French (Canadian)"}, + {4108 , /* 0x100c */ "French (Switzerland)"}, + {5132 , /* 0x140c */ "French (Luxembourg)"}, + {6156 , /* 0x180c */ "French (Monaco)"}, + {1079 , /* 0x0437 */ "Georgian"}, + {1031 , /* 0x0407 */ "German (Standard)"}, + {2055 , /* 0x0807 */ "German (Switzerland)"}, + {3079 , /* 0x0c07 */ "German (Austria)"}, + {4103 , /* 0x1007 */ "German (Luxembourg)"}, + {5127 , /* 0x1407 */ "German (Liechtenstein)"}, + {1032 , /* 0x0408 */ "Greek"}, + {1095 , /* 0x0447 */ "Gujarati"}, + {1037 , /* 0x040d */ "Hebrew"}, + {1081 , /* 0x0439 */ "Hindi"}, + {1038 , /* 0x040e */ "Hungarian"}, + {1039 , /* 0x040f */ "Icelandic"}, + {1057 , /* 0x0421 */ "Indonesian"}, + {1040 , /* 0x0410 */ "Italian (Standard)"}, + {2064 , /* 0x0810 */ "Italian (Switzerland)"}, + {1041 , /* 0x0411 */ "Japanese"}, + {1099 , /* 0x044b */ "Kannada"}, + {2144 , /* 0x0860 */ "Kashmiri (India)"}, + {1087 , /* 0x043f */ "Kazakh"}, + {1111 , /* 0x0457 */ "Konkani"}, + {1042 , /* 0x0412 */ "Korean"}, + {2066 , /* 0x0812 */ "Korean (Johab)"}, + {1062 , /* 0x0426 */ "Latvian"}, + {1063 , /* 0x0427 */ "Lithuanian"}, + {2087 , /* 0x0827 */ "Lithuanian (Classic)"}, + {1071 , /* 0x042f */ "Macedonia, Former Yugoslav Republic of"}, + {1086 , /* 0x043e */ "Malay (Malaysian)"}, + {2110 , /* 0x083e */ "Malay (Brunei Darussalam)"}, + {1100 , /* 0x044c */ "Malayalam"}, + {1112 , /* 0x0458 */ "Manipuri"}, + {1102 , /* 0x044e */ "Marathi"}, + {2145 , /* 0x0861 */ "Nepali (India)"}, + {1044 , /* 0x0414 */ "Norwegian (Bokmal)"}, + {2068 , /* 0x0814 */ "Norwegian (Nynorsk)"}, + {1096 , /* 0x0448 */ "Odia"}, + {1045 , /* 0x0415 */ "Polish"}, + {1046 , /* 0x0416 */ "Portuguese (Brazil)"}, + {2070 , /* 0x0816 */ "Portuguese (Portugal)"}, + {1094 , /* 0x0446 */ "Punjabi"}, + {1048 , /* 0x0418 */ "Romanian"}, + {1049 , /* 0x0419 */ "Russian"}, + {1103 , /* 0x044f */ "Sanskrit"}, + {3098 , /* 0x0c1a */ "Serbian (Cyrillic)"}, + {2074 , /* 0x081a */ "Serbian (Latin)"}, + {1113 , /* 0x0459 */ "Sindhi"}, + {1051 , /* 0x041b */ "Slovak"}, + {1060 , /* 0x0424 */ "Slovenian"}, + {1034 , /* 0x040a */ "Spanish (Traditional Sort)"}, + {2058 , /* 0x080a */ "Spanish (Mexican)"}, + {3082 , /* 0x0c0a */ "Spanish (Modern Sort)"}, + {4106 , /* 0x100a */ "Spanish (Guatemala)"}, + {5130 , /* 0x140a */ "Spanish (Costa Rica)"}, + {6154 , /* 0x180a */ "Spanish (Panama)"}, + {7178 , /* 0x1c0a */ "Spanish (Dominican Republic)"}, + {8202 , /* 0x200a */ "Spanish (Venezuela)"}, + {9226 , /* 0x240a */ "Spanish (Colombia)"}, + {10250 , /* 0x280a */ "Spanish (Peru)"}, + {11274 , /* 0x2c0a */ "Spanish (Argentina)"}, + {12298 , /* 0x300a */ "Spanish (Ecuador)"}, + {13322 , /* 0x340a */ "Spanish (Chile)"}, + {14346 , /* 0x380a */ "Spanish (Uruguay)"}, + {15370 , /* 0x3c0a */ "Spanish (Paraguay)"}, + {16394 , /* 0x400a */ "Spanish (Bolivia)"}, + {17418 , /* 0x440a */ "Spanish (El Salvador)"}, + {18442 , /* 0x480a */ "Spanish (Honduras)"}, + {19466 , /* 0x4c0a */ "Spanish (Nicaragua)"}, + {20490 , /* 0x500a */ "Spanish (Puerto Rico)"}, + {1072 , /* 0x0430 */ "Sutu"}, + {1089 , /* 0x0441 */ "Swahili (Kenya)"}, + {1053 , /* 0x041d */ "Swedish"}, + {2077 , /* 0x081d */ "Swedish (Finland)"}, + {1097 , /* 0x0449 */ "Tamil"}, + {1092 , /* 0x0444 */ "Tatar (Tatarstan)"}, + {1098 , /* 0x044a */ "Telugu"}, + {1054 , /* 0x041e */ "Thai"}, + {1055 , /* 0x041f */ "Turkish"}, + {1058 , /* 0x0422 */ "Ukrainian"}, + {1056 , /* 0x0420 */ "Urdu (Pakistan)"}, + {2080 , /* 0x0820 */ "Urdu (India)"}, + {1091 , /* 0x0443 */ "Uzbek (Latin)"}, + {2115 , /* 0x0843 */ "Uzbek (Cyrillic)"}, + {1066 , /* 0x042a */ "Vietnamese"}, + {1279 , /* 0x04ff */ "HID (Usage Data Descriptor)"}, + {61695 , /* 0xf0ff */ "HID (Vendor Defined 1)"}, + {62719 , /* 0xf4ff */ "HID (Vendor Defined 2)"}, + {63743 , /* 0xf8ff */ "HID (Vendor Defined 3)"}, + {64767 , /* 0xfcff */ "HID (Vendor Defined 4)"}, + { 0x00, "End"} +}; + +#endif /* __LANGIDLIST_H__ */ + diff --git a/tests/projects/windows/winsdk/usbview/monitor.ico b/tests/projects/windows/winsdk/usbview/monitor.ico new file mode 100644 index 000000000..e015959f6 Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/monitor.ico differ diff --git a/tests/projects/windows/winsdk/usbview/port.ico b/tests/projects/windows/winsdk/usbview/port.ico new file mode 100644 index 000000000..98c8aa04c Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/port.ico differ diff --git a/tests/projects/windows/winsdk/usbview/resource.h b/tests/projects/windows/winsdk/usbview/resource.h new file mode 100644 index 000000000..921fa6a30 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/resource.h @@ -0,0 +1,51 @@ +/*++ +Copyright (c) 1998-2008 Microsoft Corporation, All Rights Reserved. +--*/ + +#define IDD_MAINDIALOG 101 +#define IDR_MENU 102 +#define IDD_ABOUT 103 +#define IDI_ICON 104 +#define IDC_SPLIT 105 +#define IDACCEL 106 + +#define IDI_BADICON 107 +#define IDI_COMPUTER 108 +#define IDI_HUB 109 +#define IDI_NODEVICE 110 +#define IDI_SSICON 111 +#define IDI_NOSSDEVICE 112 + +#define IDC_TREE 1000 +#define IDC_EDIT 1001 +#define IDC_STATUS 1002 + +#define IDS_STRINGBASE 2000 +#define IDS_STANDARD_FONT 2001 +#define IDS_STANDARD_FONT_HEIGHT 2002 +#define IDS_STANDARD_FONT_WIDTH 2003 +#define IDS_USBVIEW_USAGE 2004 +#define IDS_USBVIEW_PRESSKEY 2005 +#define IDS_USBVIEW_INVALIDARG 2006 +#define IDS_USBVIEW_FILE_EXISTS_TXT 2007 +#define IDS_USBVIEW_FILE_EXISTS_XML 2008 +#define IDS_USBVIEW_INTERNAL_ERROR 2009 +#define IDS_USBVIEW_SAVED_TO 2010 +#define IDS_USBVIEW_INVALID_FILENAME 2011 + +#define IDC_VERSION 3000 +#define IDC_UVCVERSION 3001 + +#define ID_EXIT 40001 +#define ID_REFRESH 40002 +#define ID_AUTO_REFRESH 40003 +#define ID_CONFIG_DESCRIPTORS 40004 +#define ID_ABOUT 40005 +#define ID_ANNOTATION 40007 +#define ID_UNUSED 40008 +#define ID_LOG_DEBUG 40009 +#define ID_SAVE 40010 +#define ID_SAVEALL 40011 +#define ID_SAVEXML 40012 +#define IDC_STATIC 0xFFFFFFFF + diff --git a/tests/projects/windows/winsdk/usbview/split.cur b/tests/projects/windows/winsdk/usbview/split.cur new file mode 100644 index 000000000..41d65e3c5 Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/split.cur differ diff --git a/tests/projects/windows/winsdk/usbview/ssport.ico b/tests/projects/windows/winsdk/usbview/ssport.ico new file mode 100644 index 000000000..e0f712ae6 Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/ssport.ico differ diff --git a/tests/projects/windows/winsdk/usbview/ssusb.ico b/tests/projects/windows/winsdk/usbview/ssusb.ico new file mode 100644 index 000000000..71f0ebe1d Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/ssusb.ico differ diff --git a/tests/projects/windows/winsdk/usbview/usb.ico b/tests/projects/windows/winsdk/usbview/usb.ico new file mode 100644 index 000000000..e615d3e24 Binary files /dev/null and b/tests/projects/windows/winsdk/usbview/usb.ico differ diff --git a/tests/projects/windows/winsdk/usbview/usbdesc.h b/tests/projects/windows/winsdk/usbview/usbdesc.h new file mode 100644 index 000000000..8b78a3c39 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/usbdesc.h @@ -0,0 +1,394 @@ +/*++ + +Copyright (c) 1997-2008 Microsoft Corporation + +Module Name: + + USBDESC.H + +Abstract: + + This is a header file for USB descriptors which are not yet in + a standard system header file. + +Environment: + + user mode + +Revision History: + + 03-06-1998 : created + 03-28-2003 : minor changes to support UVC and USB200 + +--*/ + +#pragma pack(push, 1) + +/***************************************************************************** + D E F I N E S +*****************************************************************************/ + +// +//Device Descriptor bDeviceClass values +// +#define USB_INTERFACE_CLASS_DEVICE 0x00 +#define USB_COMMUNICATION_DEVICE 0x02 +#define USB_HUB_DEVICE 0x09 +#define USB_DEVICE_CLASS_BILLBOARD 0x11 +#define USB_DIAGNOSTIC_DEVICE 0xDC +#define USB_WIRELESS_CONTROLLER_DEVICE 0xE0 +#define USB_MISCELLANEOUS_DEVICE 0xEF +#define USB_VENDOR_SPECIFIC_DEVICE 0xFF + +// +//Device Descriptor bDeviceSubClass values +// +#define USB_COMMON_SUB_CLASS 0x02 + +// +//Interface Descriptor bInterfaceClass values: +// +//#define USB_AUDIO_INTERFACE 0x01 +//#define USB_CDC_CONTROL_INTERFACE 0x02 +//#define USB_HID_INTERFACE 0x03 +//#define USB_PHYSICAL_INTERFACE 0x05 +//#define USB_IMAGE_INTERFACE 0x06 +//#define USB_PRINTER_INTERFACE 0x07 +//#define USB_MASS_STORAGE_INTERFACE 0x08 +//#define USB_HUB_INTERFACE 0x09 +#define USB_CDC_DATA_INTERFACE 0x0A +#define USB_CHIP_SMART_CARD_INTERFACE 0x0B +#define USB_CONTENT_SECURITY_INTERFACE 0x0D +#define USB_DIAGNOSTIC_DEVICE_INTERFACE 0xDC +#define USB_WIRELESS_CONTROLLER_INTERFACE 0xE0 +#define USB_APPLICATION_SPECIFIC_INTERFACE 0xFE +//#define USB_VENDOR_SPECIFIC_INTERFACE 0xFF +#define USB_HID_DESCRIPTOR_TYPE 0x21 + +// +//IAD protocol values +// +#define USB_IAD_PROTOCOL 0x01 + +// +//Device class specific values +// +#define BILLBOARD_MAX_NUM_ALT_MODE 0x34 + +// +//USB 2.0 Specification Changes - New Descriptors +// +#define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE 0x07 +#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 0x08 +#define USB_OTG_DESCRIPTOR_TYPE 0x09 +#define USB_DEBUG_DESCRIPTOR_TYPE 0x0A +#define USB_IAD_DESCRIPTOR_TYPE 0x0B + +// +// USB Device Class Definition for Audio Devices +// Appendix A. Audio Device Class Codes +// + +// A.2 Audio Interface Subclass Codes +// +#define USB_AUDIO_SUBCLASS_UNDEFINED 0x00 +#define USB_AUDIO_SUBCLASS_AUDIOCONTROL 0x01 +#define USB_AUDIO_SUBCLASS_AUDIOSTREAMING 0x02 +#define USB_AUDIO_SUBCLASS_MIDISTREAMING 0x03 + +// A.4 Audio Class-Specific Descriptor Types +// +#define USB_AUDIO_CS_UNDEFINED 0x20 +#define USB_AUDIO_CS_DEVICE 0x21 +#define USB_AUDIO_CS_CONFIGURATION 0x22 +#define USB_AUDIO_CS_STRING 0x23 +#define USB_AUDIO_CS_INTERFACE 0x24 +#define USB_AUDIO_CS_ENDPOINT 0x25 + +// A.5 Audio Class-Specific AC (Audio Control) Interface Descriptor Subtypes +// +#define USB_AUDIO_AC_UNDEFINED 0x00 +#define USB_AUDIO_AC_HEADER 0x01 +#define USB_AUDIO_AC_INPUT_TERMINAL 0x02 +#define USB_AUDIO_AC_OUTPUT_TERMINAL 0x03 +#define USB_AUDIO_AC_MIXER_UNIT 0x04 +#define USB_AUDIO_AC_SELECTOR_UNIT 0x05 +#define USB_AUDIO_AC_FEATURE_UNIT 0x06 +#define USB_AUDIO_AC_PROCESSING_UNIT 0x07 +#define USB_AUDIO_AC_EXTENSION_UNIT 0x08 + +// A.6 Audio Class-Specific AS (Audio Streaming) Interface Descriptor Subtypes +// +#define USB_AUDIO_AS_UNDEFINED 0x00 +#define USB_AUDIO_AS_GENERAL 0x01 +#define USB_AUDIO_AS_FORMAT_TYPE 0x02 +#define USB_AUDIO_AS_FORMAT_SPECIFIC 0x03 + +// A.7 Processing Unit Process Types +// +#define USB_AUDIO_PROCESS_UNDEFINED 0x00 +#define USB_AUDIO_PROCESS_UPDOWNMIX 0x01 +#define USB_AUDIO_PROCESS_DOLBYPROLOGIC 0x02 +#define USB_AUDIO_PROCESS_3DSTEREOEXTENDER 0x03 +#define USB_AUDIO_PROCESS_REVERBERATION 0x04 +#define USB_AUDIO_PROCESS_CHORUS 0x05 +#define USB_AUDIO_PROCESS_DYNRANGECOMP 0x06 + + +/***************************************************************************** + T Y P E D E F S +*****************************************************************************/ + +// HID Class HID Descriptor +// +typedef struct _USB_HID_DESCRIPTOR +{ + UCHAR bLength; + UCHAR bDescriptorType; + USHORT bcdHID; + UCHAR bCountryCode; + UCHAR bNumDescriptors; + struct + { + UCHAR bDescriptorType; + USHORT wDescriptorLength; + } OptionalDescriptors[1]; +} USB_HID_DESCRIPTOR, *PUSB_HID_DESCRIPTOR; + + +// OTG Descriptor +// +typedef struct _USB_OTG_DESCRIPTOR +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bmAttributes; +} USB_OTG_DESCRIPTOR, *PUSB_OTG_DESCRIPTOR; + +// IAD Descriptor +// +typedef struct _USB_IAD_DESCRIPTOR +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bFirstInterface; + UCHAR bInterfaceCount; + UCHAR bFunctionClass; + UCHAR bFunctionSubClass; + UCHAR bFunctionProtocol; + UCHAR iFunction; +} USB_IAD_DESCRIPTOR, *PUSB_IAD_DESCRIPTOR; + + +// Common Class Endpoint Descriptor +// +typedef struct _USB_ENDPOINT_DESCRIPTOR2 { + UCHAR bLength; // offset 0, size 1 + UCHAR bDescriptorType; // offset 1, size 1 + UCHAR bEndpointAddress; // offset 2, size 1 + UCHAR bmAttributes; // offset 3, size 1 + USHORT wMaxPacketSize; // offset 4, size 2 + USHORT wInterval; // offset 6, size 2 + UCHAR bSyncAddress; // offset 8, size 1 +} USB_ENDPOINT_DESCRIPTOR2, *PUSB_ENDPOINT_DESCRIPTOR2; + +// Common Class Interface Descriptor +// +typedef struct _USB_INTERFACE_DESCRIPTOR2 { + UCHAR bLength; // offset 0, size 1 + UCHAR bDescriptorType; // offset 1, size 1 + UCHAR bInterfaceNumber; // offset 2, size 1 + UCHAR bAlternateSetting; // offset 3, size 1 + UCHAR bNumEndpoints; // offset 4, size 1 + UCHAR bInterfaceClass; // offset 5, size 1 + UCHAR bInterfaceSubClass; // offset 6, size 1 + UCHAR bInterfaceProtocol; // offset 7, size 1 + UCHAR iInterface; // offset 8, size 1 + USHORT wNumClasses; // offset 9, size 2 +} USB_INTERFACE_DESCRIPTOR2, *PUSB_INTERFACE_DESCRIPTOR2; + + +// +// USB Device Class Definition for Audio Devices +// + +typedef struct _USB_AUDIO_COMMON_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; +} USB_AUDIO_COMMON_DESCRIPTOR, +*PUSB_AUDIO_COMMON_DESCRIPTOR; + +// 4.3.2 Class-Specific AC (Audio Control) Interface Descriptor +// +typedef struct _USB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + USHORT bcdADC; + USHORT wTotalLength; + UCHAR bInCollection; + UCHAR baInterfaceNr[1]; +} USB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR, +*PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR; + +// 4.3.2.1 Input Terminal Descriptor +// +typedef struct _USB_AUDIO_INPUT_TERMINAL_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR bNrChannels; + USHORT wChannelConfig; + UCHAR iChannelNames; + UCHAR iTerminal; +} USB_AUDIO_INPUT_TERMINAL_DESCRIPTOR, +*PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR; + +// 4.3.2.2 Output Terminal Descriptor +// +typedef struct _USB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR bSourceID; + UCHAR iTerminal; +} USB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR, +*PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR; + +// 4.3.2.3 Mixer Unit Descriptor +// +typedef struct _USB_AUDIO_MIXER_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + UCHAR bNrInPins; + UCHAR baSourceID[1]; +} USB_AUDIO_MIXER_UNIT_DESCRIPTOR, +*PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR; + +// 4.3.2.4 Selector Unit Descriptor +// +typedef struct _USB_AUDIO_SELECTOR_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + UCHAR bNrInPins; + UCHAR baSourceID[1]; +} USB_AUDIO_SELECTOR_UNIT_DESCRIPTOR, +*PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR; + +// 4.3.2.5 Feature Unit Descriptor +// +typedef struct _USB_AUDIO_FEATURE_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + UCHAR bSourceID; + UCHAR bControlSize; + UCHAR bmaControls[1]; +} USB_AUDIO_FEATURE_UNIT_DESCRIPTOR, +*PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR; + +// 4.3.2.6 Processing Unit Descriptor +// +typedef struct _USB_AUDIO_PROCESSING_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + USHORT wProcessType; + UCHAR bNrInPins; + UCHAR baSourceID[1]; +} USB_AUDIO_PROCESSING_UNIT_DESCRIPTOR, +*PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR; + +// 4.3.2.7 Extension Unit Descriptor +// +typedef struct _USB_AUDIO_EXTENSION_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + USHORT wExtensionCode; + UCHAR bNrInPins; + UCHAR baSourceID[1]; +} USB_AUDIO_EXTENSION_UNIT_DESCRIPTOR, +*PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR; + +// 4.5.2 Class-Specific AS Interface Descriptor +// +typedef struct _USB_AUDIO_GENERAL_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalLink; + UCHAR bDelay; + USHORT wFormatTag; +} USB_AUDIO_GENERAL_DESCRIPTOR, +*PUSB_AUDIO_GENERAL_DESCRIPTOR; + +// 4.6.1.2 Class-Specific AS Endpoint Descriptor +// +typedef struct _USB_AUDIO_ENDPOINT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bmAttributes; + UCHAR bLockDelayUnits; + USHORT wLockDelay; +} USB_AUDIO_ENDPOINT_DESCRIPTOR, +*PUSB_AUDIO_ENDPOINT_DESCRIPTOR; + +// +// USB Device Class Definition for Audio Data Formats +// + +typedef struct _USB_AUDIO_COMMON_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatType; +} USB_AUDIO_COMMON_FORMAT_DESCRIPTOR, +*PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR; + + +// 2.1.5 Type I Format Type Descriptor +// 2.3.1 Type III Format Type Descriptor +// +typedef struct _USB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatType; + UCHAR bNrChannels; + UCHAR bSubframeSize; + UCHAR bBitResolution; + UCHAR bSamFreqType; +} USB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR, +*PUSB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR; + + +// 2.2.6 Type II Format Type Descriptor +// +typedef struct _USB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatType; + USHORT wMaxBitRate; + USHORT wSamplesPerFrame; + UCHAR bSamFreqType; +} USB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR, +*PUSB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR; + +#pragma pack(pop) diff --git a/tests/projects/windows/winsdk/usbview/usbschema.hpp b/tests/projects/windows/winsdk/usbview/usbschema.hpp new file mode 100644 index 000000000..1aac6d000 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/usbschema.hpp @@ -0,0 +1,6119 @@ +// +// This file is auto-generated from XSD using the command: +// xsd.exe /language:CPP /c /order /namespace:Microsoft.Kits.Samples.Usb +// + +#pragma once + +#using +#using +#using + +using namespace System::Security::Permissions; +// +// This source code was auto-generated by xsd, Version=4.0.30319.0. +// +namespace Microsoft { + namespace Kits { + namespace Samples { + namespace Usb { + using namespace System::Xml::Serialization; + using namespace System; + ref class UvcViewAll; + ref class UvcViewType; + ref class MachineInfoType; + ref class NoDeviceType; + ref class PortConnectorType; + ref class UsbPortPropertiesType; + ref class NodeConnectionInfoExV2Type; + ref class UsbBillboardSVIDType; + ref class UsbBillboardCapabilityDescriptorType; + ref class UsbDispContIdCapExtDescriptorType; + ref class UsbUsb20ExtensionDescriptorType; + ref class UsbSuperSpeedExtensionDescriptorType; + ref class UsbBosDescriptorType; + ref class UsbDeviceUnknownDescriptorType; + ref class UsbDeviceIADDescriptorType; + ref class UsbDeviceClassType; + ref class UsbDeviceOTGDescriptorType; + ref class UsbDeviceHidOptionalDescriptorsType; + ref class UsbDeviceHidDescriptorType; + ref class UsbDeviceInterfaceDescriptorType; + ref class UsbDeviceQualifierDescriptorType; + ref class UsbConfigurationDescriptorType; + ref class UsbDeviceConfigurationType; + ref class EndpointDescriptorType; + ref class UsbDeviceType; + ref class NodeConnectionInfoExType; + ref class NodeConnectionInfoExStructType; + ref class UsbDeviceDescriptorType; + ref class UsbPipeInfoType; + ref class UsbDeviceClassDetailsType; + ref class ExternalHubType; + ref class HubNodeInformationType; + ref class HubInformationType; + ref class HubDescriptorType; + ref class HubCharacteristicsType; + ref class HubInformationExType; + ref class Hub30DescriptorType; + ref class HubCapabilitiesExType; + ref class RootHubType; + ref class UsbHCPowerStateType; + ref class UsbHCPowerStateMappingType; + ref class UsbHCDeviceInfoType; + ref class HostControllerType; + + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public enum class UsbConnectionSpeedType { + + /// + Low, + + /// + Full, + + /// + High, + + /// + Super, + + /// + Unknown, + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public enum class UsbConnectionStatusType { + + /// + NoDeviceConnected, + + /// + DeviceConnected, + + /// + DeviceFailedEnumeration, + + /// + DeviceGeneralFailure, + + /// + DeviceCausedOvercurrent, + + /// + DeviceNotEnoughPower, + + /// + DeviceNotEnoughBandwidth, + + /// + DeviceHubNestedTooDeeply, + + /// + DeviceInLegacyHub, + + /// + DeviceEnumerating, + + /// + DeviceReset, + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public enum class DevicePowerStateType { + + /// + PowerDeviceUnspecified, + + /// + PowerDeviceD0, + + /// + PowerDeviceD1, + + /// + PowerDeviceD2, + + /// + PowerDeviceD3, + + /// + PowerDeviceMaximum, + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public enum class HubNodeType { + + /// + UsbHub, + + /// + UsbMiParent, + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public enum class HubTypeType { + + /// + UnknownHubType, + + /// + UsbRootHub, + + /// + Usb20Hub, + + /// + Usb30Hub, + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(AnonymousType=true, Namespace=L"USB"), + System::Xml::Serialization::XmlRootAttribute(Namespace=L"USB", IsNullable=false)] + public ref class UvcViewAll { + + private: Microsoft::Kits::Samples::Usb::UvcViewType^ uvcViewField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::UvcViewType^ UvcView { + Microsoft::Kits::Samples::Usb::UvcViewType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UvcViewType^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UvcViewType { + + private: Microsoft::Kits::Samples::Usb::MachineInfoType^ machineInfoField; + + private: cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ usbTreeField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::MachineInfoType^ MachineInfo { + Microsoft::Kits::Samples::Usb::MachineInfoType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::MachineInfoType^ value); + } + + /// + public: [System::Xml::Serialization::XmlArrayAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1), + System::Xml::Serialization::XmlArrayItemAttribute(L"UsbController", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, IsNullable=false)] + property cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ UsbTree { + cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class MachineInfoType { + + private: System::Byte uvcMajorVersionField; + + private: System::Byte uvcMinorVersionField; + + private: System::Byte uvcMajorSpecVersionField; + + private: System::Byte uvcMinorSpecVersionField; + + private: System::DateTime collectionTimeField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::Byte UvcMajorVersion { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::Byte UvcMinorVersion { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::Byte UvcMajorSpecVersion { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::Byte UvcMinorSpecVersion { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::DateTime CollectionTime { + System::DateTime get(); + System::Void set(System::DateTime value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class NoDeviceType { + + private: Microsoft::Kits::Samples::Usb::PortConnectorType^ portConnectorField; + + private: System::String^ usbPortNumberField; + + private: System::String^ nameField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::PortConnectorType^ PortConnector { + Microsoft::Kits::Samples::Usb::PortConnectorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ UsbPortNumber { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ Name { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class PortConnectorType { + + private: System::UInt64 connectionIndexField; + + private: System::UInt64 actualLengthField; + + private: Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ usbPortPropertiesField; + + private: System::UInt16 companionIndexField; + + private: System::UInt16 companionPortNumberField; + + private: System::String^ companionHubSymbolicLinkNameField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::UInt64 ConnectionIndex { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::UInt64 ActualLength { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ UsbPortProperties { + Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::UInt16 CompanionIndex { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::UInt16 CompanionPortNumber { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::String^ CompanionHubSymbolicLinkName { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbPortPropertiesType { + + private: System::Boolean portIsUserConnectableField; + + private: System::Boolean portIsDebugCapableField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::Boolean PortIsUserConnectable { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::Boolean PortIsDebugCapable { + System::Boolean get(); + System::Void set(System::Boolean value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class NodeConnectionInfoExV2Type { + + private: System::UInt64 connectionIndexField; + + private: System::UInt64 lengthField; + + private: System::Boolean usb110SupportedField; + + private: System::Boolean usb200SupportedField; + + private: System::Boolean usb300SupportedField; + + private: System::Boolean deviceIsOperatingAtSuperSpeedOrHigherField; + + private: System::Boolean deviceIsSuperSpeedCapableOrHigherField; + + private: System::Boolean deviceIsOperatingAtSuperSpeedPlusOrHigherField; + + private: System::Boolean deviceIsSuperSpeedPlusCapableOrHigherField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::UInt64 ConnectionIndex { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::UInt64 Length { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::Boolean Usb110Supported { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::Boolean Usb200Supported { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::Boolean Usb300Supported { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::Boolean DeviceIsOperatingAtSuperSpeedOrHigher { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::Boolean DeviceIsSuperSpeedCapableOrHigher { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] + property System::Boolean DeviceIsOperatingAtSuperSpeedPlusOrHigher { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] + property System::Boolean DeviceIsSuperSpeedPlusCapableOrHigher { + System::Boolean get(); + System::Void set(System::Boolean value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbBillboardSVIDType { + + private: System::String^ descriptionField; + + private: System::String^ alternateModeStringField; + + private: System::UInt16 wSVIDField; + + private: System::Byte bAlternateModeField; + + private: System::Byte iAlternateModeStringField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ Description { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ AlternateModeString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WSVID { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BAlternateMode { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IAlternateModeString { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbBillboardCapabilityDescriptorType { + + private: System::String^ vConnPowerField; + + private: System::String^ billboardDescriptorErrorsField; + + private: System::String^ addtionalInfoURLField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ usbBillboardSVIDField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bDevCapabilityTypeField; + + private: System::Byte iAddtionalInfoURLField; + + private: System::Byte bNumberOfAlternateModesField; + + private: System::Byte bPreferredAlternateModeField; + + private: System::Byte calculatedBLengthField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ VConnPower { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ BillboardDescriptorErrors { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ AddtionalInfoURL { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbBillboardSVID", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=3)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ UsbBillboardSVID { + cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDevCapabilityType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IAddtionalInfoURL { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BNumberOfAlternateModes { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BPreferredAlternateMode { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte CalculatedBLength { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDispContIdCapExtDescriptorType { + + private: System::String^ reservedBitErrorField; + + private: System::String^ containerIdStrField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bReservedField; + + private: System::Byte bDevCapabilityTypeField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ ReservedBitError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ ContainerIdStr { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BReserved { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDevCapabilityType { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbUsb20ExtensionDescriptorType { + + private: System::String^ reservedBitErrorField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bDevCapabilityTypeField; + + private: System::UInt64 bmAttributesField; + + private: System::Boolean supportsLinkPowerManagementField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ ReservedBitError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDevCapabilityType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt64 BmAttributes { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean SupportsLinkPowerManagement { + System::Boolean get(); + System::Void set(System::Boolean value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbSuperSpeedExtensionDescriptorType { + + private: System::String^ reservedAttributesBitErrorField; + + private: System::String^ reservedSpeedBitErrorField; + + private: System::String^ reservedSpeedErrorField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bDevCapabilityTypeField; + + private: System::UInt64 bmAttributesField; + + private: System::Boolean latencyToleranceMsgCapableField; + + private: System::Byte bFunctionalitySupportField; + + private: System::Byte bU1DevExitLatField; + + private: System::UInt16 wSpeedsSupportedField; + + private: System::UInt16 wU2DevExitLatField; + + private: System::Boolean supportsLowSpeedField; + + private: System::Boolean supportsFullSpeedField; + + private: System::Boolean supportsHighSpeedField; + + private: System::Boolean supportsSuperSpeedField; + + private: System::String^ lowestSpeedField; + + private: System::String^ u1DevExitLatencyStringField; + + private: System::String^ u2DevExitLatencyStringField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ ReservedAttributesBitError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ ReservedSpeedBitError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ ReservedSpeedError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDevCapabilityType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt64 BmAttributes { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean LatencyToleranceMsgCapable { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BFunctionalitySupport { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BU1DevExitLat { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WSpeedsSupported { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WU2DevExitLat { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean SupportsLowSpeed { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean SupportsFullSpeed { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean SupportsHighSpeed { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean SupportsSuperSpeed { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ LowestSpeed { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ U1DevExitLatencyString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ U2DevExitLatencyString { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbBosDescriptorType { + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ unknownDescriptorField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ usbSuperSpeedExtensionDescriptorField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ usbUsb20ExtensionDescriptorField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ usbDispContIdCapExtDescriptorField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ usbBillboardCapabilityDescriptorField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::UInt16 wTotalLengthField; + + private: System::Byte bNumDeviceCapsField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UnknownDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=0)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ UnknownDescriptor { + cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbSuperSpeedExtensionDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=1)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ UsbSuperSpeedExtensionDescriptor { + cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbUsb20ExtensionDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=2)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ UsbUsb20ExtensionDescriptor { + cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbDispContIdCapExtDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=3)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ UsbDispContIdCapExtDescriptor { + cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbBillboardCapabilityDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=4)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ UsbBillboardCapabilityDescriptor { + cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WTotalLength { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BNumDeviceCaps { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceUnknownDescriptorType { + + private: System::String^ unknownDescriptorField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ UnknownDescriptor { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceIADDescriptorType { + + private: Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ functionDetailsField; + + private: System::String^ interfaceErrorField; + + private: System::String^ functionClassErrorField; + + private: System::String^ protocolField; + + private: System::String^ stringDescField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bFirstInterfaceField; + + private: System::Byte bInterfaceCountField; + + private: System::Byte bFunctionClassField; + + private: System::Byte bFunctionSubclassField; + + private: System::Byte bFunctionProtocolField; + + private: System::Byte iFunctionField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ FunctionDetails { + Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ InterfaceError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ FunctionClassError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::String^ Protocol { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::String^ StringDesc { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BFirstInterface { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BInterfaceCount { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BFunctionClass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BFunctionSubclass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BFunctionProtocol { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IFunction { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceClassType { + + private: System::String^ deviceClassField; + + private: System::String^ deviceSubclassField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ DeviceClass { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ DeviceSubclass { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceOTGDescriptorType { + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bmAttributesField; + + private: System::String^ attributesStringField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BmAttributes { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ AttributesString { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceHidOptionalDescriptorsType { + + private: System::Byte bDescriptorTypeField; + + private: System::UInt16 wDescriptorLengthField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WDescriptorLength { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceHidDescriptorType { + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ optionalDescriptorField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::UInt16 bcdHIDField; + + private: System::Byte bCountryCodeField; + + private: System::Byte bNumDescriptorsField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"OptionalDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=0)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ OptionalDescriptor { + cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 BcdHID { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BCountryCode { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BNumDescriptors { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceInterfaceDescriptorType { + + private: Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ interfaceDetailsField; + + private: System::String^ protocolErrorField; + + private: System::String^ stringDescField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::Byte bInterfaceNumberField; + + private: System::Byte bAlternateSettingField; + + private: System::Byte bNumEndpointsField; + + private: System::Byte bInterfaceClassField; + + private: System::Byte bInterfaceSubclassField; + + private: System::Byte bInterfaceProtocolField; + + private: System::Byte iInterfaceField; + + private: System::UInt16 wNumClassesField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ InterfaceDetails { + Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ ProtocolError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ StringDesc { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BInterfaceNumber { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BAlternateSetting { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BNumEndpoints { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BInterfaceClass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BInterfaceSubclass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BInterfaceProtocol { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IInterface { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WNumClasses { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceQualifierDescriptorType { + + private: System::String^ deviceClassField; + + private: System::Byte maxPacketSizeInBytesField; + + private: System::Boolean maxPacketSizeInBytesFieldSpecified; + + private: System::String^ deviceClassErrorField; + + private: System::String^ deviceSubclassErrorField; + + private: System::String^ deviceProtocolErrorField; + + private: System::String^ deviceNumConfigErrorField; + + private: System::String^ reservedErrorField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::UInt16 bcdUSBField; + + private: System::Byte bDeviceClassField; + + private: System::Byte bDeviceSubclassField; + + private: System::Byte bDeviceProtocolField; + + private: System::Byte bMaxPacketSize0Field; + + private: System::Byte numConfigurationsField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ DeviceClass { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::Byte MaxPacketSizeInBytes { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlIgnoreAttribute] + property System::Boolean MaxPacketSizeInBytesSpecified { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ DeviceClassError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::String^ DeviceSubclassError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::String^ DeviceProtocolError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::String^ DeviceNumConfigError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::String^ ReservedError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 BcdUSB { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDeviceClass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDeviceSubclass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDeviceProtocol { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BMaxPacketSize0 { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte NumConfigurations { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbConfigurationDescriptorType { + + private: System::String^ configDescErrorField; + + private: System::String^ confValueErrorField; + + private: System::String^ confStringDescField; + + private: System::String^ attributesStrField; + + private: System::String^ maxCurrentField; + + private: System::Byte bLengthField; + + private: System::Byte bDescriptorTypeField; + + private: System::UInt16 wTotalLengthField; + + private: System::Byte bNumInterfacesField; + + private: System::Byte bConfigurationValueField; + + private: System::Byte iConfigurationField; + + private: System::Byte bmAttributesField; + + private: System::Byte maxPowerField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ ConfigDescError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ ConfValueError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ ConfStringDesc { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::String^ AttributesStr { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::String^ MaxCurrent { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BDescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WTotalLength { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BNumInterfaces { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BConfigurationValue { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IConfiguration { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte BmAttributes { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte MaxPower { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceConfigurationType { + + private: System::String^ deviceQualifierErrorField; + + private: System::String^ speedConfigurationErrorField; + + private: System::String^ deviceConfigurationErrorField; + + private: System::String^ interfaceErrorField; + + private: System::String^ preReleaseErrorField; + + private: System::String^ endpointErrorField; + + private: System::String^ hidErrorField; + + private: System::String^ otgErrorField; + + private: System::String^ iadErrorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ deviceDetailsField; + + private: Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ configurationDescriptorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ deviceQualifierDescriptorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ interfaceDescriptorField; + + private: Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ endpointDescriptorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ hidDescriptorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ otgDescriptorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ iadDescriptorField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ unknownDescriptorField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ DeviceQualifierError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ SpeedConfigurationError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ DeviceConfigurationError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::String^ InterfaceError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::String^ PreReleaseError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::String^ EndpointError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::String^ HidError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] + property System::String^ OtgError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] + property System::String^ IadError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] + property Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ DeviceDetails { + Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] + property Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ ConfigurationDescriptor { + Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] + property Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ DeviceQualifierDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=12)] + property Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ InterfaceDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=13)] + property Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ EndpointDescriptor { + Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=14)] + property Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ HidDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=15)] + property Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ OtgDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=16)] + property Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ IadDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=17)] + property Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ UnknownDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class EndpointDescriptorType { + + private: System::Byte lengthField; + + private: System::Byte descriptorTypeField; + + private: System::Byte endpointAddressField; + + private: System::Byte attributesField; + + private: System::UInt16 maxPacketSizeField; + + private: System::Byte intervalField; + + private: System::UInt16 wIntervalField; + + private: System::Byte syncAddressField; + + private: System::String^ endpointDirectionField; + + private: System::Byte endpointIdField; + + private: System::String^ endpointTypeField; + + private: System::String^ endpointPacketInfoField; + + private: System::String^ endpointPacketSizeValidationField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte Length { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte EndpointAddress { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte Attributes { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 MaxPacketSize { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte Interval { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 WInterval { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte SyncAddress { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ EndpointDirection { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte EndpointId { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ EndpointType { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ EndpointPacketInfo { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ EndpointPacketSizeValidation { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceType { + + private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ connectionInfoField; + + private: Microsoft::Kits::Samples::Usb::PortConnectorType^ portConnectorField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ deviceConfigurationField; + + private: Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ bosDescriptorField; + + private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ connectionInfoV2Field; + + private: System::String^ usbPortNumberField; + + private: System::String^ serviceNameField; + + private: System::String^ hwIdField; + + private: System::String^ deviceIdField; + + private: System::String^ deviceNameField; + + private: System::String^ deviceClassField; + + private: System::String^ usbProtocolField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ ConnectionInfo { + Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property Microsoft::Kits::Samples::Usb::PortConnectorType^ PortConnector { + Microsoft::Kits::Samples::Usb::PortConnectorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"DeviceConfiguration", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=2)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ DeviceConfiguration { + cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ BosDescriptor { + Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ ConnectionInfoV2 { + Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ UsbPortNumber { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ ServiceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ HwId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceClass { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ UsbProtocol { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class NodeConnectionInfoExType { + + private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ connectionInfoStructField; + + private: System::String^ iProductStringDescEnField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ deviceClassDetailsField; + + private: System::Byte maxPacketSizeInBytesField; + + private: System::String^ vendorStringField; + + private: System::String^ manufacturerStringField; + + private: System::String^ productStringField; + + private: System::String^ langIdStringField; + + private: System::String^ serialStringField; + + private: System::String^ pipeInfoErrorField; + + private: System::String^ lengthErrorField; + + private: System::String^ deviceErrorField; + + private: System::String^ packetSizeErrorField; + + private: System::String^ configurationCountErrorField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ ConnectionInfoStruct { + Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ IProductStringDescEn { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ DeviceClassDetails { + Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::Byte MaxPacketSizeInBytes { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::String^ VendorString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::String^ ManufacturerString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::String^ ProductString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] + property System::String^ LangIdString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] + property System::String^ SerialString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] + property System::String^ PipeInfoError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] + property System::String^ LengthError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] + property System::String^ DeviceError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=12)] + property System::String^ PacketSizeError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=13)] + property System::String^ ConfigurationCountError { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class NodeConnectionInfoExStructType { + + private: System::UInt64 connectionIndexField; + + private: Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ deviceDescriptorField; + + private: System::Byte currentConfigurationValueField; + + private: System::Byte speedField; + + private: Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType speedStrField; + + private: System::Boolean deviceIsHubField; + + private: System::Byte deviceAddressField; + + private: System::UInt64 numOfOpenPipesField; + + private: Microsoft::Kits::Samples::Usb::UsbConnectionStatusType usbConnectionStatusField; + + private: Microsoft::Kits::Samples::Usb::DevicePowerStateType devicePowerStateField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ pipeField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::UInt64 ConnectionIndex { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ DeviceDescriptor { + Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::Byte CurrentConfigurationValue { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::Byte Speed { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType SpeedStr { + Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::Boolean DeviceIsHub { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::Byte DeviceAddress { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] + property System::UInt64 NumOfOpenPipes { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] + property Microsoft::Kits::Samples::Usb::UsbConnectionStatusType UsbConnectionStatus { + Microsoft::Kits::Samples::Usb::UsbConnectionStatusType get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbConnectionStatusType value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] + property Microsoft::Kits::Samples::Usb::DevicePowerStateType DevicePowerState { + Microsoft::Kits::Samples::Usb::DevicePowerStateType get(); + System::Void set(Microsoft::Kits::Samples::Usb::DevicePowerStateType value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"Pipe", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ Pipe { + cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceDescriptorType { + + private: System::Byte lengthField; + + private: System::Byte descriptorTypeField; + + private: System::UInt16 cdUSBField; + + private: System::Byte deviceClassField; + + private: System::Byte deviceSubclassField; + + private: System::Byte deviceProtocolField; + + private: System::Byte maxPacketSize0Field; + + private: System::UInt16 idVendorField; + + private: System::UInt16 idProductField; + + private: System::UInt16 cdDeviceField; + + private: System::Byte iManufacturerField; + + private: System::Byte iProductField; + + private: System::Byte iSerialNumberField; + + private: System::Byte numConfigurationsField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte Length { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 CdUSB { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DeviceClass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DeviceSubclass { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DeviceProtocol { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte MaxPacketSize0 { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 IdVendor { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 IdProduct { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 CdDevice { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IManufacturer { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte IProduct { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte ISerialNumber { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte NumConfigurations { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbPipeInfoType { + + private: Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ endpointDescriptorField; + + private: System::UInt64 scheduleOffsetField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ EndpointDescriptor { + Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::UInt64 ScheduleOffset { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbDeviceClassDetailsType { + + private: System::String^ deviceTypeField; + + private: System::String^ deviceTypeErrorField; + + private: System::String^ subclassTypeField; + + private: System::String^ subclassTypeErrorField; + + private: System::String^ deviceProtocolField; + + private: System::String^ deviceProtocolErrorField; + + private: System::UInt32 uvcVersionField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::String^ DeviceType { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ DeviceTypeError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ SubclassType { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::String^ SubclassTypeError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::String^ DeviceProtocol { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::String^ DeviceProtocolError { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::UInt32 UvcVersion { + System::UInt32 get(); + System::Void set(System::UInt32 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class ExternalHubType { + + private: Microsoft::Kits::Samples::Usb::HubNodeInformationType^ hubNodeInformationField; + + private: System::String^ hubNameField; + + private: Microsoft::Kits::Samples::Usb::HubInformationExType^ hubInformationExField; + + private: Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ hubCapabilityExField; + + private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ connectionInfoField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ usbDeviceField; + + private: cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ noDeviceField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ deviceConfigurationField; + + private: Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ bosDescriptorField; + + private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ connectionInfoV2Field; + + private: cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ externalHubField; + + private: Microsoft::Kits::Samples::Usb::PortConnectorType^ portConnectorField; + + private: System::String^ serviceNameField; + + private: System::String^ hwIdField; + + private: System::String^ deviceIdField; + + private: System::String^ deviceNameField; + + private: System::String^ deviceClassField; + + private: System::String^ usbProtocolField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::HubNodeInformationType^ HubNodeInformation { + Microsoft::Kits::Samples::Usb::HubNodeInformationType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ HubName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::HubInformationExType^ HubInformationEx { + Microsoft::Kits::Samples::Usb::HubInformationExType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ HubCapabilityEx { + Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ ConnectionInfo { + Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=5)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ UsbDevice { + cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"NoDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ NoDevice { + cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"DeviceConfiguration", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=7)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ DeviceConfiguration { + cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] + property Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ BosDescriptor { + Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] + property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ ConnectionInfoV2 { + Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"ExternalHub", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=10)] + property cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ ExternalHub { + cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] + property Microsoft::Kits::Samples::Usb::PortConnectorType^ PortConnector { + Microsoft::Kits::Samples::Usb::PortConnectorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ ServiceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ HwId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceClass { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ UsbProtocol { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HubNodeInformationType { + + private: Microsoft::Kits::Samples::Usb::HubNodeType hubNodeField; + + private: Microsoft::Kits::Samples::Usb::HubInformationType^ hubInformationField; + + private: System::UInt64 miParentNumberOfInterfacesField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::HubNodeType HubNode { + Microsoft::Kits::Samples::Usb::HubNodeType get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubNodeType value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property Microsoft::Kits::Samples::Usb::HubInformationType^ HubInformation { + Microsoft::Kits::Samples::Usb::HubInformationType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubInformationType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::UInt64 MiParentNumberOfInterfaces { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HubInformationType { + + private: System::Boolean isRootHubField; + + private: System::Boolean isBusPoweredField; + + private: Microsoft::Kits::Samples::Usb::HubDescriptorType^ hubDescriptorField; + + private: Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ hubCharacteristicsField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::Boolean IsRootHub { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::Boolean IsBusPowered { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubDescriptor { + Microsoft::Kits::Samples::Usb::HubDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ HubCharacteristics { + Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HubDescriptorType { + + private: System::Byte descriptorLengthField; + + private: System::Byte descriptorTypeField; + + private: System::Byte numberOfPortsField; + + private: System::Byte powerOntoPowerGoodField; + + private: System::Byte hubControlCurrentField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DescriptorLength { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte NumberOfPorts { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte PowerOntoPowerGood { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte HubControlCurrent { + System::Byte get(); + System::Void set(System::Byte value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HubCharacteristicsType { + + private: System::UInt32 hubCharacteristicsValueField; + + private: System::String^ powerSwitchingField; + + private: System::Boolean compoundDeviceField; + + private: System::String^ overCurrentProtectionField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt32 HubCharacteristicsValue { + System::UInt32 get(); + System::Void set(System::UInt32 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ PowerSwitching { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean CompoundDevice { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ OverCurrentProtection { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HubInformationExType { + + private: Microsoft::Kits::Samples::Usb::HubTypeType hubTypeField; + + private: System::UInt16 highestPortNumberField; + + private: Microsoft::Kits::Samples::Usb::HubDescriptorType^ hubDescriptorField; + + private: Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ hub30DescriptorField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::HubTypeType HubType { + Microsoft::Kits::Samples::Usb::HubTypeType get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubTypeType value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::UInt16 HighestPortNumber { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubDescriptor { + Microsoft::Kits::Samples::Usb::HubDescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ Hub30Descriptor { + Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class Hub30DescriptorType { + + private: System::Byte lengthField; + + private: System::Byte descriptorTypeField; + + private: System::Byte numberOfPortsField; + + private: System::UInt16 hubCharacteristicsField; + + private: System::Byte powerOntoPowerGoodField; + + private: System::Byte hubControlCurrentField; + + private: System::Byte hubHdrDecLatField; + + private: System::UInt16 hubDelayField; + + private: System::UInt16 deviceRemovableField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte Length { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte DescriptorType { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte NumberOfPorts { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 HubCharacteristics { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte PowerOntoPowerGood { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte HubControlCurrent { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Byte HubHdrDecLat { + System::Byte get(); + System::Void set(System::Byte value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 HubDelay { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::UInt16 DeviceRemovable { + System::UInt16 get(); + System::Void set(System::UInt16 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HubCapabilitiesExType { + + private: System::Boolean hubIsHighSpeedCapableField; + + private: System::Boolean hubIsHighSpeedField; + + private: System::Boolean hubIsMultiTtCapableField; + + private: System::Boolean hubIsMultiTtField; + + private: System::Boolean hubIsRootField; + + private: System::Boolean hubIsArmedWakeOnConnectField; + + private: System::Boolean hubIsBusPoweredField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsHighSpeedCapable { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsHighSpeed { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsMultiTtCapable { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsMultiTt { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsRoot { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsArmedWakeOnConnect { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean HubIsBusPowered { + System::Boolean get(); + System::Void set(System::Boolean value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class RootHubType { + + private: Microsoft::Kits::Samples::Usb::HubNodeInformationType^ hubNodeInformationField; + + private: System::String^ hubNameField; + + private: Microsoft::Kits::Samples::Usb::HubInformationExType^ hubInformationExField; + + private: Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ hubCapabilityExField; + + private: cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ externalHubField; + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ usbDeviceField; + + private: cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ noDeviceField; + + private: System::String^ serviceNameField; + + private: System::String^ hwIdField; + + private: System::String^ deviceIdField; + + private: System::String^ deviceNameField; + + private: System::String^ deviceClassField; + + private: System::String^ usbProtocolField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::HubNodeInformationType^ HubNodeInformation { + Microsoft::Kits::Samples::Usb::HubNodeInformationType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ HubName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::HubInformationExType^ HubInformationEx { + Microsoft::Kits::Samples::Usb::HubInformationExType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ HubCapabilityEx { + Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"ExternalHub", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=4)] + property cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ ExternalHub { + cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"UsbDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, + Order=5)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ UsbDevice { + cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"NoDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ NoDevice { + cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ ServiceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ HwId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceClass { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ UsbProtocol { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbHCPowerStateType { + + private: System::String^ systemStateField; + + private: System::String^ hostControllerStateField; + + private: System::String^ hubStateField; + + private: System::Boolean canWakeUpField; + + private: System::Boolean isPoweredField; + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ SystemState { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ HostControllerState { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ HubState { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean CanWakeUp { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::Boolean IsPowered { + System::Boolean get(); + System::Void set(System::Boolean value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbHCPowerStateMappingType { + + private: cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ powerMapField; + + private: System::String^ lastSleepStateField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(L"PowerMap", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ PowerMap { + cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ get(); + System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::String^ LastSleepState { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class UsbHCDeviceInfoType { + + private: System::Int64 vendorIdField; + + private: System::Int64 deviceIdField; + + private: System::String^ driverKeyField; + + private: System::Int64 subSysIdField; + + private: System::Int64 revisionField; + + private: System::UInt64 debugPortField; + + private: System::UInt64 numberOfRootPortsField; + + private: System::UInt64 controllerFlavorField; + + private: System::String^ controllerFlavorStringField; + + private: System::Boolean portSwitchingEnabledField; + + private: System::Boolean selectiveSuspendEnabledField; + + private: System::UInt64 legacyBiosField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property System::Int64 VendorId { + System::Int64 get(); + System::Void set(System::Int64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property System::Int64 DeviceId { + System::Int64 get(); + System::Void set(System::Int64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property System::String^ DriverKey { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] + property System::Int64 SubSysId { + System::Int64 get(); + System::Void set(System::Int64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] + property System::Int64 Revision { + System::Int64 get(); + System::Void set(System::Int64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] + property System::UInt64 DebugPort { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] + property System::UInt64 NumberOfRootPorts { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] + property System::UInt64 ControllerFlavor { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] + property System::String^ ControllerFlavorString { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] + property System::Boolean PortSwitchingEnabled { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] + property System::Boolean SelectiveSuspendEnabled { + System::Boolean get(); + System::Void set(System::Boolean value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] + property System::UInt64 LegacyBios { + System::UInt64 get(); + System::Void set(System::UInt64 value); + } + }; + + /// + [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), + System::SerializableAttribute, + System::Diagnostics::DebuggerStepThroughAttribute, + System::ComponentModel::DesignerCategoryAttribute(L"code"), + System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] + public ref class HostControllerType { + + private: Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ controllerInfoField; + + private: Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ powerMappingField; + + private: Microsoft::Kits::Samples::Usb::RootHubType^ rootHubField; + + private: System::String^ serviceNameField; + + private: System::String^ hwIdField; + + private: System::String^ deviceIdField; + + private: System::String^ deviceNameField; + + private: System::String^ deviceClassField; + + private: System::String^ usbProtocolField; + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] + property Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ ControllerInfo { + Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] + property Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ PowerMapping { + Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ value); + } + + /// + public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] + property Microsoft::Kits::Samples::Usb::RootHubType^ RootHub { + Microsoft::Kits::Samples::Usb::RootHubType^ get(); + System::Void set(Microsoft::Kits::Samples::Usb::RootHubType^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ ServiceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ HwId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceId { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceName { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ DeviceClass { + System::String^ get(); + System::Void set(System::String^ value); + } + + /// + public: [System::Xml::Serialization::XmlAttributeAttribute] + property System::String^ UsbProtocol { + System::String^ get(); + System::Void set(System::String^ value); + } + }; + } + } + } +} +namespace Microsoft { + namespace Kits { + namespace Samples { + namespace Usb { + + + + + + + + inline Microsoft::Kits::Samples::Usb::UvcViewType^ UvcViewAll::UvcView::get() { + return this->uvcViewField; + } + inline System::Void UvcViewAll::UvcView::set(Microsoft::Kits::Samples::Usb::UvcViewType^ value) { + this->uvcViewField = value; + } + + + inline Microsoft::Kits::Samples::Usb::MachineInfoType^ UvcViewType::MachineInfo::get() { + return this->machineInfoField; + } + inline System::Void UvcViewType::MachineInfo::set(Microsoft::Kits::Samples::Usb::MachineInfoType^ value) { + this->machineInfoField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ UvcViewType::UsbTree::get() { + return this->usbTreeField; + } + inline System::Void UvcViewType::UsbTree::set(cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ value) { + this->usbTreeField = value; + } + + + inline System::Byte MachineInfoType::UvcMajorVersion::get() { + return this->uvcMajorVersionField; + } + inline System::Void MachineInfoType::UvcMajorVersion::set(System::Byte value) { + this->uvcMajorVersionField = value; + } + + inline System::Byte MachineInfoType::UvcMinorVersion::get() { + return this->uvcMinorVersionField; + } + inline System::Void MachineInfoType::UvcMinorVersion::set(System::Byte value) { + this->uvcMinorVersionField = value; + } + + inline System::Byte MachineInfoType::UvcMajorSpecVersion::get() { + return this->uvcMajorSpecVersionField; + } + inline System::Void MachineInfoType::UvcMajorSpecVersion::set(System::Byte value) { + this->uvcMajorSpecVersionField = value; + } + + inline System::Byte MachineInfoType::UvcMinorSpecVersion::get() { + return this->uvcMinorSpecVersionField; + } + inline System::Void MachineInfoType::UvcMinorSpecVersion::set(System::Byte value) { + this->uvcMinorSpecVersionField = value; + } + + inline System::DateTime MachineInfoType::CollectionTime::get() { + return this->collectionTimeField; + } + inline System::Void MachineInfoType::CollectionTime::set(System::DateTime value) { + this->collectionTimeField = value; + } + + + inline Microsoft::Kits::Samples::Usb::PortConnectorType^ NoDeviceType::PortConnector::get() { + return this->portConnectorField; + } + inline System::Void NoDeviceType::PortConnector::set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value) { + this->portConnectorField = value; + } + + inline System::String^ NoDeviceType::UsbPortNumber::get() { + return this->usbPortNumberField; + } + inline System::Void NoDeviceType::UsbPortNumber::set(System::String^ value) { + this->usbPortNumberField = value; + } + + inline System::String^ NoDeviceType::Name::get() { + return this->nameField; + } + inline System::Void NoDeviceType::Name::set(System::String^ value) { + this->nameField = value; + } + + + inline System::UInt64 PortConnectorType::ConnectionIndex::get() { + return this->connectionIndexField; + } + inline System::Void PortConnectorType::ConnectionIndex::set(System::UInt64 value) { + this->connectionIndexField = value; + } + + inline System::UInt64 PortConnectorType::ActualLength::get() { + return this->actualLengthField; + } + inline System::Void PortConnectorType::ActualLength::set(System::UInt64 value) { + this->actualLengthField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ PortConnectorType::UsbPortProperties::get() { + return this->usbPortPropertiesField; + } + inline System::Void PortConnectorType::UsbPortProperties::set(Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ value) { + this->usbPortPropertiesField = value; + } + + inline System::UInt16 PortConnectorType::CompanionIndex::get() { + return this->companionIndexField; + } + inline System::Void PortConnectorType::CompanionIndex::set(System::UInt16 value) { + this->companionIndexField = value; + } + + inline System::UInt16 PortConnectorType::CompanionPortNumber::get() { + return this->companionPortNumberField; + } + inline System::Void PortConnectorType::CompanionPortNumber::set(System::UInt16 value) { + this->companionPortNumberField = value; + } + + inline System::String^ PortConnectorType::CompanionHubSymbolicLinkName::get() { + return this->companionHubSymbolicLinkNameField; + } + inline System::Void PortConnectorType::CompanionHubSymbolicLinkName::set(System::String^ value) { + this->companionHubSymbolicLinkNameField = value; + } + + + inline System::Boolean UsbPortPropertiesType::PortIsUserConnectable::get() { + return this->portIsUserConnectableField; + } + inline System::Void UsbPortPropertiesType::PortIsUserConnectable::set(System::Boolean value) { + this->portIsUserConnectableField = value; + } + + inline System::Boolean UsbPortPropertiesType::PortIsDebugCapable::get() { + return this->portIsDebugCapableField; + } + inline System::Void UsbPortPropertiesType::PortIsDebugCapable::set(System::Boolean value) { + this->portIsDebugCapableField = value; + } + + + inline System::UInt64 NodeConnectionInfoExV2Type::ConnectionIndex::get() { + return this->connectionIndexField; + } + inline System::Void NodeConnectionInfoExV2Type::ConnectionIndex::set(System::UInt64 value) { + this->connectionIndexField = value; + } + + inline System::UInt64 NodeConnectionInfoExV2Type::Length::get() { + return this->lengthField; + } + inline System::Void NodeConnectionInfoExV2Type::Length::set(System::UInt64 value) { + this->lengthField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::Usb110Supported::get() { + return this->usb110SupportedField; + } + inline System::Void NodeConnectionInfoExV2Type::Usb110Supported::set(System::Boolean value) { + this->usb110SupportedField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::Usb200Supported::get() { + return this->usb200SupportedField; + } + inline System::Void NodeConnectionInfoExV2Type::Usb200Supported::set(System::Boolean value) { + this->usb200SupportedField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::Usb300Supported::get() { + return this->usb300SupportedField; + } + inline System::Void NodeConnectionInfoExV2Type::Usb300Supported::set(System::Boolean value) { + this->usb300SupportedField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedOrHigher::get() { + return this->deviceIsOperatingAtSuperSpeedOrHigherField; + } + inline System::Void NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedOrHigher::set(System::Boolean value) { + this->deviceIsOperatingAtSuperSpeedOrHigherField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsSuperSpeedCapableOrHigher::get() { + return this->deviceIsSuperSpeedCapableOrHigherField; + } + inline System::Void NodeConnectionInfoExV2Type::DeviceIsSuperSpeedCapableOrHigher::set(System::Boolean value) { + this->deviceIsSuperSpeedCapableOrHigherField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedPlusOrHigher::get() { + return this->deviceIsOperatingAtSuperSpeedPlusOrHigherField; + } + inline System::Void NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedPlusOrHigher::set(System::Boolean value) { + this->deviceIsOperatingAtSuperSpeedPlusOrHigherField = value; + } + + inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsSuperSpeedPlusCapableOrHigher::get() { + return this->deviceIsSuperSpeedPlusCapableOrHigherField; + } + inline System::Void NodeConnectionInfoExV2Type::DeviceIsSuperSpeedPlusCapableOrHigher::set(System::Boolean value) { + this->deviceIsSuperSpeedPlusCapableOrHigherField = value; + } + + + inline System::String^ UsbBillboardSVIDType::Description::get() { + return this->descriptionField; + } + inline System::Void UsbBillboardSVIDType::Description::set(System::String^ value) { + this->descriptionField = value; + } + + inline System::String^ UsbBillboardSVIDType::AlternateModeString::get() { + return this->alternateModeStringField; + } + inline System::Void UsbBillboardSVIDType::AlternateModeString::set(System::String^ value) { + this->alternateModeStringField = value; + } + + inline System::UInt16 UsbBillboardSVIDType::WSVID::get() { + return this->wSVIDField; + } + inline System::Void UsbBillboardSVIDType::WSVID::set(System::UInt16 value) { + this->wSVIDField = value; + } + + inline System::Byte UsbBillboardSVIDType::BAlternateMode::get() { + return this->bAlternateModeField; + } + inline System::Void UsbBillboardSVIDType::BAlternateMode::set(System::Byte value) { + this->bAlternateModeField = value; + } + + inline System::Byte UsbBillboardSVIDType::IAlternateModeString::get() { + return this->iAlternateModeStringField; + } + inline System::Void UsbBillboardSVIDType::IAlternateModeString::set(System::Byte value) { + this->iAlternateModeStringField = value; + } + + + inline System::String^ UsbBillboardCapabilityDescriptorType::VConnPower::get() { + return this->vConnPowerField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::VConnPower::set(System::String^ value) { + this->vConnPowerField = value; + } + + inline System::String^ UsbBillboardCapabilityDescriptorType::BillboardDescriptorErrors::get() { + return this->billboardDescriptorErrorsField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::BillboardDescriptorErrors::set(System::String^ value) { + this->billboardDescriptorErrorsField = value; + } + + inline System::String^ UsbBillboardCapabilityDescriptorType::AddtionalInfoURL::get() { + return this->addtionalInfoURLField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::AddtionalInfoURL::set(System::String^ value) { + this->addtionalInfoURLField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ UsbBillboardCapabilityDescriptorType::UsbBillboardSVID::get() { + return this->usbBillboardSVIDField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::UsbBillboardSVID::set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ value) { + this->usbBillboardSVIDField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::BDevCapabilityType::get() { + return this->bDevCapabilityTypeField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::BDevCapabilityType::set(System::Byte value) { + this->bDevCapabilityTypeField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::IAddtionalInfoURL::get() { + return this->iAddtionalInfoURLField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::IAddtionalInfoURL::set(System::Byte value) { + this->iAddtionalInfoURLField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::BNumberOfAlternateModes::get() { + return this->bNumberOfAlternateModesField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::BNumberOfAlternateModes::set(System::Byte value) { + this->bNumberOfAlternateModesField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::BPreferredAlternateMode::get() { + return this->bPreferredAlternateModeField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::BPreferredAlternateMode::set(System::Byte value) { + this->bPreferredAlternateModeField = value; + } + + inline System::Byte UsbBillboardCapabilityDescriptorType::CalculatedBLength::get() { + return this->calculatedBLengthField; + } + inline System::Void UsbBillboardCapabilityDescriptorType::CalculatedBLength::set(System::Byte value) { + this->calculatedBLengthField = value; + } + + + inline System::String^ UsbDispContIdCapExtDescriptorType::ReservedBitError::get() { + return this->reservedBitErrorField; + } + inline System::Void UsbDispContIdCapExtDescriptorType::ReservedBitError::set(System::String^ value) { + this->reservedBitErrorField = value; + } + + inline System::String^ UsbDispContIdCapExtDescriptorType::ContainerIdStr::get() { + return this->containerIdStrField; + } + inline System::Void UsbDispContIdCapExtDescriptorType::ContainerIdStr::set(System::String^ value) { + this->containerIdStrField = value; + } + + inline System::Byte UsbDispContIdCapExtDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDispContIdCapExtDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDispContIdCapExtDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDispContIdCapExtDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbDispContIdCapExtDescriptorType::BReserved::get() { + return this->bReservedField; + } + inline System::Void UsbDispContIdCapExtDescriptorType::BReserved::set(System::Byte value) { + this->bReservedField = value; + } + + inline System::Byte UsbDispContIdCapExtDescriptorType::BDevCapabilityType::get() { + return this->bDevCapabilityTypeField; + } + inline System::Void UsbDispContIdCapExtDescriptorType::BDevCapabilityType::set(System::Byte value) { + this->bDevCapabilityTypeField = value; + } + + + inline System::String^ UsbUsb20ExtensionDescriptorType::ReservedBitError::get() { + return this->reservedBitErrorField; + } + inline System::Void UsbUsb20ExtensionDescriptorType::ReservedBitError::set(System::String^ value) { + this->reservedBitErrorField = value; + } + + inline System::Byte UsbUsb20ExtensionDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbUsb20ExtensionDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbUsb20ExtensionDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbUsb20ExtensionDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbUsb20ExtensionDescriptorType::BDevCapabilityType::get() { + return this->bDevCapabilityTypeField; + } + inline System::Void UsbUsb20ExtensionDescriptorType::BDevCapabilityType::set(System::Byte value) { + this->bDevCapabilityTypeField = value; + } + + inline System::UInt64 UsbUsb20ExtensionDescriptorType::BmAttributes::get() { + return this->bmAttributesField; + } + inline System::Void UsbUsb20ExtensionDescriptorType::BmAttributes::set(System::UInt64 value) { + this->bmAttributesField = value; + } + + inline System::Boolean UsbUsb20ExtensionDescriptorType::SupportsLinkPowerManagement::get() { + return this->supportsLinkPowerManagementField; + } + inline System::Void UsbUsb20ExtensionDescriptorType::SupportsLinkPowerManagement::set(System::Boolean value) { + this->supportsLinkPowerManagementField = value; + } + + + inline System::String^ UsbSuperSpeedExtensionDescriptorType::ReservedAttributesBitError::get() { + return this->reservedAttributesBitErrorField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::ReservedAttributesBitError::set(System::String^ value) { + this->reservedAttributesBitErrorField = value; + } + + inline System::String^ UsbSuperSpeedExtensionDescriptorType::ReservedSpeedBitError::get() { + return this->reservedSpeedBitErrorField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::ReservedSpeedBitError::set(System::String^ value) { + this->reservedSpeedBitErrorField = value; + } + + inline System::String^ UsbSuperSpeedExtensionDescriptorType::ReservedSpeedError::get() { + return this->reservedSpeedErrorField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::ReservedSpeedError::set(System::String^ value) { + this->reservedSpeedErrorField = value; + } + + inline System::Byte UsbSuperSpeedExtensionDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbSuperSpeedExtensionDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbSuperSpeedExtensionDescriptorType::BDevCapabilityType::get() { + return this->bDevCapabilityTypeField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::BDevCapabilityType::set(System::Byte value) { + this->bDevCapabilityTypeField = value; + } + + inline System::UInt64 UsbSuperSpeedExtensionDescriptorType::BmAttributes::get() { + return this->bmAttributesField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::BmAttributes::set(System::UInt64 value) { + this->bmAttributesField = value; + } + + inline System::Boolean UsbSuperSpeedExtensionDescriptorType::LatencyToleranceMsgCapable::get() { + return this->latencyToleranceMsgCapableField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::LatencyToleranceMsgCapable::set(System::Boolean value) { + this->latencyToleranceMsgCapableField = value; + } + + inline System::Byte UsbSuperSpeedExtensionDescriptorType::BFunctionalitySupport::get() { + return this->bFunctionalitySupportField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::BFunctionalitySupport::set(System::Byte value) { + this->bFunctionalitySupportField = value; + } + + inline System::Byte UsbSuperSpeedExtensionDescriptorType::BU1DevExitLat::get() { + return this->bU1DevExitLatField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::BU1DevExitLat::set(System::Byte value) { + this->bU1DevExitLatField = value; + } + + inline System::UInt16 UsbSuperSpeedExtensionDescriptorType::WSpeedsSupported::get() { + return this->wSpeedsSupportedField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::WSpeedsSupported::set(System::UInt16 value) { + this->wSpeedsSupportedField = value; + } + + inline System::UInt16 UsbSuperSpeedExtensionDescriptorType::WU2DevExitLat::get() { + return this->wU2DevExitLatField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::WU2DevExitLat::set(System::UInt16 value) { + this->wU2DevExitLatField = value; + } + + inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsLowSpeed::get() { + return this->supportsLowSpeedField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsLowSpeed::set(System::Boolean value) { + this->supportsLowSpeedField = value; + } + + inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsFullSpeed::get() { + return this->supportsFullSpeedField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsFullSpeed::set(System::Boolean value) { + this->supportsFullSpeedField = value; + } + + inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsHighSpeed::get() { + return this->supportsHighSpeedField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsHighSpeed::set(System::Boolean value) { + this->supportsHighSpeedField = value; + } + + inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsSuperSpeed::get() { + return this->supportsSuperSpeedField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsSuperSpeed::set(System::Boolean value) { + this->supportsSuperSpeedField = value; + } + + inline System::String^ UsbSuperSpeedExtensionDescriptorType::LowestSpeed::get() { + return this->lowestSpeedField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::LowestSpeed::set(System::String^ value) { + this->lowestSpeedField = value; + } + + inline System::String^ UsbSuperSpeedExtensionDescriptorType::U1DevExitLatencyString::get() { + return this->u1DevExitLatencyStringField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::U1DevExitLatencyString::set(System::String^ value) { + this->u1DevExitLatencyStringField = value; + } + + inline System::String^ UsbSuperSpeedExtensionDescriptorType::U2DevExitLatencyString::get() { + return this->u2DevExitLatencyStringField; + } + inline System::Void UsbSuperSpeedExtensionDescriptorType::U2DevExitLatencyString::set(System::String^ value) { + this->u2DevExitLatencyStringField = value; + } + + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ UsbBosDescriptorType::UnknownDescriptor::get() { + return this->unknownDescriptorField; + } + inline System::Void UsbBosDescriptorType::UnknownDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ value) { + this->unknownDescriptorField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ UsbBosDescriptorType::UsbSuperSpeedExtensionDescriptor::get() { + return this->usbSuperSpeedExtensionDescriptorField; + } + inline System::Void UsbBosDescriptorType::UsbSuperSpeedExtensionDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ value) { + this->usbSuperSpeedExtensionDescriptorField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ UsbBosDescriptorType::UsbUsb20ExtensionDescriptor::get() { + return this->usbUsb20ExtensionDescriptorField; + } + inline System::Void UsbBosDescriptorType::UsbUsb20ExtensionDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ value) { + this->usbUsb20ExtensionDescriptorField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ UsbBosDescriptorType::UsbDispContIdCapExtDescriptor::get() { + return this->usbDispContIdCapExtDescriptorField; + } + inline System::Void UsbBosDescriptorType::UsbDispContIdCapExtDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ value) { + this->usbDispContIdCapExtDescriptorField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ UsbBosDescriptorType::UsbBillboardCapabilityDescriptor::get() { + return this->usbBillboardCapabilityDescriptorField; + } + inline System::Void UsbBosDescriptorType::UsbBillboardCapabilityDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ value) { + this->usbBillboardCapabilityDescriptorField = value; + } + + inline System::Byte UsbBosDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbBosDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbBosDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbBosDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::UInt16 UsbBosDescriptorType::WTotalLength::get() { + return this->wTotalLengthField; + } + inline System::Void UsbBosDescriptorType::WTotalLength::set(System::UInt16 value) { + this->wTotalLengthField = value; + } + + inline System::Byte UsbBosDescriptorType::BNumDeviceCaps::get() { + return this->bNumDeviceCapsField; + } + inline System::Void UsbBosDescriptorType::BNumDeviceCaps::set(System::Byte value) { + this->bNumDeviceCapsField = value; + } + + + inline System::String^ UsbDeviceUnknownDescriptorType::UnknownDescriptor::get() { + return this->unknownDescriptorField; + } + inline System::Void UsbDeviceUnknownDescriptorType::UnknownDescriptor::set(System::String^ value) { + this->unknownDescriptorField = value; + } + + inline System::Byte UsbDeviceUnknownDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDeviceUnknownDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDeviceUnknownDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceUnknownDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + + inline Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ UsbDeviceIADDescriptorType::FunctionDetails::get() { + return this->functionDetailsField; + } + inline System::Void UsbDeviceIADDescriptorType::FunctionDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value) { + this->functionDetailsField = value; + } + + inline System::String^ UsbDeviceIADDescriptorType::InterfaceError::get() { + return this->interfaceErrorField; + } + inline System::Void UsbDeviceIADDescriptorType::InterfaceError::set(System::String^ value) { + this->interfaceErrorField = value; + } + + inline System::String^ UsbDeviceIADDescriptorType::FunctionClassError::get() { + return this->functionClassErrorField; + } + inline System::Void UsbDeviceIADDescriptorType::FunctionClassError::set(System::String^ value) { + this->functionClassErrorField = value; + } + + inline System::String^ UsbDeviceIADDescriptorType::Protocol::get() { + return this->protocolField; + } + inline System::Void UsbDeviceIADDescriptorType::Protocol::set(System::String^ value) { + this->protocolField = value; + } + + inline System::String^ UsbDeviceIADDescriptorType::StringDesc::get() { + return this->stringDescField; + } + inline System::Void UsbDeviceIADDescriptorType::StringDesc::set(System::String^ value) { + this->stringDescField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDeviceIADDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceIADDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BFirstInterface::get() { + return this->bFirstInterfaceField; + } + inline System::Void UsbDeviceIADDescriptorType::BFirstInterface::set(System::Byte value) { + this->bFirstInterfaceField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BInterfaceCount::get() { + return this->bInterfaceCountField; + } + inline System::Void UsbDeviceIADDescriptorType::BInterfaceCount::set(System::Byte value) { + this->bInterfaceCountField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BFunctionClass::get() { + return this->bFunctionClassField; + } + inline System::Void UsbDeviceIADDescriptorType::BFunctionClass::set(System::Byte value) { + this->bFunctionClassField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BFunctionSubclass::get() { + return this->bFunctionSubclassField; + } + inline System::Void UsbDeviceIADDescriptorType::BFunctionSubclass::set(System::Byte value) { + this->bFunctionSubclassField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::BFunctionProtocol::get() { + return this->bFunctionProtocolField; + } + inline System::Void UsbDeviceIADDescriptorType::BFunctionProtocol::set(System::Byte value) { + this->bFunctionProtocolField = value; + } + + inline System::Byte UsbDeviceIADDescriptorType::IFunction::get() { + return this->iFunctionField; + } + inline System::Void UsbDeviceIADDescriptorType::IFunction::set(System::Byte value) { + this->iFunctionField = value; + } + + + inline System::String^ UsbDeviceClassType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void UsbDeviceClassType::DeviceClass::set(System::String^ value) { + this->deviceClassField = value; + } + + inline System::String^ UsbDeviceClassType::DeviceSubclass::get() { + return this->deviceSubclassField; + } + inline System::Void UsbDeviceClassType::DeviceSubclass::set(System::String^ value) { + this->deviceSubclassField = value; + } + + + inline System::Byte UsbDeviceOTGDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDeviceOTGDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDeviceOTGDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceOTGDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbDeviceOTGDescriptorType::BmAttributes::get() { + return this->bmAttributesField; + } + inline System::Void UsbDeviceOTGDescriptorType::BmAttributes::set(System::Byte value) { + this->bmAttributesField = value; + } + + inline System::String^ UsbDeviceOTGDescriptorType::AttributesString::get() { + return this->attributesStringField; + } + inline System::Void UsbDeviceOTGDescriptorType::AttributesString::set(System::String^ value) { + this->attributesStringField = value; + } + + + inline System::Byte UsbDeviceHidOptionalDescriptorsType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceHidOptionalDescriptorsType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::UInt16 UsbDeviceHidOptionalDescriptorsType::WDescriptorLength::get() { + return this->wDescriptorLengthField; + } + inline System::Void UsbDeviceHidOptionalDescriptorsType::WDescriptorLength::set(System::UInt16 value) { + this->wDescriptorLengthField = value; + } + + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ UsbDeviceHidDescriptorType::OptionalDescriptor::get() { + return this->optionalDescriptorField; + } + inline System::Void UsbDeviceHidDescriptorType::OptionalDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ value) { + this->optionalDescriptorField = value; + } + + inline System::Byte UsbDeviceHidDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDeviceHidDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDeviceHidDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceHidDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::UInt16 UsbDeviceHidDescriptorType::BcdHID::get() { + return this->bcdHIDField; + } + inline System::Void UsbDeviceHidDescriptorType::BcdHID::set(System::UInt16 value) { + this->bcdHIDField = value; + } + + inline System::Byte UsbDeviceHidDescriptorType::BCountryCode::get() { + return this->bCountryCodeField; + } + inline System::Void UsbDeviceHidDescriptorType::BCountryCode::set(System::Byte value) { + this->bCountryCodeField = value; + } + + inline System::Byte UsbDeviceHidDescriptorType::BNumDescriptors::get() { + return this->bNumDescriptorsField; + } + inline System::Void UsbDeviceHidDescriptorType::BNumDescriptors::set(System::Byte value) { + this->bNumDescriptorsField = value; + } + + + inline Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ UsbDeviceInterfaceDescriptorType::InterfaceDetails::get() { + return this->interfaceDetailsField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::InterfaceDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value) { + this->interfaceDetailsField = value; + } + + inline System::String^ UsbDeviceInterfaceDescriptorType::ProtocolError::get() { + return this->protocolErrorField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::ProtocolError::set(System::String^ value) { + this->protocolErrorField = value; + } + + inline System::String^ UsbDeviceInterfaceDescriptorType::StringDesc::get() { + return this->stringDescField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::StringDesc::set(System::String^ value) { + this->stringDescField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceNumber::get() { + return this->bInterfaceNumberField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceNumber::set(System::Byte value) { + this->bInterfaceNumberField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BAlternateSetting::get() { + return this->bAlternateSettingField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BAlternateSetting::set(System::Byte value) { + this->bAlternateSettingField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BNumEndpoints::get() { + return this->bNumEndpointsField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BNumEndpoints::set(System::Byte value) { + this->bNumEndpointsField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceClass::get() { + return this->bInterfaceClassField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceClass::set(System::Byte value) { + this->bInterfaceClassField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceSubclass::get() { + return this->bInterfaceSubclassField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceSubclass::set(System::Byte value) { + this->bInterfaceSubclassField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceProtocol::get() { + return this->bInterfaceProtocolField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceProtocol::set(System::Byte value) { + this->bInterfaceProtocolField = value; + } + + inline System::Byte UsbDeviceInterfaceDescriptorType::IInterface::get() { + return this->iInterfaceField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::IInterface::set(System::Byte value) { + this->iInterfaceField = value; + } + + inline System::UInt16 UsbDeviceInterfaceDescriptorType::WNumClasses::get() { + return this->wNumClassesField; + } + inline System::Void UsbDeviceInterfaceDescriptorType::WNumClasses::set(System::UInt16 value) { + this->wNumClassesField = value; + } + + + inline System::String^ UsbDeviceQualifierDescriptorType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void UsbDeviceQualifierDescriptorType::DeviceClass::set(System::String^ value) { + this->deviceClassField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytes::get() { + return this->maxPacketSizeInBytesField; + } + inline System::Void UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytes::set(System::Byte value) { + this->maxPacketSizeInBytesField = value; + } + + inline System::Boolean UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytesSpecified::get() { + return this->maxPacketSizeInBytesFieldSpecified; + } + inline System::Void UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytesSpecified::set(System::Boolean value) { + this->maxPacketSizeInBytesFieldSpecified = value; + } + + inline System::String^ UsbDeviceQualifierDescriptorType::DeviceClassError::get() { + return this->deviceClassErrorField; + } + inline System::Void UsbDeviceQualifierDescriptorType::DeviceClassError::set(System::String^ value) { + this->deviceClassErrorField = value; + } + + inline System::String^ UsbDeviceQualifierDescriptorType::DeviceSubclassError::get() { + return this->deviceSubclassErrorField; + } + inline System::Void UsbDeviceQualifierDescriptorType::DeviceSubclassError::set(System::String^ value) { + this->deviceSubclassErrorField = value; + } + + inline System::String^ UsbDeviceQualifierDescriptorType::DeviceProtocolError::get() { + return this->deviceProtocolErrorField; + } + inline System::Void UsbDeviceQualifierDescriptorType::DeviceProtocolError::set(System::String^ value) { + this->deviceProtocolErrorField = value; + } + + inline System::String^ UsbDeviceQualifierDescriptorType::DeviceNumConfigError::get() { + return this->deviceNumConfigErrorField; + } + inline System::Void UsbDeviceQualifierDescriptorType::DeviceNumConfigError::set(System::String^ value) { + this->deviceNumConfigErrorField = value; + } + + inline System::String^ UsbDeviceQualifierDescriptorType::ReservedError::get() { + return this->reservedErrorField; + } + inline System::Void UsbDeviceQualifierDescriptorType::ReservedError::set(System::String^ value) { + this->reservedErrorField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbDeviceQualifierDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbDeviceQualifierDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::UInt16 UsbDeviceQualifierDescriptorType::BcdUSB::get() { + return this->bcdUSBField; + } + inline System::Void UsbDeviceQualifierDescriptorType::BcdUSB::set(System::UInt16 value) { + this->bcdUSBField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::BDeviceClass::get() { + return this->bDeviceClassField; + } + inline System::Void UsbDeviceQualifierDescriptorType::BDeviceClass::set(System::Byte value) { + this->bDeviceClassField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::BDeviceSubclass::get() { + return this->bDeviceSubclassField; + } + inline System::Void UsbDeviceQualifierDescriptorType::BDeviceSubclass::set(System::Byte value) { + this->bDeviceSubclassField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::BDeviceProtocol::get() { + return this->bDeviceProtocolField; + } + inline System::Void UsbDeviceQualifierDescriptorType::BDeviceProtocol::set(System::Byte value) { + this->bDeviceProtocolField = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::BMaxPacketSize0::get() { + return this->bMaxPacketSize0Field; + } + inline System::Void UsbDeviceQualifierDescriptorType::BMaxPacketSize0::set(System::Byte value) { + this->bMaxPacketSize0Field = value; + } + + inline System::Byte UsbDeviceQualifierDescriptorType::NumConfigurations::get() { + return this->numConfigurationsField; + } + inline System::Void UsbDeviceQualifierDescriptorType::NumConfigurations::set(System::Byte value) { + this->numConfigurationsField = value; + } + + + inline System::String^ UsbConfigurationDescriptorType::ConfigDescError::get() { + return this->configDescErrorField; + } + inline System::Void UsbConfigurationDescriptorType::ConfigDescError::set(System::String^ value) { + this->configDescErrorField = value; + } + + inline System::String^ UsbConfigurationDescriptorType::ConfValueError::get() { + return this->confValueErrorField; + } + inline System::Void UsbConfigurationDescriptorType::ConfValueError::set(System::String^ value) { + this->confValueErrorField = value; + } + + inline System::String^ UsbConfigurationDescriptorType::ConfStringDesc::get() { + return this->confStringDescField; + } + inline System::Void UsbConfigurationDescriptorType::ConfStringDesc::set(System::String^ value) { + this->confStringDescField = value; + } + + inline System::String^ UsbConfigurationDescriptorType::AttributesStr::get() { + return this->attributesStrField; + } + inline System::Void UsbConfigurationDescriptorType::AttributesStr::set(System::String^ value) { + this->attributesStrField = value; + } + + inline System::String^ UsbConfigurationDescriptorType::MaxCurrent::get() { + return this->maxCurrentField; + } + inline System::Void UsbConfigurationDescriptorType::MaxCurrent::set(System::String^ value) { + this->maxCurrentField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::BLength::get() { + return this->bLengthField; + } + inline System::Void UsbConfigurationDescriptorType::BLength::set(System::Byte value) { + this->bLengthField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::BDescriptorType::get() { + return this->bDescriptorTypeField; + } + inline System::Void UsbConfigurationDescriptorType::BDescriptorType::set(System::Byte value) { + this->bDescriptorTypeField = value; + } + + inline System::UInt16 UsbConfigurationDescriptorType::WTotalLength::get() { + return this->wTotalLengthField; + } + inline System::Void UsbConfigurationDescriptorType::WTotalLength::set(System::UInt16 value) { + this->wTotalLengthField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::BNumInterfaces::get() { + return this->bNumInterfacesField; + } + inline System::Void UsbConfigurationDescriptorType::BNumInterfaces::set(System::Byte value) { + this->bNumInterfacesField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::BConfigurationValue::get() { + return this->bConfigurationValueField; + } + inline System::Void UsbConfigurationDescriptorType::BConfigurationValue::set(System::Byte value) { + this->bConfigurationValueField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::IConfiguration::get() { + return this->iConfigurationField; + } + inline System::Void UsbConfigurationDescriptorType::IConfiguration::set(System::Byte value) { + this->iConfigurationField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::BmAttributes::get() { + return this->bmAttributesField; + } + inline System::Void UsbConfigurationDescriptorType::BmAttributes::set(System::Byte value) { + this->bmAttributesField = value; + } + + inline System::Byte UsbConfigurationDescriptorType::MaxPower::get() { + return this->maxPowerField; + } + inline System::Void UsbConfigurationDescriptorType::MaxPower::set(System::Byte value) { + this->maxPowerField = value; + } + + + inline System::String^ UsbDeviceConfigurationType::DeviceQualifierError::get() { + return this->deviceQualifierErrorField; + } + inline System::Void UsbDeviceConfigurationType::DeviceQualifierError::set(System::String^ value) { + this->deviceQualifierErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::SpeedConfigurationError::get() { + return this->speedConfigurationErrorField; + } + inline System::Void UsbDeviceConfigurationType::SpeedConfigurationError::set(System::String^ value) { + this->speedConfigurationErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::DeviceConfigurationError::get() { + return this->deviceConfigurationErrorField; + } + inline System::Void UsbDeviceConfigurationType::DeviceConfigurationError::set(System::String^ value) { + this->deviceConfigurationErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::InterfaceError::get() { + return this->interfaceErrorField; + } + inline System::Void UsbDeviceConfigurationType::InterfaceError::set(System::String^ value) { + this->interfaceErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::PreReleaseError::get() { + return this->preReleaseErrorField; + } + inline System::Void UsbDeviceConfigurationType::PreReleaseError::set(System::String^ value) { + this->preReleaseErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::EndpointError::get() { + return this->endpointErrorField; + } + inline System::Void UsbDeviceConfigurationType::EndpointError::set(System::String^ value) { + this->endpointErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::HidError::get() { + return this->hidErrorField; + } + inline System::Void UsbDeviceConfigurationType::HidError::set(System::String^ value) { + this->hidErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::OtgError::get() { + return this->otgErrorField; + } + inline System::Void UsbDeviceConfigurationType::OtgError::set(System::String^ value) { + this->otgErrorField = value; + } + + inline System::String^ UsbDeviceConfigurationType::IadError::get() { + return this->iadErrorField; + } + inline System::Void UsbDeviceConfigurationType::IadError::set(System::String^ value) { + this->iadErrorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ UsbDeviceConfigurationType::DeviceDetails::get() { + return this->deviceDetailsField; + } + inline System::Void UsbDeviceConfigurationType::DeviceDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value) { + this->deviceDetailsField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ UsbDeviceConfigurationType::ConfigurationDescriptor::get() { + return this->configurationDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::ConfigurationDescriptor::set(Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ value) { + this->configurationDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ UsbDeviceConfigurationType::DeviceQualifierDescriptor::get() { + return this->deviceQualifierDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::DeviceQualifierDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ value) { + this->deviceQualifierDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ UsbDeviceConfigurationType::InterfaceDescriptor::get() { + return this->interfaceDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::InterfaceDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ value) { + this->interfaceDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ UsbDeviceConfigurationType::EndpointDescriptor::get() { + return this->endpointDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::EndpointDescriptor::set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value) { + this->endpointDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ UsbDeviceConfigurationType::HidDescriptor::get() { + return this->hidDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::HidDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ value) { + this->hidDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ UsbDeviceConfigurationType::OtgDescriptor::get() { + return this->otgDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::OtgDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ value) { + this->otgDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ UsbDeviceConfigurationType::IadDescriptor::get() { + return this->iadDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::IadDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ value) { + this->iadDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ UsbDeviceConfigurationType::UnknownDescriptor::get() { + return this->unknownDescriptorField; + } + inline System::Void UsbDeviceConfigurationType::UnknownDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ value) { + this->unknownDescriptorField = value; + } + + + inline System::Byte EndpointDescriptorType::Length::get() { + return this->lengthField; + } + inline System::Void EndpointDescriptorType::Length::set(System::Byte value) { + this->lengthField = value; + } + + inline System::Byte EndpointDescriptorType::DescriptorType::get() { + return this->descriptorTypeField; + } + inline System::Void EndpointDescriptorType::DescriptorType::set(System::Byte value) { + this->descriptorTypeField = value; + } + + inline System::Byte EndpointDescriptorType::EndpointAddress::get() { + return this->endpointAddressField; + } + inline System::Void EndpointDescriptorType::EndpointAddress::set(System::Byte value) { + this->endpointAddressField = value; + } + + inline System::Byte EndpointDescriptorType::Attributes::get() { + return this->attributesField; + } + inline System::Void EndpointDescriptorType::Attributes::set(System::Byte value) { + this->attributesField = value; + } + + inline System::UInt16 EndpointDescriptorType::MaxPacketSize::get() { + return this->maxPacketSizeField; + } + inline System::Void EndpointDescriptorType::MaxPacketSize::set(System::UInt16 value) { + this->maxPacketSizeField = value; + } + + inline System::Byte EndpointDescriptorType::Interval::get() { + return this->intervalField; + } + inline System::Void EndpointDescriptorType::Interval::set(System::Byte value) { + this->intervalField = value; + } + + inline System::UInt16 EndpointDescriptorType::WInterval::get() { + return this->wIntervalField; + } + inline System::Void EndpointDescriptorType::WInterval::set(System::UInt16 value) { + this->wIntervalField = value; + } + + inline System::Byte EndpointDescriptorType::SyncAddress::get() { + return this->syncAddressField; + } + inline System::Void EndpointDescriptorType::SyncAddress::set(System::Byte value) { + this->syncAddressField = value; + } + + inline System::String^ EndpointDescriptorType::EndpointDirection::get() { + return this->endpointDirectionField; + } + inline System::Void EndpointDescriptorType::EndpointDirection::set(System::String^ value) { + this->endpointDirectionField = value; + } + + inline System::Byte EndpointDescriptorType::EndpointId::get() { + return this->endpointIdField; + } + inline System::Void EndpointDescriptorType::EndpointId::set(System::Byte value) { + this->endpointIdField = value; + } + + inline System::String^ EndpointDescriptorType::EndpointType::get() { + return this->endpointTypeField; + } + inline System::Void EndpointDescriptorType::EndpointType::set(System::String^ value) { + this->endpointTypeField = value; + } + + inline System::String^ EndpointDescriptorType::EndpointPacketInfo::get() { + return this->endpointPacketInfoField; + } + inline System::Void EndpointDescriptorType::EndpointPacketInfo::set(System::String^ value) { + this->endpointPacketInfoField = value; + } + + inline System::String^ EndpointDescriptorType::EndpointPacketSizeValidation::get() { + return this->endpointPacketSizeValidationField; + } + inline System::Void EndpointDescriptorType::EndpointPacketSizeValidation::set(System::String^ value) { + this->endpointPacketSizeValidationField = value; + } + + + inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ UsbDeviceType::ConnectionInfo::get() { + return this->connectionInfoField; + } + inline System::Void UsbDeviceType::ConnectionInfo::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value) { + this->connectionInfoField = value; + } + + inline Microsoft::Kits::Samples::Usb::PortConnectorType^ UsbDeviceType::PortConnector::get() { + return this->portConnectorField; + } + inline System::Void UsbDeviceType::PortConnector::set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value) { + this->portConnectorField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ UsbDeviceType::DeviceConfiguration::get() { + return this->deviceConfigurationField; + } + inline System::Void UsbDeviceType::DeviceConfiguration::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value) { + this->deviceConfigurationField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ UsbDeviceType::BosDescriptor::get() { + return this->bosDescriptorField; + } + inline System::Void UsbDeviceType::BosDescriptor::set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value) { + this->bosDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ UsbDeviceType::ConnectionInfoV2::get() { + return this->connectionInfoV2Field; + } + inline System::Void UsbDeviceType::ConnectionInfoV2::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value) { + this->connectionInfoV2Field = value; + } + + inline System::String^ UsbDeviceType::UsbPortNumber::get() { + return this->usbPortNumberField; + } + inline System::Void UsbDeviceType::UsbPortNumber::set(System::String^ value) { + this->usbPortNumberField = value; + } + + inline System::String^ UsbDeviceType::ServiceName::get() { + return this->serviceNameField; + } + inline System::Void UsbDeviceType::ServiceName::set(System::String^ value) { + this->serviceNameField = value; + } + + inline System::String^ UsbDeviceType::HwId::get() { + return this->hwIdField; + } + inline System::Void UsbDeviceType::HwId::set(System::String^ value) { + this->hwIdField = value; + } + + inline System::String^ UsbDeviceType::DeviceId::get() { + return this->deviceIdField; + } + inline System::Void UsbDeviceType::DeviceId::set(System::String^ value) { + this->deviceIdField = value; + } + + inline System::String^ UsbDeviceType::DeviceName::get() { + return this->deviceNameField; + } + inline System::Void UsbDeviceType::DeviceName::set(System::String^ value) { + this->deviceNameField = value; + } + + inline System::String^ UsbDeviceType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void UsbDeviceType::DeviceClass::set(System::String^ value) { + this->deviceClassField = value; + } + + inline System::String^ UsbDeviceType::UsbProtocol::get() { + return this->usbProtocolField; + } + inline System::Void UsbDeviceType::UsbProtocol::set(System::String^ value) { + this->usbProtocolField = value; + } + + + inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ NodeConnectionInfoExType::ConnectionInfoStruct::get() { + return this->connectionInfoStructField; + } + inline System::Void NodeConnectionInfoExType::ConnectionInfoStruct::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ value) { + this->connectionInfoStructField = value; + } + + inline System::String^ NodeConnectionInfoExType::IProductStringDescEn::get() { + return this->iProductStringDescEnField; + } + inline System::Void NodeConnectionInfoExType::IProductStringDescEn::set(System::String^ value) { + this->iProductStringDescEnField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ NodeConnectionInfoExType::DeviceClassDetails::get() { + return this->deviceClassDetailsField; + } + inline System::Void NodeConnectionInfoExType::DeviceClassDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ value) { + this->deviceClassDetailsField = value; + } + + inline System::Byte NodeConnectionInfoExType::MaxPacketSizeInBytes::get() { + return this->maxPacketSizeInBytesField; + } + inline System::Void NodeConnectionInfoExType::MaxPacketSizeInBytes::set(System::Byte value) { + this->maxPacketSizeInBytesField = value; + } + + inline System::String^ NodeConnectionInfoExType::VendorString::get() { + return this->vendorStringField; + } + inline System::Void NodeConnectionInfoExType::VendorString::set(System::String^ value) { + this->vendorStringField = value; + } + + inline System::String^ NodeConnectionInfoExType::ManufacturerString::get() { + return this->manufacturerStringField; + } + inline System::Void NodeConnectionInfoExType::ManufacturerString::set(System::String^ value) { + this->manufacturerStringField = value; + } + + inline System::String^ NodeConnectionInfoExType::ProductString::get() { + return this->productStringField; + } + inline System::Void NodeConnectionInfoExType::ProductString::set(System::String^ value) { + this->productStringField = value; + } + + inline System::String^ NodeConnectionInfoExType::LangIdString::get() { + return this->langIdStringField; + } + inline System::Void NodeConnectionInfoExType::LangIdString::set(System::String^ value) { + this->langIdStringField = value; + } + + inline System::String^ NodeConnectionInfoExType::SerialString::get() { + return this->serialStringField; + } + inline System::Void NodeConnectionInfoExType::SerialString::set(System::String^ value) { + this->serialStringField = value; + } + + inline System::String^ NodeConnectionInfoExType::PipeInfoError::get() { + return this->pipeInfoErrorField; + } + inline System::Void NodeConnectionInfoExType::PipeInfoError::set(System::String^ value) { + this->pipeInfoErrorField = value; + } + + inline System::String^ NodeConnectionInfoExType::LengthError::get() { + return this->lengthErrorField; + } + inline System::Void NodeConnectionInfoExType::LengthError::set(System::String^ value) { + this->lengthErrorField = value; + } + + inline System::String^ NodeConnectionInfoExType::DeviceError::get() { + return this->deviceErrorField; + } + inline System::Void NodeConnectionInfoExType::DeviceError::set(System::String^ value) { + this->deviceErrorField = value; + } + + inline System::String^ NodeConnectionInfoExType::PacketSizeError::get() { + return this->packetSizeErrorField; + } + inline System::Void NodeConnectionInfoExType::PacketSizeError::set(System::String^ value) { + this->packetSizeErrorField = value; + } + + inline System::String^ NodeConnectionInfoExType::ConfigurationCountError::get() { + return this->configurationCountErrorField; + } + inline System::Void NodeConnectionInfoExType::ConfigurationCountError::set(System::String^ value) { + this->configurationCountErrorField = value; + } + + + inline System::UInt64 NodeConnectionInfoExStructType::ConnectionIndex::get() { + return this->connectionIndexField; + } + inline System::Void NodeConnectionInfoExStructType::ConnectionIndex::set(System::UInt64 value) { + this->connectionIndexField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ NodeConnectionInfoExStructType::DeviceDescriptor::get() { + return this->deviceDescriptorField; + } + inline System::Void NodeConnectionInfoExStructType::DeviceDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ value) { + this->deviceDescriptorField = value; + } + + inline System::Byte NodeConnectionInfoExStructType::CurrentConfigurationValue::get() { + return this->currentConfigurationValueField; + } + inline System::Void NodeConnectionInfoExStructType::CurrentConfigurationValue::set(System::Byte value) { + this->currentConfigurationValueField = value; + } + + inline System::Byte NodeConnectionInfoExStructType::Speed::get() { + return this->speedField; + } + inline System::Void NodeConnectionInfoExStructType::Speed::set(System::Byte value) { + this->speedField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType NodeConnectionInfoExStructType::SpeedStr::get() { + return this->speedStrField; + } + inline System::Void NodeConnectionInfoExStructType::SpeedStr::set(Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType value) { + this->speedStrField = value; + } + + inline System::Boolean NodeConnectionInfoExStructType::DeviceIsHub::get() { + return this->deviceIsHubField; + } + inline System::Void NodeConnectionInfoExStructType::DeviceIsHub::set(System::Boolean value) { + this->deviceIsHubField = value; + } + + inline System::Byte NodeConnectionInfoExStructType::DeviceAddress::get() { + return this->deviceAddressField; + } + inline System::Void NodeConnectionInfoExStructType::DeviceAddress::set(System::Byte value) { + this->deviceAddressField = value; + } + + inline System::UInt64 NodeConnectionInfoExStructType::NumOfOpenPipes::get() { + return this->numOfOpenPipesField; + } + inline System::Void NodeConnectionInfoExStructType::NumOfOpenPipes::set(System::UInt64 value) { + this->numOfOpenPipesField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbConnectionStatusType NodeConnectionInfoExStructType::UsbConnectionStatus::get() { + return this->usbConnectionStatusField; + } + inline System::Void NodeConnectionInfoExStructType::UsbConnectionStatus::set(Microsoft::Kits::Samples::Usb::UsbConnectionStatusType value) { + this->usbConnectionStatusField = value; + } + + inline Microsoft::Kits::Samples::Usb::DevicePowerStateType NodeConnectionInfoExStructType::DevicePowerState::get() { + return this->devicePowerStateField; + } + inline System::Void NodeConnectionInfoExStructType::DevicePowerState::set(Microsoft::Kits::Samples::Usb::DevicePowerStateType value) { + this->devicePowerStateField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ NodeConnectionInfoExStructType::Pipe::get() { + return this->pipeField; + } + inline System::Void NodeConnectionInfoExStructType::Pipe::set(cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ value) { + this->pipeField = value; + } + + + inline System::Byte UsbDeviceDescriptorType::Length::get() { + return this->lengthField; + } + inline System::Void UsbDeviceDescriptorType::Length::set(System::Byte value) { + this->lengthField = value; + } + + inline System::Byte UsbDeviceDescriptorType::DescriptorType::get() { + return this->descriptorTypeField; + } + inline System::Void UsbDeviceDescriptorType::DescriptorType::set(System::Byte value) { + this->descriptorTypeField = value; + } + + inline System::UInt16 UsbDeviceDescriptorType::CdUSB::get() { + return this->cdUSBField; + } + inline System::Void UsbDeviceDescriptorType::CdUSB::set(System::UInt16 value) { + this->cdUSBField = value; + } + + inline System::Byte UsbDeviceDescriptorType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void UsbDeviceDescriptorType::DeviceClass::set(System::Byte value) { + this->deviceClassField = value; + } + + inline System::Byte UsbDeviceDescriptorType::DeviceSubclass::get() { + return this->deviceSubclassField; + } + inline System::Void UsbDeviceDescriptorType::DeviceSubclass::set(System::Byte value) { + this->deviceSubclassField = value; + } + + inline System::Byte UsbDeviceDescriptorType::DeviceProtocol::get() { + return this->deviceProtocolField; + } + inline System::Void UsbDeviceDescriptorType::DeviceProtocol::set(System::Byte value) { + this->deviceProtocolField = value; + } + + inline System::Byte UsbDeviceDescriptorType::MaxPacketSize0::get() { + return this->maxPacketSize0Field; + } + inline System::Void UsbDeviceDescriptorType::MaxPacketSize0::set(System::Byte value) { + this->maxPacketSize0Field = value; + } + + inline System::UInt16 UsbDeviceDescriptorType::IdVendor::get() { + return this->idVendorField; + } + inline System::Void UsbDeviceDescriptorType::IdVendor::set(System::UInt16 value) { + this->idVendorField = value; + } + + inline System::UInt16 UsbDeviceDescriptorType::IdProduct::get() { + return this->idProductField; + } + inline System::Void UsbDeviceDescriptorType::IdProduct::set(System::UInt16 value) { + this->idProductField = value; + } + + inline System::UInt16 UsbDeviceDescriptorType::CdDevice::get() { + return this->cdDeviceField; + } + inline System::Void UsbDeviceDescriptorType::CdDevice::set(System::UInt16 value) { + this->cdDeviceField = value; + } + + inline System::Byte UsbDeviceDescriptorType::IManufacturer::get() { + return this->iManufacturerField; + } + inline System::Void UsbDeviceDescriptorType::IManufacturer::set(System::Byte value) { + this->iManufacturerField = value; + } + + inline System::Byte UsbDeviceDescriptorType::IProduct::get() { + return this->iProductField; + } + inline System::Void UsbDeviceDescriptorType::IProduct::set(System::Byte value) { + this->iProductField = value; + } + + inline System::Byte UsbDeviceDescriptorType::ISerialNumber::get() { + return this->iSerialNumberField; + } + inline System::Void UsbDeviceDescriptorType::ISerialNumber::set(System::Byte value) { + this->iSerialNumberField = value; + } + + inline System::Byte UsbDeviceDescriptorType::NumConfigurations::get() { + return this->numConfigurationsField; + } + inline System::Void UsbDeviceDescriptorType::NumConfigurations::set(System::Byte value) { + this->numConfigurationsField = value; + } + + + inline Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ UsbPipeInfoType::EndpointDescriptor::get() { + return this->endpointDescriptorField; + } + inline System::Void UsbPipeInfoType::EndpointDescriptor::set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value) { + this->endpointDescriptorField = value; + } + + inline System::UInt64 UsbPipeInfoType::ScheduleOffset::get() { + return this->scheduleOffsetField; + } + inline System::Void UsbPipeInfoType::ScheduleOffset::set(System::UInt64 value) { + this->scheduleOffsetField = value; + } + + + inline System::String^ UsbDeviceClassDetailsType::DeviceType::get() { + return this->deviceTypeField; + } + inline System::Void UsbDeviceClassDetailsType::DeviceType::set(System::String^ value) { + this->deviceTypeField = value; + } + + inline System::String^ UsbDeviceClassDetailsType::DeviceTypeError::get() { + return this->deviceTypeErrorField; + } + inline System::Void UsbDeviceClassDetailsType::DeviceTypeError::set(System::String^ value) { + this->deviceTypeErrorField = value; + } + + inline System::String^ UsbDeviceClassDetailsType::SubclassType::get() { + return this->subclassTypeField; + } + inline System::Void UsbDeviceClassDetailsType::SubclassType::set(System::String^ value) { + this->subclassTypeField = value; + } + + inline System::String^ UsbDeviceClassDetailsType::SubclassTypeError::get() { + return this->subclassTypeErrorField; + } + inline System::Void UsbDeviceClassDetailsType::SubclassTypeError::set(System::String^ value) { + this->subclassTypeErrorField = value; + } + + inline System::String^ UsbDeviceClassDetailsType::DeviceProtocol::get() { + return this->deviceProtocolField; + } + inline System::Void UsbDeviceClassDetailsType::DeviceProtocol::set(System::String^ value) { + this->deviceProtocolField = value; + } + + inline System::String^ UsbDeviceClassDetailsType::DeviceProtocolError::get() { + return this->deviceProtocolErrorField; + } + inline System::Void UsbDeviceClassDetailsType::DeviceProtocolError::set(System::String^ value) { + this->deviceProtocolErrorField = value; + } + + inline System::UInt32 UsbDeviceClassDetailsType::UvcVersion::get() { + return this->uvcVersionField; + } + inline System::Void UsbDeviceClassDetailsType::UvcVersion::set(System::UInt32 value) { + this->uvcVersionField = value; + } + + + inline Microsoft::Kits::Samples::Usb::HubNodeInformationType^ ExternalHubType::HubNodeInformation::get() { + return this->hubNodeInformationField; + } + inline System::Void ExternalHubType::HubNodeInformation::set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value) { + this->hubNodeInformationField = value; + } + + inline System::String^ ExternalHubType::HubName::get() { + return this->hubNameField; + } + inline System::Void ExternalHubType::HubName::set(System::String^ value) { + this->hubNameField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubInformationExType^ ExternalHubType::HubInformationEx::get() { + return this->hubInformationExField; + } + inline System::Void ExternalHubType::HubInformationEx::set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value) { + this->hubInformationExField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ ExternalHubType::HubCapabilityEx::get() { + return this->hubCapabilityExField; + } + inline System::Void ExternalHubType::HubCapabilityEx::set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value) { + this->hubCapabilityExField = value; + } + + inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ ExternalHubType::ConnectionInfo::get() { + return this->connectionInfoField; + } + inline System::Void ExternalHubType::ConnectionInfo::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value) { + this->connectionInfoField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ ExternalHubType::UsbDevice::get() { + return this->usbDeviceField; + } + inline System::Void ExternalHubType::UsbDevice::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value) { + this->usbDeviceField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ ExternalHubType::NoDevice::get() { + return this->noDeviceField; + } + inline System::Void ExternalHubType::NoDevice::set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value) { + this->noDeviceField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ ExternalHubType::DeviceConfiguration::get() { + return this->deviceConfigurationField; + } + inline System::Void ExternalHubType::DeviceConfiguration::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value) { + this->deviceConfigurationField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ ExternalHubType::BosDescriptor::get() { + return this->bosDescriptorField; + } + inline System::Void ExternalHubType::BosDescriptor::set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value) { + this->bosDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ ExternalHubType::ConnectionInfoV2::get() { + return this->connectionInfoV2Field; + } + inline System::Void ExternalHubType::ConnectionInfoV2::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value) { + this->connectionInfoV2Field = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ ExternalHubType::ExternalHub::get() { + return this->externalHubField; + } + inline System::Void ExternalHubType::ExternalHub::set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value) { + this->externalHubField = value; + } + + inline Microsoft::Kits::Samples::Usb::PortConnectorType^ ExternalHubType::PortConnector::get() { + return this->portConnectorField; + } + inline System::Void ExternalHubType::PortConnector::set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value) { + this->portConnectorField = value; + } + + inline System::String^ ExternalHubType::ServiceName::get() { + return this->serviceNameField; + } + inline System::Void ExternalHubType::ServiceName::set(System::String^ value) { + this->serviceNameField = value; + } + + inline System::String^ ExternalHubType::HwId::get() { + return this->hwIdField; + } + inline System::Void ExternalHubType::HwId::set(System::String^ value) { + this->hwIdField = value; + } + + inline System::String^ ExternalHubType::DeviceId::get() { + return this->deviceIdField; + } + inline System::Void ExternalHubType::DeviceId::set(System::String^ value) { + this->deviceIdField = value; + } + + inline System::String^ ExternalHubType::DeviceName::get() { + return this->deviceNameField; + } + inline System::Void ExternalHubType::DeviceName::set(System::String^ value) { + this->deviceNameField = value; + } + + inline System::String^ ExternalHubType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void ExternalHubType::DeviceClass::set(System::String^ value) { + this->deviceClassField = value; + } + + inline System::String^ ExternalHubType::UsbProtocol::get() { + return this->usbProtocolField; + } + inline System::Void ExternalHubType::UsbProtocol::set(System::String^ value) { + this->usbProtocolField = value; + } + + + inline Microsoft::Kits::Samples::Usb::HubNodeType HubNodeInformationType::HubNode::get() { + return this->hubNodeField; + } + inline System::Void HubNodeInformationType::HubNode::set(Microsoft::Kits::Samples::Usb::HubNodeType value) { + this->hubNodeField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubInformationType^ HubNodeInformationType::HubInformation::get() { + return this->hubInformationField; + } + inline System::Void HubNodeInformationType::HubInformation::set(Microsoft::Kits::Samples::Usb::HubInformationType^ value) { + this->hubInformationField = value; + } + + inline System::UInt64 HubNodeInformationType::MiParentNumberOfInterfaces::get() { + return this->miParentNumberOfInterfacesField; + } + inline System::Void HubNodeInformationType::MiParentNumberOfInterfaces::set(System::UInt64 value) { + this->miParentNumberOfInterfacesField = value; + } + + + inline System::Boolean HubInformationType::IsRootHub::get() { + return this->isRootHubField; + } + inline System::Void HubInformationType::IsRootHub::set(System::Boolean value) { + this->isRootHubField = value; + } + + inline System::Boolean HubInformationType::IsBusPowered::get() { + return this->isBusPoweredField; + } + inline System::Void HubInformationType::IsBusPowered::set(System::Boolean value) { + this->isBusPoweredField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubInformationType::HubDescriptor::get() { + return this->hubDescriptorField; + } + inline System::Void HubInformationType::HubDescriptor::set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value) { + this->hubDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ HubInformationType::HubCharacteristics::get() { + return this->hubCharacteristicsField; + } + inline System::Void HubInformationType::HubCharacteristics::set(Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ value) { + this->hubCharacteristicsField = value; + } + + + inline System::Byte HubDescriptorType::DescriptorLength::get() { + return this->descriptorLengthField; + } + inline System::Void HubDescriptorType::DescriptorLength::set(System::Byte value) { + this->descriptorLengthField = value; + } + + inline System::Byte HubDescriptorType::DescriptorType::get() { + return this->descriptorTypeField; + } + inline System::Void HubDescriptorType::DescriptorType::set(System::Byte value) { + this->descriptorTypeField = value; + } + + inline System::Byte HubDescriptorType::NumberOfPorts::get() { + return this->numberOfPortsField; + } + inline System::Void HubDescriptorType::NumberOfPorts::set(System::Byte value) { + this->numberOfPortsField = value; + } + + inline System::Byte HubDescriptorType::PowerOntoPowerGood::get() { + return this->powerOntoPowerGoodField; + } + inline System::Void HubDescriptorType::PowerOntoPowerGood::set(System::Byte value) { + this->powerOntoPowerGoodField = value; + } + + inline System::Byte HubDescriptorType::HubControlCurrent::get() { + return this->hubControlCurrentField; + } + inline System::Void HubDescriptorType::HubControlCurrent::set(System::Byte value) { + this->hubControlCurrentField = value; + } + + + inline System::UInt32 HubCharacteristicsType::HubCharacteristicsValue::get() { + return this->hubCharacteristicsValueField; + } + inline System::Void HubCharacteristicsType::HubCharacteristicsValue::set(System::UInt32 value) { + this->hubCharacteristicsValueField = value; + } + + inline System::String^ HubCharacteristicsType::PowerSwitching::get() { + return this->powerSwitchingField; + } + inline System::Void HubCharacteristicsType::PowerSwitching::set(System::String^ value) { + this->powerSwitchingField = value; + } + + inline System::Boolean HubCharacteristicsType::CompoundDevice::get() { + return this->compoundDeviceField; + } + inline System::Void HubCharacteristicsType::CompoundDevice::set(System::Boolean value) { + this->compoundDeviceField = value; + } + + inline System::String^ HubCharacteristicsType::OverCurrentProtection::get() { + return this->overCurrentProtectionField; + } + inline System::Void HubCharacteristicsType::OverCurrentProtection::set(System::String^ value) { + this->overCurrentProtectionField = value; + } + + + inline Microsoft::Kits::Samples::Usb::HubTypeType HubInformationExType::HubType::get() { + return this->hubTypeField; + } + inline System::Void HubInformationExType::HubType::set(Microsoft::Kits::Samples::Usb::HubTypeType value) { + this->hubTypeField = value; + } + + inline System::UInt16 HubInformationExType::HighestPortNumber::get() { + return this->highestPortNumberField; + } + inline System::Void HubInformationExType::HighestPortNumber::set(System::UInt16 value) { + this->highestPortNumberField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubInformationExType::HubDescriptor::get() { + return this->hubDescriptorField; + } + inline System::Void HubInformationExType::HubDescriptor::set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value) { + this->hubDescriptorField = value; + } + + inline Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ HubInformationExType::Hub30Descriptor::get() { + return this->hub30DescriptorField; + } + inline System::Void HubInformationExType::Hub30Descriptor::set(Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ value) { + this->hub30DescriptorField = value; + } + + + inline System::Byte Hub30DescriptorType::Length::get() { + return this->lengthField; + } + inline System::Void Hub30DescriptorType::Length::set(System::Byte value) { + this->lengthField = value; + } + + inline System::Byte Hub30DescriptorType::DescriptorType::get() { + return this->descriptorTypeField; + } + inline System::Void Hub30DescriptorType::DescriptorType::set(System::Byte value) { + this->descriptorTypeField = value; + } + + inline System::Byte Hub30DescriptorType::NumberOfPorts::get() { + return this->numberOfPortsField; + } + inline System::Void Hub30DescriptorType::NumberOfPorts::set(System::Byte value) { + this->numberOfPortsField = value; + } + + inline System::UInt16 Hub30DescriptorType::HubCharacteristics::get() { + return this->hubCharacteristicsField; + } + inline System::Void Hub30DescriptorType::HubCharacteristics::set(System::UInt16 value) { + this->hubCharacteristicsField = value; + } + + inline System::Byte Hub30DescriptorType::PowerOntoPowerGood::get() { + return this->powerOntoPowerGoodField; + } + inline System::Void Hub30DescriptorType::PowerOntoPowerGood::set(System::Byte value) { + this->powerOntoPowerGoodField = value; + } + + inline System::Byte Hub30DescriptorType::HubControlCurrent::get() { + return this->hubControlCurrentField; + } + inline System::Void Hub30DescriptorType::HubControlCurrent::set(System::Byte value) { + this->hubControlCurrentField = value; + } + + inline System::Byte Hub30DescriptorType::HubHdrDecLat::get() { + return this->hubHdrDecLatField; + } + inline System::Void Hub30DescriptorType::HubHdrDecLat::set(System::Byte value) { + this->hubHdrDecLatField = value; + } + + inline System::UInt16 Hub30DescriptorType::HubDelay::get() { + return this->hubDelayField; + } + inline System::Void Hub30DescriptorType::HubDelay::set(System::UInt16 value) { + this->hubDelayField = value; + } + + inline System::UInt16 Hub30DescriptorType::DeviceRemovable::get() { + return this->deviceRemovableField; + } + inline System::Void Hub30DescriptorType::DeviceRemovable::set(System::UInt16 value) { + this->deviceRemovableField = value; + } + + + inline System::Boolean HubCapabilitiesExType::HubIsHighSpeedCapable::get() { + return this->hubIsHighSpeedCapableField; + } + inline System::Void HubCapabilitiesExType::HubIsHighSpeedCapable::set(System::Boolean value) { + this->hubIsHighSpeedCapableField = value; + } + + inline System::Boolean HubCapabilitiesExType::HubIsHighSpeed::get() { + return this->hubIsHighSpeedField; + } + inline System::Void HubCapabilitiesExType::HubIsHighSpeed::set(System::Boolean value) { + this->hubIsHighSpeedField = value; + } + + inline System::Boolean HubCapabilitiesExType::HubIsMultiTtCapable::get() { + return this->hubIsMultiTtCapableField; + } + inline System::Void HubCapabilitiesExType::HubIsMultiTtCapable::set(System::Boolean value) { + this->hubIsMultiTtCapableField = value; + } + + inline System::Boolean HubCapabilitiesExType::HubIsMultiTt::get() { + return this->hubIsMultiTtField; + } + inline System::Void HubCapabilitiesExType::HubIsMultiTt::set(System::Boolean value) { + this->hubIsMultiTtField = value; + } + + inline System::Boolean HubCapabilitiesExType::HubIsRoot::get() { + return this->hubIsRootField; + } + inline System::Void HubCapabilitiesExType::HubIsRoot::set(System::Boolean value) { + this->hubIsRootField = value; + } + + inline System::Boolean HubCapabilitiesExType::HubIsArmedWakeOnConnect::get() { + return this->hubIsArmedWakeOnConnectField; + } + inline System::Void HubCapabilitiesExType::HubIsArmedWakeOnConnect::set(System::Boolean value) { + this->hubIsArmedWakeOnConnectField = value; + } + + inline System::Boolean HubCapabilitiesExType::HubIsBusPowered::get() { + return this->hubIsBusPoweredField; + } + inline System::Void HubCapabilitiesExType::HubIsBusPowered::set(System::Boolean value) { + this->hubIsBusPoweredField = value; + } + + + inline Microsoft::Kits::Samples::Usb::HubNodeInformationType^ RootHubType::HubNodeInformation::get() { + return this->hubNodeInformationField; + } + inline System::Void RootHubType::HubNodeInformation::set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value) { + this->hubNodeInformationField = value; + } + + inline System::String^ RootHubType::HubName::get() { + return this->hubNameField; + } + inline System::Void RootHubType::HubName::set(System::String^ value) { + this->hubNameField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubInformationExType^ RootHubType::HubInformationEx::get() { + return this->hubInformationExField; + } + inline System::Void RootHubType::HubInformationEx::set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value) { + this->hubInformationExField = value; + } + + inline Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ RootHubType::HubCapabilityEx::get() { + return this->hubCapabilityExField; + } + inline System::Void RootHubType::HubCapabilityEx::set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value) { + this->hubCapabilityExField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ RootHubType::ExternalHub::get() { + return this->externalHubField; + } + inline System::Void RootHubType::ExternalHub::set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value) { + this->externalHubField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ RootHubType::UsbDevice::get() { + return this->usbDeviceField; + } + inline System::Void RootHubType::UsbDevice::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value) { + this->usbDeviceField = value; + } + + inline cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ RootHubType::NoDevice::get() { + return this->noDeviceField; + } + inline System::Void RootHubType::NoDevice::set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value) { + this->noDeviceField = value; + } + + inline System::String^ RootHubType::ServiceName::get() { + return this->serviceNameField; + } + inline System::Void RootHubType::ServiceName::set(System::String^ value) { + this->serviceNameField = value; + } + + inline System::String^ RootHubType::HwId::get() { + return this->hwIdField; + } + inline System::Void RootHubType::HwId::set(System::String^ value) { + this->hwIdField = value; + } + + inline System::String^ RootHubType::DeviceId::get() { + return this->deviceIdField; + } + inline System::Void RootHubType::DeviceId::set(System::String^ value) { + this->deviceIdField = value; + } + + inline System::String^ RootHubType::DeviceName::get() { + return this->deviceNameField; + } + inline System::Void RootHubType::DeviceName::set(System::String^ value) { + this->deviceNameField = value; + } + + inline System::String^ RootHubType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void RootHubType::DeviceClass::set(System::String^ value) { + this->deviceClassField = value; + } + + inline System::String^ RootHubType::UsbProtocol::get() { + return this->usbProtocolField; + } + inline System::Void RootHubType::UsbProtocol::set(System::String^ value) { + this->usbProtocolField = value; + } + + + inline System::String^ UsbHCPowerStateType::SystemState::get() { + return this->systemStateField; + } + inline System::Void UsbHCPowerStateType::SystemState::set(System::String^ value) { + this->systemStateField = value; + } + + inline System::String^ UsbHCPowerStateType::HostControllerState::get() { + return this->hostControllerStateField; + } + inline System::Void UsbHCPowerStateType::HostControllerState::set(System::String^ value) { + this->hostControllerStateField = value; + } + + inline System::String^ UsbHCPowerStateType::HubState::get() { + return this->hubStateField; + } + inline System::Void UsbHCPowerStateType::HubState::set(System::String^ value) { + this->hubStateField = value; + } + + inline System::Boolean UsbHCPowerStateType::CanWakeUp::get() { + return this->canWakeUpField; + } + inline System::Void UsbHCPowerStateType::CanWakeUp::set(System::Boolean value) { + this->canWakeUpField = value; + } + + inline System::Boolean UsbHCPowerStateType::IsPowered::get() { + return this->isPoweredField; + } + inline System::Void UsbHCPowerStateType::IsPowered::set(System::Boolean value) { + this->isPoweredField = value; + } + + + inline cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ UsbHCPowerStateMappingType::PowerMap::get() { + return this->powerMapField; + } + inline System::Void UsbHCPowerStateMappingType::PowerMap::set(cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ value) { + this->powerMapField = value; + } + + inline System::String^ UsbHCPowerStateMappingType::LastSleepState::get() { + return this->lastSleepStateField; + } + inline System::Void UsbHCPowerStateMappingType::LastSleepState::set(System::String^ value) { + this->lastSleepStateField = value; + } + + + inline System::Int64 UsbHCDeviceInfoType::VendorId::get() { + return this->vendorIdField; + } + inline System::Void UsbHCDeviceInfoType::VendorId::set(System::Int64 value) { + this->vendorIdField = value; + } + + inline System::Int64 UsbHCDeviceInfoType::DeviceId::get() { + return this->deviceIdField; + } + inline System::Void UsbHCDeviceInfoType::DeviceId::set(System::Int64 value) { + this->deviceIdField = value; + } + + inline System::String^ UsbHCDeviceInfoType::DriverKey::get() { + return this->driverKeyField; + } + inline System::Void UsbHCDeviceInfoType::DriverKey::set(System::String^ value) { + this->driverKeyField = value; + } + + inline System::Int64 UsbHCDeviceInfoType::SubSysId::get() { + return this->subSysIdField; + } + inline System::Void UsbHCDeviceInfoType::SubSysId::set(System::Int64 value) { + this->subSysIdField = value; + } + + inline System::Int64 UsbHCDeviceInfoType::Revision::get() { + return this->revisionField; + } + inline System::Void UsbHCDeviceInfoType::Revision::set(System::Int64 value) { + this->revisionField = value; + } + + inline System::UInt64 UsbHCDeviceInfoType::DebugPort::get() { + return this->debugPortField; + } + inline System::Void UsbHCDeviceInfoType::DebugPort::set(System::UInt64 value) { + this->debugPortField = value; + } + + inline System::UInt64 UsbHCDeviceInfoType::NumberOfRootPorts::get() { + return this->numberOfRootPortsField; + } + inline System::Void UsbHCDeviceInfoType::NumberOfRootPorts::set(System::UInt64 value) { + this->numberOfRootPortsField = value; + } + + inline System::UInt64 UsbHCDeviceInfoType::ControllerFlavor::get() { + return this->controllerFlavorField; + } + inline System::Void UsbHCDeviceInfoType::ControllerFlavor::set(System::UInt64 value) { + this->controllerFlavorField = value; + } + + inline System::String^ UsbHCDeviceInfoType::ControllerFlavorString::get() { + return this->controllerFlavorStringField; + } + inline System::Void UsbHCDeviceInfoType::ControllerFlavorString::set(System::String^ value) { + this->controllerFlavorStringField = value; + } + + inline System::Boolean UsbHCDeviceInfoType::PortSwitchingEnabled::get() { + return this->portSwitchingEnabledField; + } + inline System::Void UsbHCDeviceInfoType::PortSwitchingEnabled::set(System::Boolean value) { + this->portSwitchingEnabledField = value; + } + + inline System::Boolean UsbHCDeviceInfoType::SelectiveSuspendEnabled::get() { + return this->selectiveSuspendEnabledField; + } + inline System::Void UsbHCDeviceInfoType::SelectiveSuspendEnabled::set(System::Boolean value) { + this->selectiveSuspendEnabledField = value; + } + + inline System::UInt64 UsbHCDeviceInfoType::LegacyBios::get() { + return this->legacyBiosField; + } + inline System::Void UsbHCDeviceInfoType::LegacyBios::set(System::UInt64 value) { + this->legacyBiosField = value; + } + + + inline Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ HostControllerType::ControllerInfo::get() { + return this->controllerInfoField; + } + inline System::Void HostControllerType::ControllerInfo::set(Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ value) { + this->controllerInfoField = value; + } + + inline Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ HostControllerType::PowerMapping::get() { + return this->powerMappingField; + } + inline System::Void HostControllerType::PowerMapping::set(Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ value) { + this->powerMappingField = value; + } + + inline Microsoft::Kits::Samples::Usb::RootHubType^ HostControllerType::RootHub::get() { + return this->rootHubField; + } + inline System::Void HostControllerType::RootHub::set(Microsoft::Kits::Samples::Usb::RootHubType^ value) { + this->rootHubField = value; + } + + inline System::String^ HostControllerType::ServiceName::get() { + return this->serviceNameField; + } + inline System::Void HostControllerType::ServiceName::set(System::String^ value) { + this->serviceNameField = value; + } + + inline System::String^ HostControllerType::HwId::get() { + return this->hwIdField; + } + inline System::Void HostControllerType::HwId::set(System::String^ value) { + this->hwIdField = value; + } + + inline System::String^ HostControllerType::DeviceId::get() { + return this->deviceIdField; + } + inline System::Void HostControllerType::DeviceId::set(System::String^ value) { + this->deviceIdField = value; + } + + inline System::String^ HostControllerType::DeviceName::get() { + return this->deviceNameField; + } + inline System::Void HostControllerType::DeviceName::set(System::String^ value) { + this->deviceNameField = value; + } + + inline System::String^ HostControllerType::DeviceClass::get() { + return this->deviceClassField; + } + inline System::Void HostControllerType::DeviceClass::set(System::String^ value) { + this->deviceClassField = value; + } + + inline System::String^ HostControllerType::UsbProtocol::get() { + return this->usbProtocolField; + } + inline System::Void HostControllerType::UsbProtocol::set(System::String^ value) { + this->usbProtocolField = value; + } + } + } + } +} + diff --git a/tests/projects/windows/winsdk/usbview/usbviddesc.h b/tests/projects/windows/winsdk/usbview/usbviddesc.h new file mode 100644 index 000000000..f5a17164f --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/usbviddesc.h @@ -0,0 +1,743 @@ +/*++ + +Copyright (c) 2002-2003 Microsoft Corporation + +Module Name: + + USBVIDDESC.H + +Abstract: + + This is a header file for USB Video Class Specific descriptors which are not yet in + a standard system header file. + +Environment: + + user mode + +Revision History: + + 11-20-2002 : created + 03-28-2003 : major updates to support latest UVC specs + +--*/ + +#pragma pack(push, 1) + +/***************************************************************************** + D E F I N E S +*****************************************************************************/ + +//global version for USB Video Class spec version +#define BCDVDC 0x0083 + +// +// USB Device Class Definition for Video Devices v8.c +// Appendix A. Video Device Class Codes +// + +// A.1 Video Interface Class Code +//TBD Normally would be in USB100.h but not official yet +#define USB_DEVICE_CLASS_VIDEO 0x0E +#define USB_DEVICE_CLASS_VIDEO_PRERELEASE 0xFF +//CC_VIDEO in spec. The rest of the codes will be USB_VIDEO plus text from spec codes + +// A.2 Video Interface Subclass Codes +// +#define USB_VIDEO_SC_UNDEFINED 0x00 +#define USB_VIDEO_SC_VIDEOCONTROL 0x01 +#define USB_VIDEO_SC_VIDEOSTREAMING 0x02 +#define USB_VIDEO_SC_VIDEO_INTERFACE_COLLECTION 0x03 + +// A.3 Video Interface Protocol Codes +// +#define USB_VIDEO_PC_PROTOCOL_UNDEFINED 0x00 + +// A.4 Video Class-Specific Descriptor Types +// +#define USB_VIDEO_CS_UNDEFINED 0x20 +#define USB_VIDEO_CS_DEVICE 0x21 +#define USB_VIDEO_CS_CONFIGURATION 0x22 +#define USB_VIDEO_CS_STRING 0x23 +#define USB_VIDEO_CS_INTERFACE 0x24 +#define USB_VIDEO_CS_ENDPOINT 0x25 + +// A.5 Video Class-Specific VC (Video Control) Interface Descriptor Subtypes +// +#define USB_VIDEO_VC_DESCRIPTOR_UNDEFINED 0x00 +#define USB_VIDEO_VC_HEADER 0x01 +#define USB_VIDEO_VC_INPUT_TERMINAL 0x02 +#define USB_VIDEO_VC_OUTPUT_TERMINAL 0x03 +#define USB_VIDEO_VC_SELECTOR_UNIT 0x04 +#define USB_VIDEO_VC_PROCESSING_UNIT 0x05 +#define USB_VIDEO_VC_EXTENSION_UNIT 0x06 + +// A.6 Video Class-Specific VS (Video Streaming) Interface Descriptor Subtypes +// +#define USB_VIDEO_VS_UNDEFINED 0x00 +#define USB_VIDEO_VS_INPUT_HEADER 0x01 +#define USB_VIDEO_VS_OUTPUT_HEADER 0x02 +#define USB_VIDEO_VS_STILL_IMAGE_FRAME 0x03 +#define USB_VIDEO_VS_FORMAT_UNCOMPRESSED 0x04 +#define USB_VIDEO_VS_FRAME_UNCOMPRESSED 0x05 +#define USB_VIDEO_VS_FORMAT_MJPEG 0x06 +#define USB_VIDEO_VS_FRAME_MJPEG 0x07 +#define USB_VIDEO_VS_FORMAT_MPEG1 0x08 +#define USB_VIDEO_VS_FORMAT_MPEG2PS 0x09 +#define USB_VIDEO_VS_FORMAT_MPEG2TS 0x0A +#define USB_VIDEO_VS_FORMAT_MPEG4SL 0x0B +#define USB_VIDEO_VS_FORMAT_DV 0x0C +#define USB_VIDEO_VS_COLORFORMAT 0x0D +#define USB_VIDEO_VS_FORMAT_VENDOR 0x0E +#define USB_VIDEO_VS_FRAME_VENDOR 0x0F + +// A.7 Video Class-Specific Endpoint Descriptor Subtypes +// +#define USB_VIDEO_EP_UNDEFINED 0x00 +#define USB_VIDEO_EP_GENERAL 0x01 +#define USB_VIDEO_EP_ENDPOINT 0x02 +#define USB_VIDEO_EP_INTERRUPT 0x03 + +// +// Below definitions only necessary if testing requests +// +// A.8 Video Class-Specific Request Codes +// +#define USB_VIDEO_RC_UNDEFINED 0x00 +#define USB_VIDEO_SET_CUR 0x01 +#define USB_VIDEO_GET_CUR 0x81 +#define USB_VIDEO_GET_MIN 0x82 +#define USB_VIDEO_GET_MAX 0x83 +#define USB_VIDEO_GET_RES 0x84 +#define USB_VIDEO_GET_LEN 0x85 +#define USB_VIDEO_GET_INFO 0x86 +#define USB_VIDEO_GET_DEF 0x87 + +// A.9 Control Selector Codes +// A.9.1 VideoControl Interface Control Selectors +#define USB_VIDEO_VC_UNDEFINED_CONTROL 0x00 +#define USB_VIDEO_VC_VIDEO_POWER_MODE_CONTROL 0x01 +#define USB_VIDEO_VC_REQUEST_ERROR_CODE_CONTROL 0x02 +#define USB_VIDEO_VC_INDICATE_HOST_CLOCK_CONTROL 0x03 + +//A.9.2 Terminal Control Selectors +// +#define USB_VIDEO_TE_CONTROL_UNDEFINED 0x00 + +//A.9.3 Selector Unit Control Selectors +// +#define USB_VIDEO_SU_CONTROL_UNDEFINED 0x00 +#define USB_VIDEO_SU_INPUT_SELECT_CONTROL 0x01 + +//A.9.4 Camera Terminal Control Selectors +// +#define USB_VIDEO_CT_CONTROL_UNDEFINED 0x00 +#define USB_VIDEO_CT_SCANNING_MODE_CONTROL 0x01 +#define USB_VIDEO_CT_AE_MODE_CONTROL 0x02 +#define USB_VIDEO_CT_AE_PRIORITY_CONTROL 0x03 +#define USB_VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define USB_VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define USB_VIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define USB_VIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07 +#define USB_VIDEO_CT_FOCUS_AUTO_CONTROL 0x08 +#define USB_VIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define USB_VIDEO_CT_IRIS_RELATIVE_CONTROL 0x0A +#define USB_VIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0B +#define USB_VIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0C +#define USB_VIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0D +#define USB_VIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0E +#define USB_VIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0F +#define USB_VIDEO_CT_ROLL_RELATIVE_CONTROL 0x10 + +//A.9.5 Processing Unit Control Selectors +// +#define USB_VIDEO_PU_CONTROL_UNDEFINED 0x04 +#define USB_VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define USB_VIDEO_PU_BRIGHTNESS_CONTROL 0x02 +#define USB_VIDEO_PU_CONTRAST_CONTROL 0x03 +#define USB_VIDEO_PU_GAIN_CONTROL 0x04 +#define USB_VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define USB_VIDEO_PU_HUE_CONTROL 0x06 +#define USB_VIDEO_PU_SATURATION_CONTROL 0x07 +#define USB_VIDEO_PU_SHARPNESS_CONTROL 0x08 +#define USB_VIDEO_PU_GAMMA_CONTROL 0x09 +#define USB_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A +#define USB_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B +#define USB_VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C +#define USB_VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D +#define USB_VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0E +#define USB_VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F +#define USB_VIDEO_PU_HUE_AUTO_CONTROL 0x10 + +//A.9.6 Extension Unit Control Selectors +// +#define USB_VIDEO_XU_CONTROL_UNDEFINED 0x00 + +//A.9.7 VideoStreaming Interface Control Selectors +// +#define USB_VIDEO_VS_CONTROL_UNDEFINED 0x00 +#define USB_VIDEO_VS_PROBE_CONTROL 0x01 +#define USB_VIDEO_VS_COMMIT_CONTROL 0x02 +#define USB_VIDEO_VS_STILL_PROBE_CONTROL 0x03 +#define USB_VIDEO_VS_STILL_COMMIT_CONTROL 0x04 +#define USB_VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define USB_VIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define USB_VIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define USB_VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define USB_VIDEO_VS_SYNCH_DELAY_CONTROL 0x09 + +#define TapeControls 0 +#define TransportModes 1 +#define CameraControls 2 +#define ProcessorControls 3 +#define InHeaderControls 4 + +/***************************************************************************** + T Y P E D E F S +*****************************************************************************/ + + +/***************************************************************************** + USB Device Class Definition for Video Devices v8.b +*****************************************************************************/ + +typedef struct _USB_VIDEO_COMMON_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; +} USB_VIDEO_COMMON_DESCRIPTOR, +*PUSB_VIDEO_COMMON_DESCRIPTOR; + +// 3.6.2 Class-Specific VC (Video Control) Interface Descriptor +// +typedef struct _USB_VIDEO_VC_INTERFACE_HEADER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + USHORT bcdVDC; + USHORT wTotalLength; + ULONG32 dwClockFrequency; + UCHAR bInCollection; +// UCHAR baInterfaceNr; // variable length (0 minimum) +} USB_VIDEO_VC_INTERFACE_HEADER_DESCRIPTOR, +*PUSB_VIDEO_VC_INTERFACE_HEADER_DESCRIPTOR; + +// 3.6.2.1 Input Terminal Descriptor +// +typedef struct _USB_VIDEO_INPUT_TERMINAL_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR iTerminal; +} USB_VIDEO_INPUT_TERMINAL_DESCRIPTOR, +*PUSB_VIDEO_INPUT_TERMINAL_DESCRIPTOR; + +// 3.6.2.2 Output Terminal Descriptor +// +typedef struct _USB_VIDEO_OUTPUT_TERMINAL_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR bSourceID; + UCHAR iTerminal; +} USB_VIDEO_OUTPUT_TERMINAL_DESCRIPTOR, +*PUSB_VIDEO_OUTPUT_TERMINAL_DESCRIPTOR; + +// 3.6.2.3 Camera Unit Descriptor +// +typedef struct _USB_VIDEO_CAMERA_TERMINAL_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR iTerminal; + USHORT wObjectiveFocalLengthMin; + USHORT wObjectiveFocalLengthMax; + USHORT wOcularFocalLength; + UCHAR bControlSize; +// UCHAR bmControls; // variable length (0 min, 3 max) +} USB_VIDEO_CAMERA_TERMINAL_DESCRIPTOR, +*PUSB_VIDEO_CAMERA_TERMINAL_DESCRIPTOR; + +// 3.6.2.4 Selector Unit Descriptor +// +typedef struct _USB_VIDEO_SELECTOR_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + UCHAR bNrInPins; + UCHAR baSourceID; // variable length (1 minimum) + UCHAR iSelector; +} USB_VIDEO_SELECTOR_UNIT_DESCRIPTOR, +*PUSB_VIDEO_SELECTOR_UNIT_DESCRIPTOR; + +// 3.6.2.5 Processing Unit Descriptor +// +typedef struct _USB_VIDEO_PROCESSING_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + UCHAR bSourceID; + USHORT wMaxMultiplier; + UCHAR bControlSize; +// UCHAR bmControls; // variable length (0 minimum) + UCHAR iProcessing; +} USB_VIDEO_PROCESSING_UNIT_DESCRIPTOR, +*PUSB_VIDEO_PROCESSING_UNIT_DESCRIPTOR; + +// 3.6.2.6 Extension Unit Descriptor +// +typedef struct _USB_VIDEO_EXTENSION_UNIT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bUnitID; + GUID guidExtensionCode; + UCHAR bNumControls; + UCHAR bNrInPins; + UCHAR baSourceID; // variable length (1 minimum) +// UCHAR bControlSize; +// UCHAR bmControls; // variable length (0 minimum) +// UCHAR iExtension; +} USB_VIDEO_EXTENSION_UNIT_DESCRIPTOR, +*PUSB_VIDEO_EXTENSION_UNIT_DESCRIPTOR; + +// 3.7.2.2 Class-Specific VC Interrupt EndPoint Descriptor +// +typedef struct _USB_VIDEO_VC_INTERRUPT_ENDPOINT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubType; + USHORT wMaxTransferSize; +} USB_VIDEO_VC_INTERRUPT_ENDPOINT_DESCRIPTOR, +*PUSB_VIDEO_VC_INTERRUPT_ENDPOINT_DESCRIPTOR; +// 3.8.2.1 Class-Specific Input Header Descriptor +// +typedef struct _USB_VIDEO_INPUT_HEADER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bNumFormats; + USHORT wTotalLength; + UCHAR bEndpointAddress; + UCHAR bmInfo; + UCHAR bTerminalLink; + UCHAR bStillCaptureMethod; + UCHAR bTriggerSupport; + UCHAR bTriggerUsage; + UCHAR bControlSize; +// UCHAR bmaControls; // variable length (0 minimum) +} USB_VIDEO_INPUT_HEADER_DESCRIPTOR, +*PUSB_VIDEO_INPUT_HEADER_DESCRIPTOR; + +// 3.8.2.2 Class-Specific Output Header Descriptor +// +typedef struct _USB_VIDEO_OUTPUT_HEADER_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bNumFormats; + USHORT wTotalLength; + UCHAR bEndpointAddress; + UCHAR bTerminalLink; +} USB_VIDEO_OUTPUT_HEADER_DESCRIPTOR, +*PUSB_VIDEO_OUTPUT_HEADER_DESCRIPTOR; + +// 3.8.2.3 Payload Format Descriptors +//Payload Format Descriptor Document +//Uncompressed Video DWGVideo Payload Uncompressed 0.xx.doc +//MJPEG Video DWGVideo Payload MJPEG Format Ver0.xx.doc +//MPEG1 System Stream DWGVideo Payload MPEG1 System Stream, MPEG2-PS Format Ver0.xx.doc +//MPEG2 PS DWGVideo Payload MPEG1 System Stream, MPEG2-PS Format Ver0.xx.doc +//MPEG-2 TS DWGVideo Payload MPEG2TS Format Ver0.xx.doc +//MPEG-4 SL DWGVideo Payload MPEG4 SL format Ver0.xx.doc +//DV DWGVideo Payload DV Format Ver0.xx.doc + +// 3.8.2.4 Video Frame Descriptor +// +//Video Frame Descriptor Document +//Uncompressed DWGVideo Payload Uncompressed 0.xx.doc +//MJPEG DWGVideo Payload MJPEG Format Ver0.xx.doc + +// 3.8.2.5 Still Image Frame Descriptor +// +typedef struct _VIDEO_STILL_IMAGE { + USHORT wWidth; + USHORT wHeight; +} VIDEO_STILL_IMAGE, +*PVIDEO_STILL_IMAGE; + +typedef struct _USB_VIDEO_STILL_IMAGE_FRAME_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bEndpointAddress; + UCHAR bNumImageSizePatterns; + VIDEO_STILL_IMAGE dwStillImage; // variable count + UCHAR bNumCompressionPattern; + UCHAR bCompression; // variable count +} USB_VIDEO_STILL_IMAGE_FRAME_DESCRIPTOR, +*PUSB_VIDEO_STILL_IMAGE_FRAME_DESCRIPTOR; + +// 3.8.2.6 Color Matching Descriptor +// +typedef struct _USB_VIDEO_COLOR_MATCHING_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bColorPrimaries; + UCHAR bTransferCharacteristics; + UCHAR bMatrixCoefficients; +} USB_VIDEO_COLOR_MATCHING_DESCRIPTOR, +*PUSB_VIDEO_COLOR_MATCHING_DESCRIPTOR; +/* +// 3.9.1 Class-specific VC Interrupt Endpoint Descriptor +typedef struct _USB_VIDEO_VS_ENDPOINT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubType; + USHORT wMaxTransferSize; +} USB_VIDEO_VS_ENDPOINT_DESCRIPTOR, +*PUSB_VIDEO_VS_ENDPOINT_DESCRIPTOR; +*/ +// +// USB Device Class Definition for Video Devices: Uncompressed Payload 0.8a Draft Revision +// + +// 3.1.1 Uncompressed Video Format Descriptor +// +typedef struct _USB_VIDEO_UNCOMPRESSED_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + GUID guidFormat; + UCHAR bBitsPerPixel; + UCHAR bDefaultFrameIndex; + UCHAR bAspectRatioX; + UCHAR bAspectRatioY; + UCHAR bmInterlaceFlags; + UCHAR bCopyProtect; +} USB_VIDEO_UNCOMPRESSED_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_UNCOMPRESSED_FORMAT_DESCRIPTOR; + +// 3.1.2 Uncompressed Video Frame Descriptor Common +// +typedef struct _USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_COMMON { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; +} USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_COMMON, +*PUSB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_COMMON; + +// 3.1.2 Uncompressed Video Frame Descriptor - Continuous +// +typedef struct _USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_CONTINUOUS { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG32 dwMinFrameInterval; + ULONG32 dwMaxFrameInterval; + ULONG32 dwFrameIntervalStep; +} USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_CONTINUOUS, +*PUSB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_CONTINUOUS; + +// 3.1.2 Uncompressed Video Frame Descriptor - Discrete +// +typedef struct _USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_DISCRETE { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG32 dwFrameInterval; // variable count +} USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_DISCRETE, +*PUSB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_DISCRETE; + +// +// USB Device Class Definition for Video Devices: Motion-JPEG Payload 0.8a Draft Revision +// 3.1.1 MJPEG Video Format Descriptor +// +typedef struct _USB_VIDEO_MJPEG_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + UCHAR bmFlags; + UCHAR bDefaultFrameIndex; + UCHAR bAspectRatioX; + UCHAR bAspectRatioY; + UCHAR bmInterlaceFlags; + UCHAR bCopyProtect; +} USB_VIDEO_MJPEG_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_MJPEG_FORMAT_DESCRIPTOR; + +// 3.1.2 MJPEG Video Frame Descriptors Common +// +typedef struct _USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_COMMON { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; +} USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_COMMON, +*PUSB_VIDEO_MJPEG_FRAME_DESCRIPTOR_COMMON; + +// 3.1.2 MJPEG Video Frame Descriptors - Continuous +// +typedef struct _USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_CONTINUOUS { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG32 dwMinFrameInterval; + ULONG32 dwMaxFrameInterval; + ULONG32 dwFrameIntervalStep; +} USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_CONTINUOUS, +*PUSB_VIDEO_MJPEG_FRAME_DESCRIPTOR_CONTINUOUS; + +// 3.1.2 MJPEG Video Frame Descriptors -Discrete +// +typedef struct _USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_DISCRETE { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG32 dwFrameInterval; // variable count +} USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_DISCRETE, +*PUSB_VIDEO_MJPEG_FRAME_DESCRIPTOR_DISCRETE; + +// +// USB Device Class Definition for Video Devices: MPEG1-SS, MPEG2-PS Payload 0.8a Draft Revision +// 3.1.1 MPEG1 System Stream Format Descriptor +// +typedef struct _USB_VIDEO_MPEG1_SS_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + USHORT wPacketLength; + USHORT wPackLength; + UCHAR bPackdataType; +} USB_VIDEO_MPEG1_SS_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_MPEG1_SS_FORMAT_DESCRIPTOR; + +// 3.1.2 MPEG2 PS Format Descriptor +// +typedef struct _USB_VIDEO_MPEG2_PS_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + USHORT wPacketLength; + USHORT wPackLength; + UCHAR bPackdataType; +} USB_VIDEO_MPEG2_PS_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_MPEG2_PS_FORMAT_DESCRIPTOR; + +// +// USB Device Class Definition for Video Devices: MPEG-2 TS Payload 0.8a Draft Revision +// 3.1.1 MPEG-2 TS Format Descriptor +// +typedef struct _USB_VIDEO_MPEG2_TS_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bDataOffset; + UCHAR bPacketLength; + UCHAR bStrideLength; +} USB_VIDEO_MPEG2_TS_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_MPEG2_TS_FORMAT_DESCRIPTOR; + +// +// USB Device Class Definition for Video Devices: MPEG4 SL Payload 0.8a Draft Revision +// 3.1.1 MPEG4 SL Format Descriptor +// +typedef struct _USB_VIDEO_MPEG4_SL_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + USHORT wPacketLength; +} USB_VIDEO_MPEG4_SL_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_MPEG4_SL_FORMAT_DESCRIPTOR; + +// USB Device Class Definition for Video Devices: DV Payload 0.8a Draft Revision +// 3.1.1 DV Format Descriptor +typedef struct _USB_VIDEO_DV_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + ULONG32 dwMaxVideoFrameBufferSize; + UCHAR bFormatType; +} USB_VIDEO_DV_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_DV_FORMAT_DESCRIPTOR; + +// USB Device Class Definition for Video Devices: Vendor Payload 0.8c Draft Revision +// 3.1.1 Vendor Video Format Descriptor +typedef struct _USB_VIDEO_VENDOR_VIDEO_FORMAT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + GUID guidMajorFormat; + GUID guidSubFormat; + GUID guidSpecifier; + UCHAR bPayloadClass; + UCHAR bDefaultFrameIndex; + UCHAR bCopyProtect; +} USB_VIDEO_VENDOR_VIDEO_FORMAT_DESCRIPTOR, +*PUSB_VIDEO_VENDOR_VIDEO_FORMAT_DESCRIPTOR; + +// USB Device Class Definition for Video Devices: Vendor Payload 0.8c Draft Revision +// 3.1.2 Vendor Video Frame Descriptor +typedef struct _USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_COMMON { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; +} USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_COMMON, +*PUSB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_COMMON; + +typedef struct _USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_CONTINUOUS { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG32 dwMinFrameInterval; + ULONG32 dwMaxFrameInterval; + ULONG32 dwFrameIntervalStep; +} USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_CONTINUOUS, +*PUSB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_CONTINUOUS; + +typedef struct _USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_DISCRETE { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG32 dwMinBitRate; + ULONG32 dwMaxBitRate; + ULONG32 dwMaxVideoFrameBufferSize; + ULONG32 dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG32 dwFrameInterval; // variable count +} USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_DISCRETE, +*PUSB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_DISCRETE; + +// USB Device Class Definition for Video Devices: Media Transport Terminal 0.8a Draft Revision +// 3.1 Media Transport Input Descriptor +typedef struct _USB_VIDEO_MEDIA_TRANSPORT_INPUT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR iTerminal; + UCHAR bControlSize; + UCHAR bmControls; // variable size (min 1) +// UCHAR bTransportModeSize; // variable count (min 0) +// UCHAR bmTransportModes; // variable count (min 0) +} USB_VIDEO_MEDIA_TRANSPORT_INPUT_DESCRIPTOR, +*PUSB_VIDEO_MEDIA_TRANSPORT_INPUT_DESCRIPTOR; + +// 3.2 Media Transport Output Descriptor +typedef struct _USB_VIDEO_MEDIA_TRANSPORT_OUTPUT_DESCRIPTOR { + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bTerminalID; + USHORT wTerminalType; + UCHAR bAssocTerminal; + UCHAR bSourceID; + UCHAR iTerminal; + UCHAR bControlSize; + UCHAR bmControls; // variable size (min 1) +// UCHAR bTransportModeSize; // variable count (min 0) +// UCHAR bmTransportModes; // variable count (min 0) +} USB_VIDEO_MEDIA_TRANSPORT_OUTPUT_DESCRIPTOR, +*PUSB_VIDEO_MEDIA_TRANSPORT_OUTPUT_DESCRIPTOR; + +#pragma pack(pop) diff --git a/tests/projects/windows/winsdk/usbview/uvcdesc.h b/tests/projects/windows/winsdk/usbview/uvcdesc.h new file mode 100644 index 000000000..f343fa731 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/uvcdesc.h @@ -0,0 +1,1106 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// +// Copyright (C) Microsoft Corporation, 1999 - 2008 +// +// File: uvcdesc.h +// +// This header is from the UVC 1.1 USBVideo driver +// +//-------------------------------------------------------------------------- + +#ifndef ___UVCDESC_H___ +#define ___UVCDESC_H___ + + +// USB Video Device Class Code +#define USB_DEVICE_CLASS_VIDEO 0x0E + +// Video sub-classes +#define SUBCLASS_UNDEFINED 0x00 +#define VIDEO_SUBCLASS_CONTROL 0x01 +#define VIDEO_SUBCLASS_STREAMING 0x02 + +// Video Class-Specific Descriptor Types +#define CS_UNDEFINED 0x20 +#define CS_DEVICE 0x21 +#define CS_CONFIGURATION 0x22 +#define CS_STRING 0x23 +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +// Video Class-Specific VC Interface Descriptor Subtypes +#define VC_HEADER 0x01 +#define INPUT_TERMINAL 0x02 +#define OUTPUT_TERMINAL 0x03 +#define SELECTOR_UNIT 0x04 +#define PROCESSING_UNIT 0x05 +#define EXTENSION_UNIT 0x06 +#define MAX_TYPE_UNIT 0x07 + +// Video Class-Specific VS Interface Descriptor Subtypes +#define VS_DESCRIPTOR_UNDEFINED 0x00 +#define VS_INPUT_HEADER 0x01 +#define VS_OUTPUT_HEADER 0x02 +#define VS_STILL_IMAGE_FRAME 0x03 +#define VS_FORMAT_UNCOMPRESSED 0x04 +#define VS_FRAME_UNCOMPRESSED 0x05 +#define VS_FORMAT_MJPEG 0x06 +#define VS_FRAME_MJPEG 0x07 +#define VS_FORMAT_MPEG1 0x08 +#define VS_FORMAT_MPEG2PS 0x09 +#define VS_FORMAT_MPEG2TS 0x0A +#define VS_FORMAT_MPEG4SL 0x0B +#define VS_FORMAT_DV 0x0C +#define VS_COLORFORMAT 0x0D +#define VS_FORMAT_VENDOR 0x0E +#define VS_FRAME_VENDOR 0x0F + +// Video Class-Specific Endpoint Descriptor Subtypes +#define EP_UNDEFINED 0x00 +#define EP_GENERAL 0x01 +#define EP_ENDPOINT 0x02 +#define EP_INTERRUPT 0x03 + +// Video Class-Specific Terminal Types +#define TERMINAL_TYPE_VENDOR_SPECIFIC 0x0100 +#define TERMINAL_TYPE_USB_STREAMING 0x0101 +#define TERMINAL_TYPE_INPUT_MASK 0x0200 +#define TERMINAL_TYPE_INPUT_VENDOR_SPECIFIC 0x0200 +#define TERMINAL_TYPE_INPUT_CAMERA 0x0201 +#define TERMINAL_TYPE_INPUT_MEDIA_TRANSPORT 0x0202 +#define TERMINAL_TYPE_OUTPUT_MASK 0x0300 +#define TERMINAL_TYPE_OUTPUT_VENDOR_SPECIFIC 0x0300 +#define TERMINAL_TYPE_OUTPUT_DISPLAY 0x0301 +#define TERMINAL_TYPE_OUTPUT_MEDIA_TRANSPORT 0x0302 +#define TERMINAL_TYPE_EXTERNAL_VENDOR_SPECIFIC 0x0400 +#define TERMINAL_TYPE_EXTERNAL_UNDEFINED 0x0400 +#define TERMINAL_TYPE_EXTERNAL_COMPOSITE 0x0401 +#define TERMINAL_TYPE_EXTERNAL_SVIDEO 0x0402 +#define TERMINAL_TYPE_EXTERNAL_COMPONENT 0x0403 + + +// Controls for error checking only +#define DEV_SPECIFIC_CONTROL 0x1001 + +// Map KSNODE_TYPE GUIDs to Indexes +#define NODE_TYPE_NONE 0 +#define NODE_TYPE_STREAMING 1 +#define NODE_TYPE_INPUT_TERMINAL 2 +#define NODE_TYPE_OUTPUT_TERMINAL 3 +#define NODE_TYPE_SELECTOR 4 +#define NODE_TYPE_PROCESSING 5 +#define NODE_TYPE_CAMERA_TERMINAL 6 +#define NODE_TYPE_INPUT_MTT 7 +#define NODE_TYPE_OUTPUT_MTT 8 +#define NODE_TYPE_DEV_SPEC 9 +#define NODE_TYPE_MAX 9 + +// USB bmRequestType values +#define USBVIDEO_INTERFACE_SET 0x21 +#define USBVIDEO_ENDPOINT_SET 0x22 +#define USBVIDEO_INTERFACE_GET 0xA1 +#define USBVIDEO_ENDPOINT_GET 0xA2 + +// Video Class-specific specific requests +#define CLASS_SPECIFIC_GET_MASK 0x80 + +#define RC_UNDEFINED 0x00 +#define SET_CUR 0x01 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 +#define GET_LEN 0x85 +#define GET_INFO 0x86 +#define GET_DEF 0x87 + +// Power Mode Control constants +#define POWER_MODE_CONTROL_FULL 0x0 +#define POWER_MODE_CONTROL_DEV_DEPENDENT 0x1 + +// Video Class-specific Processing Unit Controls +#define PU_CONTROL_UNDEFINED 0x00 +#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define PU_BRIGHTNESS_CONTROL 0x02 +#define PU_CONTRAST_CONTROL 0x03 +#define PU_GAIN_CONTROL 0x04 +#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define PU_HUE_CONTROL 0x06 +#define PU_SATURATION_CONTROL 0x07 +#define PU_SHARPNESS_CONTROL 0x08 +#define PU_GAMMA_CONTROL 0x09 +#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A +#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B +#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C +#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D +#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0E +#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F +#define PU_HUE_AUTO_CONTROL 0x10 +#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 +#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 + +// Video Class-specific Camera Terminal Controls +#define CT_CONTROL_UNDEFINED 0x00 +#define CT_SCANNING_MODE_CONTROL 0x01 +#define CT_AE_MODE_CONTROL 0x02 +#define CT_AE_PRIORITY_CONTROL 0x03 +#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define CT_FOCUS_RELATIVE_CONTROL 0x07 +#define CT_FOCUS_AUTO_CONTROL 0x08 +#define CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define CT_IRIS_RELATIVE_CONTROL 0x0A +#define CT_ZOOM_ABSOLUTE_CONTROL 0x0B +#define CT_ZOOM_RELATIVE_CONTROL 0x0C +#define CT_PANTILT_ABSOLUTE_CONTROL 0x0D +#define CT_PANTILT_RELATIVE_CONTROL 0x0E +#define CT_ROLL_ABSOLUTE_CONTROL 0x0F +#define CT_ROLL_RELATIVE_CONTROL 0x10 +#define CT_PRIVACY_CONTROL 0x11 + +#define CT_RELATIVE_INCREASE 0x01 +#define CT_RELATIVE_DECREASE 0xff +#define CT_RELATIVE_STOP 0x00 + +// Selector Unit Control Selector +#define SU_INPUT_SELECT_CONTROL 0x01 + +// Media Tape Transport Control Selector +#define MTT_CONTROL_UNDEFINED 0x00 +#define MTT_TRANSPORT_CONTROL 0x01 +#define MTT_ATN_INFORMATION_CONTROL 0x02 +#define MTT_MEDIA_INFORMATION_CONTROL 0x03 +#define MTT_TIME_CODE_INFORMATION_CONTROL 0x04 + +// Media Transport Terminal States +#define MTT_STATE_PLAY_NEXT_FRAME 0x00 +#define MTT_STATE_PLAY_FWD_SLOWEST 0x01 +#define MTT_STATE_PLAY_SLOW_FWD_4 0x02 +#define MTT_STATE_PLAY_SLOW_FWD_3 0x03 +#define MTT_STATE_PLAY_SLOW_FWD_2 0x04 +#define MTT_STATE_PLAY_SLOW_FWD_1 0x05 +#define MTT_STATE_PLAY_X1 0x06 +#define MTT_STATE_PLAY_FAST_FWD_1 0x07 +#define MTT_STATE_PLAY_FAST_FWD_2 0x08 +#define MTT_STATE_PLAY_FAST_FWD_3 0x09 +#define MTT_STATE_PLAY_FAST_FWD_4 0x0A +#define MTT_STATE_PLAY_FASTEST_FWD 0x0B +#define MTT_STATE_PLAY_PREV_FRAME 0x0C +#define MTT_STATE_PLAY_SLOWEST_REV 0x0D +#define MTT_STATE_PLAY_SLOW_REV_4 0x0E +#define MTT_STATE_PLAY_SLOW_REV_3 0x0F +#define MTT_STATE_PLAY_SLOW_REV_2 0x10 +#define MTT_STATE_PLAY_SLOW_REV_1 0x11 +#define MTT_STATE_PLAY_REV 0x12 +#define MTT_STATE_PLAY_FAST_REV_1 0x13 +#define MTT_STATE_PLAY_FAST_REV_2 0x14 +#define MTT_STATE_PLAY_FAST_REV_3 0x15 +#define MTT_STATE_PLAY_FAST_REV_4 0x16 +#define MTT_STATE_PLAY_FASTEST_REV 0x17 +#define MTT_STATE_PLAY 0x18 +#define MTT_STATE_PAUSE 0x19 +#define MTT_STATE_PLAY_REVERSE_PAUSE 0x1A + + +#define MTT_STATE_STOP 0x40 +#define MTT_STATE_FAST_FORWARD 0x41 +#define MTT_STATE_REWIND 0x42 +#define MTT_STATE_HIGH_SPEED_REWIND 0x43 + +#define MTT_STATE_RECORD_START 0x50 +#define MTT_STATE_RECORD_PAUSE 0x51 + +#define MTT_STATE_EJECT 0x60 + +#define MTT_STATE_PLAY_SLOW_FWD_X 0x70 +#define MTT_STATE_PLAY_FAST_FWD_X 0x71 +#define MTT_STATE_PLAY_SLOW_REV_X 0x72 +#define MTT_STATE_PLAY_FAST_REV_X 0x73 +#define MTT_STATE_STOP_START 0x74 +#define MTT_STATE_STOP_END 0x75 +#define MTT_STATE_STOP_EMERGENCY 0x76 +#define MTT_STATE_STOP_CONDENSATION 0x77 +#define MTT_STATE_UNSPECIFIED 0x7F + +// Video Control Interface Control Selectors +#define VC_UNDEFINED_CONTROL 0x00 +#define VC_VIDEO_POWER_MODE_CONTROL 0x01 +#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 + +// VideoStreaming Interface Control Selectors +#define VS_CONTROL_UNDEFINED 0x00 +#define VS_PROBE_CONTROL 0x01 +#define VS_COMMIT_CONTROL 0x02 +#define VS_STILL_PROBE_CONTROL 0x03 +#define VS_STILL_COMMIT_CONTROL 0x04 +#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define VS_SYNC_DELAY_CONTROL 0x09 + +// Probe commit bitmap framing info +#define VS_PROBE_COMMIT_BIT_FID 0x01 +#define VS_PROBE_COMMIT_BIT_EOF 0x02 + +// Stream payload header Bit Field Header bits +#define BFH_FID 0x01 // Frame ID bit +#define BFH_EOF 0x02 // End of Frame bit +#define BFH_PTS 0x04 // Presentation Time Stamp bit +#define BFH_SCR 0x08 // Source Clock Reference bit +#define BFH_RES 0x10 // Reserved bit +#define BFH_STI 0x20 // Still image bit +#define BFH_ERR 0x40 // Error bit +#define BFH_EOH 0x80 // End of header bit + +#define HDR_LENGTH 1 // Length of header length field in bytes +#define BFH_LENGTH 1 // Length of BFH field in bytes +#define PTS_LENGTH 4 // Length of PTS field in bytes +#define SCR_LENGTH 6 // Length of SCR field in bytes + +// USB Video Status Codes (Request Error Code Control) +#define USBVIDEO_RE_STATUS_NOERROR 0x00 +#define USBVIDEO_RE_STATUS_NOT_READY 0x01 +#define USBVIDEO_RE_STATUS_WRONG_STATE 0x02 +#define USBVIDEO_RE_STATUS_POWER 0x03 +#define USBVIDEO_RE_STATUS_OUT_OF_RANGE 0x04 +#define USBVIDEO_RE_STATUS_INVALID_UNIT 0x05 +#define USBVIDEO_RE_STATUS_INVALID_CONTROL 0x06 +#define USBVIDEO_RE_STATUS_UNKNOWN 0x07 + +// USB Video Device Status Codes (Stream Error Code Control) +#define USBVIDEO_SE_STATUS_NOERROR 0x00 +#define USBVIDEO_SE_STATUS_PROTECTED_CONTENT 0x01 +#define USBVIDEO_SE_STATUS_INPUT_BUFFER_UNDERRUN 0x02 +#define USBVIDEO_SE_STATUS_DATA_DICONTINUITY 0x03 +#define USBVIDEO_SE_STATUS_OUTPUT_BUFFER_UNDERRUN 0x04 +#define USBVIDEO_SE_STATUS_OUTPUT_BUFFER_OVERRUN 0x05 +#define USBVIDEO_SE_STATUS_FORMAT_CHANGE 0x06 +#define USBVIDEO_SE_STATUS_STILL_IMAGE_ERROR 0x07 +#define USBVIDEO_SE_STATUS_UNKNOWN 0x08 + +// Status Interrupt Types +#define STATUS_INTERRUPT_VC 1 +#define STATUS_INTERRUPT_VS 2 + +// Status Interrupt Attributes +#define STATUS_INTERRUPT_ATTRIBUTE_VALUE 0x00 +#define STATUS_INTERRUPT_ATTRIBUTE_INFO 0x01 +#define STATUS_INTERRUPT_ATTRIBUTE_FAILURE 0x02 + +// VideoStreaming interface interrupt types +#define VS_INTERRUPT_EVENT_BUTTON_PRESS 0x00 +#define VS_INTERRUPT_VALUE_BUTTON_RELEASE 0x00 +#define VS_INTERRUPT_VALUE_BUTTON_PRESS 0x01 + +// Get Info Values +#define USBVIDEO_ASYNC_CONTROL 0x10 +#define USBVIDEO_SETTABLE_CONTROL 0x2 + +#define MAX_INTERRUPT_PACKET_VALUE_SIZE 8 + +// Frame descriptor frame interval array offsets +#define MIN_FRAME_INTERVAL_OFFSET 0 +#define MAX_FRAME_INTERVAL_OFFSET 1 +#define FRAME_INTERVAL_STEP_OFFSET 2 + +// Still image capture methods +#define STILL_CAPTURE_METHOD_NONE 0 +#define STILL_CAPTURE_METHOD_1 1 +#define STILL_CAPTURE_METHOD_2 2 +#define STILL_CAPTURE_METHOD_3 3 + +// Still image trigger control states +#define STILL_IMAGE_TRIGGER_NORMAL 0 +#define STILL_IMAGE_TRIGGER_TRANSMIT 1 +#define STILL_IMAGE_TRIGGER_TRANSMIT_BULK 2 +#define STILL_IMAGE_TRIGGER_TRANSMIT_ABORT 3 + +// Endpoint descriptor masks +#define EP_DESCRIPTOR_TRANSACTION_SIZE_MASK 0x07ff +#define EP_DESCRIPTOR_NUM_TRANSACTION_MASK 0x1800 +#define EP_DESCRIPTOR_NUM_TRANSACTION_OFFSET 11 + + +// Copy protection flag defined in the Uncompressed Payload Spec +#define USB_VIDEO_UNCOMPRESSED_RESTRICT_DUPLICATION 1 + +// Interlace flags +#define INTERLACE_FLAGS_SUPPORTED_MASK 0x01 +#define INTERLACE_FLAGS_FIELDS_PER_FRAME_MASK 0x02 +#define INTERLACE_FLAGS_FIELDS_PER_FRAME_2 0x00 +#define INTERLACE_FLAGS_FIELDS_PER_FRAME_1 0x02 +#define INTERLACE_FLAGS_FIELD_1_FIRST_MASK 0x04 +#define INTERLACE_FLAGS_FIELD_PATTERN_MASK 0x30 +#define INTERLACE_FLAGS_FIELD_PATTERN_FIELD1 0x00 +#define INTERLACE_FLAGS_FIELD_PATTERN_FIELD2 0x10 +#define INTERLACE_FLAGS_FIELD_PATTERN_REGULAR 0x20 +#define INTERLACE_FLAGS_FIELD_PATTERN_RANDOM 0x30 +#define INTERLACE_FLAGS_DISPLAY_MODE_MASK 0xC0 +#define INTERLACE_FLAGS_DISPLAY_MODE_BOB 0x00 +#define INTERLACE_FLAGS_DISPLAY_MODE_WEAVE 0x40 +#define INTERLACE_FLAGS_DISPLAY_MODE_BOB_WEAVE 0x80 + +// Color Matching Flags +#define UVC_PRIMARIES_UNKNOWN 0x0 +#define UVC_PRIMARIES_BT709 0x1 +#define UVC_PRIMARIES_BT470_2M 0x2 +#define UVC_PRIMARIES_BT470_2BG 0x3 +#define UVC_PRIMARIES_SMPTE_170M 0x4 +#define UVC_PRIMARIES_SMPTE_240M 0x5 + +#define UVC_GAMMA_UNKNOWN 0x0 +#define UVC_GAMMA_BT709 0x1 +#define UVC_GAMMA_BT470_2M 0x2 +#define UVC_GAMMA_BT470_2BG 0x3 +#define UVC_GAMMA_SMPTE_170M 0x4 +#define UVC_GAMMA_SMPTE_240M 0x5 +#define UVC_GAMMA_LINEAR 0x6 +#define UVC_GAMMA_sRGB 0x7 + +#define UVC_TRANSFER_MATRIX_UNKNOWN 0x0 +#define UVC_TRANSFER_MATRIX_BT709 0x1 +#define UVC_TRANSFER_MATRIX_FCC 0x2 +#define UVC_TRANSFER_MATRIX_BT470_2BG 0x3 +#define UVC_TRANSFER_MATRIX_BT601 0x4 +#define UVC_TRANSFER_MATRIX_SMPTE_240M 0x5 + +// +// BEGIN - VDC Descriptor and Control Structures +// +#pragma warning( disable : 4200 ) // Allow zero-sized arrays at end of structs +#pragma pack( push, vdc_descriptor_structs, 1) + +// Video Specific Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // descriptor subtype +} VIDEO_SPECIFIC, *PVIDEO_SPECIFIC; + +#define SIZEOF_VIDEO_SPECIFIC(pDesc) sizeof(VIDEO_SPECIFIC) + + +// Video Unit Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // descriptor subtype + UCHAR bUnitID; // Constant uniquely identifying the Unit +} VIDEO_UNIT, *PVIDEO_UNIT; + +#define SIZEOF_VIDEO_UNIT(pDesc) sizeof(VIDEO_UNIT) + +// VideoControl Header Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // VC_HEADER descriptor subtype + USHORT bcdVideoSpec; // USB video class spec revision number + USHORT wTotalLength; // Total length, including all units and terminals + ULONG dwClockFreq; // Device clock frequency in Hz + UCHAR bInCollection; // number of video streaming interfaces + UCHAR baInterfaceNr[]; // interface number array +} VIDEO_CONTROL_HEADER_UNIT, *PVIDEO_CONTROL_HEADER_UNIT; + +#define SIZEOF_VIDEO_CONTROL_HEADER_UNIT(pDesc) \ + ((sizeof(VIDEO_CONTROL_HEADER_UNIT) + (pDesc)->bInCollection)) + + +// VideoControl Input Terminal Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // INPUT_TERMINAL descriptor subtype + UCHAR bTerminalID; // Constant uniquely identifying the Terminal + USHORT wTerminalType; // Constant characterizing the terminal type + UCHAR bAssocTerminal; // ID of associated output terminal + UCHAR iTerminal; // Index of string descriptor +} VIDEO_INPUT_TERMINAL, *PVIDEO_INPUT_TERMINAL; + +#define SIZEOF_VIDEO_INPUT_TERMINAL(pDesc) sizeof(VIDEO_INPUT_TERMINAL) + + +// VideoControl Output Terminal Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // OUTPUT_TERMINAL descriptor subtype + UCHAR bTerminalID; // Constant uniquely identifying the Terminal + USHORT wTerminalType; // Constant characterizing the terminal type + UCHAR bAssocTerminal; // ID of associated input terminal + UCHAR bSourceID; // ID of source unit/terminal + UCHAR iTerminal; // Index of string descriptor +} VIDEO_OUTPUT_TERMINAL, *PVIDEO_OUTPUT_TERMINAL; + +#define SIZEOF_VIDEO_OUTPUT_TERMINAL(pDesc) sizeof(VIDEO_OUTPUT_TERMINAL) + + +// VideoControl Camera Terminal Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // INPUT_TERMINAL descriptor subtype + UCHAR bTerminalID; // Constant uniquely identifying the Terminal + USHORT wTerminalType; // Sensor type + UCHAR bAssocTerminal; // ID of associated output terminal + UCHAR iTerminal; // Index of string descriptor + USHORT wObjectiveFocalLengthMin; // Min focal length for zoom + USHORT wObjectiveFocalLengthMax; // Max focal length for zoom + USHORT wOcularFocalLength; // Ocular focal length for zoom + UCHAR bControlSize; // Size of bmControls field + UCHAR bmControls[]; // Bitmap of controls supported +} VIDEO_CAMERA_TERMINAL, *PVIDEO_CAMERA_TERMINAL; + +#define SIZEOF_VIDEO_CAMERA_TERMINAL(pDesc) \ + (sizeof(VIDEO_CAMERA_TERMINAL) + (pDesc)->bControlSize) + + +// Media Transport Input Terminal Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // INPUT_TERMINAL descriptor subtype + UCHAR bTerminalID; // Constant uniquely identifying the Terminal + USHORT wTerminalType; // Media Transport type + UCHAR bAssocTerminal; // ID of associated output terminal + UCHAR iTerminal; // Index of string descriptor + UCHAR bControlSize; // Size of bmControls field + UCHAR bmControls[]; // Bitmap of controls supported +} VIDEO_INPUT_MTT, *PVIDEO_INPUT_MTT; + + +__inline size_t SizeOfVideoInputMTT(_In_ PVIDEO_INPUT_MTT pDesc) +{ + UCHAR bTransportModeSize; + PUCHAR pbCurr; + + pbCurr = pDesc->bmControls + pDesc->bControlSize; + bTransportModeSize = *pbCurr; + + return sizeof(VIDEO_INPUT_MTT) + pDesc->bControlSize + 1 + bTransportModeSize; +} + +#define SIZEOF_VIDEO_INPUT_MTT(pDesc) SizeOfVideoInputMTT(pDesc) + + +// Media Transport Output Terminal Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // OUTPUT_TERMINAL descriptor subtype + UCHAR bTerminalID; // Constant uniquely identifying the Terminal + USHORT wTerminalType; // Media Transport type + UCHAR bAssocTerminal; // ID of associated output terminal + UCHAR bSourceID; // ID of source unit/terminal + UCHAR iTerminal; // Index of string descriptor + UCHAR bControlSize; // Size of bmControls field + UCHAR bmControls[]; // Bitmap of controls supported +} VIDEO_OUTPUT_MTT, *PVIDEO_OUTPUT_MTT; + + +__inline size_t SizeOfVideoOutputMTT(_In_ PVIDEO_OUTPUT_MTT pDesc) +{ + UCHAR bTransportModeSize; + PUCHAR pbCurr; + + pbCurr = pDesc->bmControls + pDesc->bControlSize; + bTransportModeSize = *pbCurr; + + return sizeof(VIDEO_OUTPUT_MTT) + pDesc->bControlSize + 1+ bTransportModeSize; +} + +#define SIZEOF_VIDEO_OUTPUT_MTT(pDesc) SizeOfVideoOutputMTT(pDesc) + + +// VideoControl Selector Unit Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // SELECTOR_UNIT descriptor subtype + UCHAR bUnitID; // Constant uniquely identifying the Unit + UCHAR bNrInPins; // Number of input pins + UCHAR baSourceID[]; // IDs of connected units/terminals +} VIDEO_SELECTOR_UNIT, *PVIDEO_SELECTOR_UNIT; + +#define SIZEOF_VIDEO_SELECTOR_UNIT(pDesc) \ + (sizeof(VIDEO_SELECTOR_UNIT) + (pDesc)->bNrInPins + 1) + + +// VideoControl Processing Unit Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // PROCESSING_UNIT descriptor subtype + UCHAR bUnitID; // Constant uniquely identifying the Unit + UCHAR bSourceID; // ID of connected unit/terminal + USHORT wMaxMultiplier; // Maximum digital magnification + UCHAR bControlSize; // Size of bmControls field + UCHAR bmControls[]; // Bitmap of controls supported +} VIDEO_PROCESSING_UNIT, *PVIDEO_PROCESSING_UNIT; + +#define SIZEOF_VIDEO_PROCESSING_UNIT(pDesc) \ + (sizeof(VIDEO_PROCESSING_UNIT) + 1 + (pDesc)->bControlSize) + + +// VideoControl Extension Unit Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // EXTENSION_UNIT descriptor subtype + UCHAR bUnitID; // Constant uniquely identifying the Unit + GUID guidExtensionCode; // Vendor-specific code identifying extension unit + UCHAR bNumControls; // Number of controls in Extension Unit + UCHAR bNrInPins; // Number of input pins + UCHAR baSourceID[]; // IDs of connected units/terminals +} VIDEO_EXTENSION_UNIT, *PVIDEO_EXTENSION_UNIT; +// this is followed by bControlSize, bmControls and iExtension (1 byte) + +__inline size_t SizeOfVideoExtensionUnit(PVIDEO_EXTENSION_UNIT pDesc) +{ + UCHAR bControlSize; + PUCHAR pbCurr; + + // baSourceID is an array, and hence understood to be an address + pbCurr = pDesc->baSourceID + pDesc->bNrInPins; + if (((ULONG_PTR) pbCurr < (ULONG_PTR) pDesc->baSourceID) || + (ULONG_PTR) pbCurr >= (ULONG_PTR)((UCHAR *) pDesc + pDesc->bLength)) + return 0; + + bControlSize = *pbCurr; + return 24 + pDesc->bNrInPins + bControlSize; +} + +#define SIZEOF_VIDEO_EXTENSION_UNIT(pDesc) SizeOfVideoExtensionUnit(pDesc) + + +// Class-specific Interrupt Endpoint Descriptor +typedef struct { + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_ENDPOINT descriptor type + UCHAR bDescriptorSubtype; // EP_INTERRUPT descriptor subtype + USHORT wMaxTransferSize; // Max interrupt payload size +} VIDEO_CS_INTERRUPT, *PVIDEO_CS_INTERRUPT; + +#define SIZEOF_VIDEO_CS_INTERRUPT(pDesc) sizeof(VIDEO_CS_INTERRUPT) + + +// VideoStreaming Input Header Descriptor +typedef struct _VIDEO_STREAMING_INPUT_HEADER +{ + UCHAR bLength; // Size of this descriptor in bytes + UCHAR bDescriptorType; // CS_INTERFACE descriptor type + UCHAR bDescriptorSubtype; // VS_INPUT_HEADER descriptor subtype + UCHAR bNumFormats; + USHORT wTotalLength; + UCHAR bEndpointAddress; + UCHAR bmInfo; + UCHAR bTerminalLink; + UCHAR bStillCaptureMethod; + UCHAR bTriggerSupport; + UCHAR bTriggerUsage; + UCHAR bControlSize; + UCHAR bmaControls[]; +} VIDEO_STREAMING_INPUT_HEADER, *PVIDEO_STREAMING_INPUT_HEADER; + +#define SIZEOF_VIDEO_STREAMING_INPUT_HEADER(pDesc) \ + (sizeof(VIDEO_STREAMING_INPUT_HEADER) + (pDesc->bNumFormats * pDesc->bControlSize)) + + +// VideoStreaming Output Header Descriptor +typedef struct _VIDEO_STREAMING_OUTPUT_HEADER +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bNumFormats; + USHORT wTotalLength; + UCHAR bEndpointAddress; + UCHAR bTerminalLink; +} VIDEO_STREAMING_OUTPUT_HEADER, *PVIDEO_STREAMING_OUTPUT_HEADER; + +#define SIZEOF_VIDEO_STREAMING_OUTPUT_HEADER(pDesc) sizeof(VIDEO_STREAMING_OUTPUT_HEADER) + + +typedef struct _VIDEO_STILL_IMAGE_RECT +{ + USHORT wWidth; + USHORT wHeight; +} VIDEO_STILL_IMAGE_RECT; + +// VideoStreaming Still Image Frame Descriptor +typedef struct _VIDEO_STILL_IMAGE_FRAME +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bEndpointAddress; + UCHAR bNumImageSizePatterns; + VIDEO_STILL_IMAGE_RECT aStillRect[]; +} VIDEO_STILL_IMAGE_FRAME, *PVIDEO_STILL_IMAGE_FRAME; + +__inline size_t SizeOfVideoStillImageFrame(PVIDEO_STILL_IMAGE_FRAME pDesc) +{ + UCHAR bNumCompressionPatterns; + PUCHAR pbCurr; + + pbCurr = (PUCHAR) pDesc->aStillRect + (sizeof(VIDEO_STILL_IMAGE_RECT) * pDesc->bNumImageSizePatterns); + bNumCompressionPatterns = *pbCurr; + + return (sizeof(VIDEO_STILL_IMAGE_FRAME) + + (sizeof(VIDEO_STILL_IMAGE_RECT) * pDesc->bNumImageSizePatterns) + + 1 + bNumCompressionPatterns); +} + +#define SIZEOF_VIDEO_STILL_IMAGE_FRAME(pDesc) SizeOfVideoStillImageFrame(pDesc) + + +// VideoStreaming Color Matching Descriptor +typedef struct _VIDEO_COLORFORMAT +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bColorPrimaries; + UCHAR bTransferCharacteristics; + UCHAR bMatrixCoefficients; +} VIDEO_COLORFORMAT, *PVIDEO_COLORFORMAT; + +#define SIZEOF_VIDEO_COLORFORMAT(pDesc) sizeof(VIDEO_COLORFORMAT) + + +// VideoStreaming Uncompressed Format Descriptor +typedef struct _VIDEO_FORMAT_UNCOMPRESSED +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + GUID guidFormat; + UCHAR bBitsPerPixel; + UCHAR bDefaultFrameIndex; + UCHAR bAspectRatioX; + UCHAR bAspectRatioY; + UCHAR bmInterlaceFlags; + UCHAR bCopyProtect; +} VIDEO_FORMAT_UNCOMPRESSED, *PVIDEO_FORMAT_UNCOMPRESSED; + +#define SIZEOF_VIDEO_FORMAT_UNCOMPRESSED(pDesc) sizeof(VIDEO_FORMAT_UNCOMPRESSED) + + +// VideoStreaming Uncompressed Frame Descriptor +typedef struct _VIDEO_FRAME_UNCOMPRESSED +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG dwMinBitRate; + ULONG dwMaxBitRate; + ULONG dwMaxVideoFrameBufferSize; + ULONG dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG adwFrameInterval[]; +} VIDEO_FRAME_UNCOMPRESSED, *PVIDEO_FRAME_UNCOMPRESSED; + + +__inline size_t SizeOfVideoFrameUncompressed(_In_ PVIDEO_FRAME_UNCOMPRESSED pDesc) +{ + if (pDesc->bFrameIntervalType == 0) { // Continuous + return sizeof(VIDEO_FRAME_UNCOMPRESSED) + (3 * sizeof(ULONG)); + } + else { // Discrete + return sizeof(VIDEO_FRAME_UNCOMPRESSED) + (pDesc->bFrameIntervalType * sizeof(ULONG)); + } +} + +#define SIZEOF_VIDEO_FRAME_UNCOMPRESSED(pDesc) SizeOfVideoFrameUncompressed(pDesc) + + +// VideoStreaming MJPEG Format Descriptor +typedef struct _VIDEO_FORMAT_MJPEG +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + UCHAR bmFlags; + UCHAR bDefaultFrameIndex; + UCHAR bAspectRatioX; + UCHAR bAspectRatioY; + UCHAR bmInterlaceFlags; + UCHAR bCopyProtect; +} VIDEO_FORMAT_MJPEG, *PVIDEO_FORMAT_MJPEG; + +#define SIZEOF_VIDEO_FORMAT_MJPEG(pDesc) sizeof(VIDEO_FORMAT_MJPEG) + + +// VideoStreaming MJPEG Frame Descriptor +typedef struct _VIDEO_FRAME_MJPEG +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG dwMinBitRate; + ULONG dwMaxBitRate; + ULONG dwMaxVideoFrameBufferSize; + ULONG dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG adwFrameInterval[]; +} VIDEO_FRAME_MJPEG, *PVIDEO_FRAME_MJPEG; + + +__inline size_t SizeOfVideoFrameMjpeg(_In_ PVIDEO_FRAME_MJPEG pDesc) +{ + if (pDesc->bFrameIntervalType == 0) { // Continuous + return sizeof(VIDEO_FRAME_MJPEG) + (3 * sizeof(ULONG)); + } + else { // Discrete + return sizeof(VIDEO_FRAME_MJPEG) + (pDesc->bFrameIntervalType * sizeof(ULONG)); + } +} + +#define SIZEOF_VIDEO_FRAME_MJPEG(pDesc) SizeOfVideoFrameMjpeg(pDesc) + + +// VideoStreaming Vendor Format Descriptor +typedef struct _VIDEO_FORMAT_VENDOR +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + GUID guidMajorFormat; + GUID guidSubFormat; + GUID guidSpecifier; + UCHAR bPayloadClass; + UCHAR bDefaultFrameIndex; + UCHAR bCopyProtect; +} VIDEO_FORMAT_VENDOR, *PVIDEO_FORMAT_VENDOR; + +#define SIZEOF_VIDEO_FORMAT_VENDOR(pDesc) sizeof(VIDEO_FORMAT_VENDOR) + + +// VideoStreaming Vendor Frame Descriptor +typedef struct _VIDEO_FRAME_VENDOR +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG dwMinBitRate; + ULONG dwMaxBitRate; + ULONG dwMaxVideoFrameBufferSize; + ULONG dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + DWORD adwFrameInterval[]; +} VIDEO_FRAME_VENDOR, *PVIDEO_FRAME_VENDOR; + +__inline size_t SizeOfVideoFrameVendor(_In_ PVIDEO_FRAME_VENDOR pDesc) +{ + if (pDesc->bFrameIntervalType == 0) { // Continuous + return sizeof(VIDEO_FRAME_VENDOR) + (3 * sizeof(ULONG)); + } + else { // Discrete + return sizeof(VIDEO_FRAME_VENDOR) + (pDesc->bFrameIntervalType * sizeof(ULONG)); + } +} + +#define SIZEOF_VIDEO_FRAME_VENDOR(pDesc) SizeOfVideoFrameVendor(pDesc) + + +// VideoStreaming DV Format Descriptor +typedef struct _VIDEO_FORMAT_DV +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + ULONG dwMaxVideoFrameBufferSize; + UCHAR bFormatType; +} VIDEO_FORMAT_DV, *PVIDEO_FORMAT_DV; + +#define SIZEOF_VIDEO_FORMAT_DV(pDesc) sizeof(VIDEO_FORMAT_DV) + + +// VideoStreaming MPEG2-TS Format Descriptor +typedef struct _VIDEO_FORMAT_MPEG2TS +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bDataOffset; + UCHAR bPacketLength; + UCHAR bStrideLength; +} VIDEO_FORMAT_MPEG2TS, *PVIDEO_FORMAT_MPEG2TS; + +#define SIZEOF_VIDEO_FORMAT_MPEG2TS(pDesc) sizeof(VIDEO_FORMAT_MPEG2TS) + + +// VideoStreaming MPEG1 System Stream Format Descriptor +typedef struct _VIDEO_FORMAT_MPEG1SS +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bPacketLength; + UCHAR bPackLength; + UCHAR bPackDataType; +} VIDEO_FORMAT_MPEG1SS, *PVIDEO_FORMAT_MPEG1SS; + +#define SIZEOF_VIDEO_FORMAT_MPEG1SS(pDesc) sizeof(VIDEO_FORMAT_MPEG1SS) + + +// VideoStreaming MPEG2-PS Format Descriptor +typedef struct _VIDEO_FORMAT_MPEG2PS +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bPacketLength; + UCHAR bPackLength; + UCHAR bPackDataType; +} VIDEO_FORMAT_MPEG2PS, *PVIDEO_FORMAT_MPEG2PS; + +#define SIZEOF_VIDEO_FORMAT_MPEG2PS(pDesc) sizeof(VIDEO_FORMAT_MPEG2PS) + + +// VideoStreaming MPEG4-SL Format Descriptor +typedef struct _VIDEO_FORMAT_MPEG4SL +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bPacketLength; +} VIDEO_FORMAT_MPEG4SL, *PVIDEO_FORMAT_MPEG4SL; + +#define SIZEOF_VIDEO_FORMAT_MPEG4SL(pDesc) sizeof(VIDEO_FORMAT_MPEG4SL) + +// VideoStreaming Probe/Commit Control +typedef struct _VS_PROBE_COMMIT_CONTROL +{ + USHORT bmHint; + UCHAR bFormatIndex; + UCHAR bFrameIndex; + ULONG dwFrameInterval; + USHORT wKeyFrameRate; + USHORT wPFrameRate; + USHORT wCompQuality; + USHORT wCompWindowSize; + USHORT wDelay; + ULONG dwMaxVideoFrameSize; + ULONG dwMaxPayloadTransferSize; +} VS_PROBE_COMMIT_CONTROL, *PVS_PROBE_COMMIT_CONTROL; + +// VideoStreaming Still Probe/Commit Control +typedef struct _VS_STILL_PROBE_COMMIT_CONTROL +{ + UCHAR bFormatIndex; + UCHAR bFrameIndex; + UCHAR bCompressionIndex; + ULONG dwMaxVideoFrameSize; + ULONG dwMaxPayloadTransferSize; +} VS_STILL_PROBE_COMMIT_CONTROL, *PVS_STILL_PROBE_COMMIT_CONTROL; + + +// Status Interrupt Packet (Video Control) +typedef struct _VC_INTERRUPT_PACKET +{ + UCHAR bStatusType; + UCHAR bOriginator; + UCHAR bEvent; + UCHAR bSelector; + UCHAR bAttribute; + UCHAR bValue[1]; +} VC_INTERRUPT_PACKET, *PVC_INTERRUPT_PACKET; + +// Status Interrupt Packet (Video Control) +typedef struct _VC_INTERRUPT_PACKET_EX +{ + UCHAR bStatusType; + UCHAR bOriginator; + UCHAR bEvent; + UCHAR bSelector; + UCHAR bAttribute; + UCHAR bValue[MAX_INTERRUPT_PACKET_VALUE_SIZE]; +} VC_INTERRUPT_PACKET_EX, *PVC_INTERRUPT_PACKET_EX; + +// Status Interrupt Packet (Video Streaming) +typedef struct _VS_INTERRUPT_PACKET +{ + UCHAR bStatusType; + UCHAR bOriginator; + UCHAR bEvent; + UCHAR bValue[1]; +} VS_INTERRUPT_PACKET, *PVS_INTERRUPT_PACKET; + +// Status Interrupt Packet (Generic) +typedef struct _VIDEO_INTERRUPT_PACKET +{ + UCHAR bStatusType; + UCHAR bOriginator; +} VIDEO_INTERRUPT_PACKET, *PVIDEO_INTERRUPT_PACKET; + + +// Relative property struct +typedef struct _VIDEO_RELATIVE_PROPERTY +{ + UCHAR bValue; + UCHAR bSpeed; +} VIDEO_RELATIVE_PROPERTY, *PVIDEO_RELATIVE_PROPERTY; + +// Relative Zoom control struct +typedef struct _ZOOM_RELATIVE_PROPERTY +{ + UCHAR bZoom; + UCHAR bDigitalZoom; + UCHAR bSpeed; +} ZOOM_RELATIVE_PROPERTY, *PZOOM_RELATIVE_PROPERTY; + +// Relative pan-tilt struct +typedef struct _PANTILT_RELATIVE_PROPERTY +{ + UCHAR bPanRelative; + UCHAR bPanSpeed; + UCHAR bTiltRelative; + UCHAR bTiltSpeed; +} PANTILT_RELATIVE_PROPERTY, *PPANTILT_RELATIVE_PROPERTY; + +typedef struct _MEDIA_INFORMATION_CONTROL +{ + UCHAR bmMediaType; + UCHAR bmWriteProtect; +} MEDIA_INFORMATION_CONTROL, *PMEDIA_INFORMATION_CONTROL; + +typedef struct _TIME_CODE_INFORMATION_CONTROL +{ + UCHAR bcdFrame; + UCHAR bcdSecond; + UCHAR bcdMinute; + UCHAR bcdHour; +} TIME_CODE_INFORMATION_CONTROL, *PTIME_CODE_INFORMATION_CONTROL; + +typedef struct _ATN_INFORMATION_CONTROL +{ + UCHAR bmMediaType; + DWORD dwATN_Data; +} ATN_INFORMATION_CONTROL, *PATN_INFORMATION_CONTROL; + +#define VS_FORMAT_FRAME_BASED 0x10 +#define VS_FRAME_FRAME_BASED 0x11 +#define VS_FORMAT_STREAM_BASED 0x12 + +// Format Descriptor for UVC 1.1 frame based format +typedef struct _VIDEO_FORMAT_FRAME +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + UCHAR bNumFrameDescriptors; + GUID guidFormat; + UCHAR bBitsPerPixel; + UCHAR bDefaultFrameIndex; + UCHAR bAspectRatioX; + UCHAR bAspectRatioY; + UCHAR bmInterlaceFlags; + UCHAR bCopyProtect; + UCHAR bVariableSize; +} VIDEO_FORMAT_FRAME, *PVIDEO_FORMAT_FRAME; + +#define SIZEOF_VIDEO_FORMAT_FRAME(pDesc) sizeof(VIDEO_FORMAT_FRAME) + + +// Frame Descriptor for UVC 1.1 frame based format +typedef struct _VIDEO_FRAME_FRAME +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFrameIndex; + UCHAR bmCapabilities; + USHORT wWidth; + USHORT wHeight; + ULONG dwMinBitRate; + ULONG dwMaxBitRate; + ULONG dwDefaultFrameInterval; + UCHAR bFrameIntervalType; + ULONG dwBytesPerLine; + ULONG adwFrameInterval[]; +} VIDEO_FRAME_FRAME, *PVIDEO_FRAME_FRAME; + +__inline size_t SizeOfVideoFrameFrame(_In_ PVIDEO_FRAME_FRAME pDesc) +{ + if (pDesc->bFrameIntervalType == 0) { // Continuous + return sizeof(VIDEO_FRAME_FRAME) + (3 * sizeof(ULONG)); + } + else { // Discrete + return sizeof(VIDEO_FRAME_FRAME) + (pDesc->bFrameIntervalType * sizeof(ULONG)); + } +} + +#define SIZEOF_VIDEO_FRAME_FRAME(pDesc) SizeOfVideoFrameFrame(pDesc) + +// VideoStreaming Stream Based Format Descriptor +typedef struct _VIDEO_FORMAT_STREAM +{ + UCHAR bLength; + UCHAR bDescriptorType; + UCHAR bDescriptorSubtype; + UCHAR bFormatIndex; + GUID guidFormat; + ULONG dwPacketLength; +} VIDEO_FORMAT_STREAM, *PVIDEO_FORMAT_STREAM; + +#define SIZEOF_VIDEO_FORMAT_STREAM(pDesc) sizeof(VIDEO_FORMAT_STREAM) + +// VideoStreaming Probe/Commit Control +typedef struct _VS_PROBE_COMMIT_CONTROL2 +{ + USHORT bmHint; + UCHAR bFormatIndex; + UCHAR bFrameIndex; + ULONG dwFrameInterval; + USHORT wKeyFrameRate; + USHORT wPFrameRate; + USHORT wCompQuality; + USHORT wCompWindowSize; + USHORT wDelay; + ULONG dwMaxVideoFrameSize; + ULONG dwMaxPayloadTransferSize; + ULONG dwClockFrequency; + UCHAR bmFramingInfo; + UCHAR bPreferredVersion; + UCHAR bMinVersion; + UCHAR bMaxVersion; +} VS_PROBE_COMMIT_CONTROL2, *PVS_PROBE_COMMIT_CONTROL2; + +#pragma pack( pop, vdc_descriptor_structs ) +#pragma warning( default : 4200 ) + + +// +// END - VDC Descriptor and Control Structures +// + +#endif // ___UVCDESC_H___ diff --git a/tests/projects/windows/winsdk/usbview/uvcview.c b/tests/projects/windows/winsdk/usbview/uvcview.c new file mode 100644 index 000000000..04b295292 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/uvcview.c @@ -0,0 +1,2153 @@ +/*++ + +Copyright (c) 1997-2011 Microsoft Corporation + +Module Name: + +USBVIEW.C + +Abstract: + +This is the GUI goop for the USBVIEW application. + +Environment: + +user mode + +Revision History: + +04-25-97 : created +11-20-02 : minor changes to support more reporting options +04/13/2005 : major bug fixing +07/01/2008 : add UVC 1.1 support and move to Dev branch + +--*/ + +/***************************************************************************** +I N C L U D E S +*****************************************************************************/ + +#include "resource.h" +#include "uvcview.h" +#include "h264.h" +#include "xmlhelper.h" + +#include + + +/***************************************************************************** +D E F I N E S +*****************************************************************************/ + +// window control defines +// +#define SIZEBAR 0 +#define WINDOWSCALEFACTOR 15 + +/***************************************************************************** + L O C A L T Y P E D E F S +*****************************************************************************/ +typedef struct _TREEITEMINFO +{ + struct _TREEITEMINFO *Next; + USHORT Depth; + PCHAR Name; + +} TREEITEMINFO, *PTREEITEMINFO; + + +/***************************************************************************** +L O C A L E N U M S +*****************************************************************************/ + +typedef enum _USBVIEW_SAVE_FILE_TYPE +{ + UsbViewNone = 0, + UsbViewXmlFile, + UsbViewTxtFile +} USBVIEW_SAVE_FILE_TYPE; + +/***************************************************************************** +L O C A L F U N C T I O N P R O T O T Y P E S +*****************************************************************************/ + +int WINAPI +WinMain ( + _In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPSTR lpszCmdLine, + _In_ int nCmdShow + ); + +BOOL +CreateMainWindow ( + int nCmdShow + ); + +VOID +ResizeWindows ( + BOOL bSizeBar, + int BarLocation + ); + +LRESULT CALLBACK +MainDlgProc ( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ); + +BOOL +USBView_OnInitDialog ( + HWND hWnd, + HWND hWndFocus, + LPARAM lParam + ); + +VOID +USBView_OnClose ( + HWND hWnd + ); + +VOID +USBView_OnCommand ( + HWND hWnd, + int id, + HWND hwndCtl, + UINT codeNotify + ); + +VOID +USBView_OnLButtonDown ( + HWND hWnd, + BOOL fDoubleClick, + int x, + int y, + UINT keyFlags + ); + +VOID +USBView_OnLButtonUp ( + HWND hWnd, + int x, + int y, + UINT keyFlags + ); + +VOID +USBView_OnMouseMove ( + HWND hWnd, + int x, + int y, + UINT keyFlags + ); + +VOID +USBView_OnSize ( + HWND hWnd, + UINT state, + int cx, + int cy + ); + +LRESULT +USBView_OnNotify ( + HWND hWnd, + int DlgItem, + LPNMHDR lpNMHdr + ); + +BOOL +USBView_OnDeviceChange ( + HWND hwnd, + UINT uEvent, + DWORD dwEventData + ); + +VOID DestroyTree (VOID); + +VOID RefreshTree (VOID); + +LRESULT CALLBACK +AboutDlgProc ( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ); + +VOID +WalkTree ( + _In_ HTREEITEM hTreeItem, + _In_ LPFNTREECALLBACK lpfnTreeCallback, + _In_opt_ PVOID pContext + ); + +VOID +ExpandItem ( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ); + +VOID +AddItemInformationToFile( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ); + +DWORD +DisplayLastError( + _Inout_updates_bytes_(count) char *szString, + int count); + +VOID AddItemInformationToXmlView( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ); +HRESULT InitializeConsole(); +VOID UnInitializeConsole(); +BOOL IsStdOutFile(); +VOID DisplayMessage(DWORD dwMsgId, ...); +VOID PrintString(LPTSTR lpszString); +LPTSTR WStringToAnsiString(LPWSTR lpwszString); +VOID WaitForKeyPress(); +BOOL ProcessCommandLine(); +HRESULT ProcessCommandSaveFile(LPTSTR szFileName, DWORD dwCreationDisposition, USBVIEW_SAVE_FILE_TYPE fileType); +HRESULT SaveAllInformationAsText(LPTSTR lpstrTextFileName, DWORD dwCreationDisposition); +HRESULT SaveAllInformationAsXml(LPTSTR lpstrTextFileName , DWORD dwCreationDisposition); + +/***************************************************************************** +G L O B A L S +*****************************************************************************/ +BOOL gDoConfigDesc = TRUE; +BOOL gDoAnnotation = TRUE; +BOOL gLogDebug = FALSE; +int TotalHubs = 0; + +extern DEVICE_GUID_LIST gHubList; +extern DEVICE_GUID_LIST gDeviceList; + +/***************************************************************************** +G L O B A L S P R I V A T E T O T H I S F I L E +*****************************************************************************/ + +HINSTANCE ghInstance = NULL; +HWND ghMainWnd = NULL; +HWND ghTreeWnd = NULL; +HWND ghEditWnd = NULL; +HWND ghStatusWnd = NULL; +HMENU ghMainMenu = NULL; +HTREEITEM ghTreeRoot = NULL; +HCURSOR ghSplitCursor = NULL; +HDEVNOTIFY gNotifyDevHandle = NULL; +HDEVNOTIFY gNotifyHubHandle = NULL; +HANDLE ghStdOut = NULL; + +BOOL gbConsoleFile = FALSE; +BOOL gbConsoleInitialized = FALSE; +BOOL gbButtonDown = FALSE; +BOOL gDoAutoRefresh = TRUE; + +int gBarLocation = 0; +int giGoodDevice = 0; +int giBadDevice = 0; +int giComputer = 0; +int giHub = 0; +int giNoDevice = 0; +int giGoodSsDevice = 0; +int giNoSsDevice = 0; + + +/***************************************************************************** + +WinMain() + +*****************************************************************************/ + +int WINAPI +WinMain ( + _In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, + _In_ LPSTR lpszCmdLine, + _In_ int nCmdShow + ) +{ + MSG msg; + HACCEL hAccel; + int retStatus = 0; + + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpszCmdLine); + + InitXmlHelper(); + + ghInstance = hInstance; + + ghSplitCursor = LoadCursor(ghInstance, + MAKEINTRESOURCE(IDC_SPLIT)); + + if (!ghSplitCursor) + { + OOPS(); + return retStatus; + } + + hAccel = LoadAccelerators(ghInstance, + MAKEINTRESOURCE(IDACCEL)); + + if (!hAccel) + { + OOPS(); + return retStatus; + } + + if (!CreateTextBuffer()) + { + return retStatus; + } + + if (!ProcessCommandLine()) + { + // There were no command line flags, open GUI + if (CreateMainWindow(nCmdShow)) + { + while (GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(ghMainWnd, + hAccel, + &msg) && + !IsDialogMessage(ghMainWnd, + &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + retStatus = 1; + } + } + + DestroyTextBuffer(); + + ReleaseXmlWriter(); + + CHECKFORLEAKS(); + + return retStatus; +} + + +/***************************************************************************** + +ProcessCommandLine() + +Parses the command line and takes appropriate actions. Returns FALSE If there is no action to +perform +*****************************************************************************/ +BOOL ProcessCommandLine() +{ + LPWSTR *szArgList = NULL; + LPTSTR szArg = NULL; + LPTSTR szAnsiArg= NULL; + BOOL quietMode = FALSE; + + HRESULT hr = S_OK; + DWORD dwCreationDisposition = CREATE_NEW; + USBVIEW_SAVE_FILE_TYPE fileType = UsbViewNone; + + int nArgs = 0; + int i = 0; + BOOL bStatus = FALSE; + BOOL bStopArgProcessing = FALSE; + + szArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs); + + // If there are no arguments we return false + bStatus = (nArgs > 1)? TRUE:FALSE; + + if (NULL != szArgList) + { + if (nArgs > 1) + { + // If there are arguments, initialize console for ouput + InitializeConsole(); + } + + for (i = 1; (i < nArgs) && (bStopArgProcessing == FALSE); i++) + { + // Convert argument to ANSI string for futher processing + + szAnsiArg = WStringToAnsiString(szArgList[i]); + + if(NULL == szAnsiArg) + { + DisplayMessage(IDS_USBVIEW_INVALIDARG, szAnsiArg); + DisplayMessage(IDS_USBVIEW_USAGE); + break; + } + + if (0 == _stricmp(szAnsiArg, "/?")) + { + DisplayMessage(IDS_USBVIEW_USAGE); + break; + } + else if (NULL != StrStrI(szAnsiArg, "/saveall:")) + { + fileType = UsbViewTxtFile; + } + else if (NULL != StrStrI(szAnsiArg, "/savexml:")) + { + fileType = UsbViewXmlFile; + } + else if (0 == _stricmp(szAnsiArg, "/f")) + { + dwCreationDisposition = CREATE_ALWAYS; + } + else if (0 == _stricmp(szAnsiArg, "/q")) + { + quietMode = TRUE; + } + else + { + DisplayMessage(IDS_USBVIEW_INVALIDARG, szAnsiArg); + DisplayMessage(IDS_USBVIEW_USAGE); + bStopArgProcessing = TRUE; + } + + if (fileType != UsbViewNone) + { + // Save view information as to file + szArg = strchr(szAnsiArg, ':'); + + if (NULL == szArg || strlen(szArg) == 1) + { + // No ':' or just a ':' + DisplayMessage(IDS_USBVIEW_INVALID_FILENAME, szAnsiArg); + DisplayMessage(IDS_USBVIEW_USAGE); + bStopArgProcessing = TRUE; + } + else + { + hr = ProcessCommandSaveFile(szArg + 1, dwCreationDisposition, fileType); + + if (FAILED(hr)) + { + // No more processing + bStopArgProcessing = TRUE; + } + + fileType = UsbViewNone; + } + } + + if (NULL != szAnsiArg) + { + LocalFree(szAnsiArg); + } + } + + if(!quietMode) + { + WaitForKeyPress(); + } + + if (gbConsoleInitialized) + { + UnInitializeConsole(); + } + + LocalFree(szArgList); + } + return bStatus; +} + + +/***************************************************************************** + +ProcessCommandSaveFile() + +Process the save file command line + +*****************************************************************************/ +HRESULT ProcessCommandSaveFile(LPTSTR szFileName, DWORD dwCreationDisposition, USBVIEW_SAVE_FILE_TYPE fileType) +{ + HRESULT hr = S_OK; + LPTSTR szErrorBuffer = NULL; + + if (UsbViewNone == fileType || NULL == szFileName) + { + hr = E_INVALIDARG; + // Invalid arguments, return + return (hr); + } + + // The UI is not created yet, open the UI, but HIDE it + CreateMainWindow(SW_HIDE); + + if (UsbViewXmlFile == fileType) + { + hr = SaveAllInformationAsXml(szFileName, dwCreationDisposition); + } + + if (UsbViewTxtFile == fileType) + { + hr = SaveAllInformationAsText(szFileName, dwCreationDisposition); + } + + if (FAILED(hr)) + { + if (GetLastError() == ERROR_FILE_EXISTS || hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)) + { + // The operation failed because the file we tried to write to already existed and '/f' option + // was not present. Display error message to user describing '/f' option + switch(fileType) + { + case UsbViewXmlFile: + DisplayMessage(IDS_USBVIEW_FILE_EXISTS_XML, szFileName); + break; + case UsbViewTxtFile: + DisplayMessage(IDS_USBVIEW_FILE_EXISTS_TXT, szFileName); + break; + default: + DisplayMessage(IDS_USBVIEW_INTERNAL_ERROR); + break; + } + } + else + { + // Try to obtain system error message + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &szErrorBuffer, // FormatMessage expects this buffer to be cast as LPTSTR + 0, + NULL); + PrintString("Unable to save file.\n"); + PrintString(szErrorBuffer); + LocalFree(szErrorBuffer); + } + } + else + { + // Display file saved to message in console + DisplayMessage(IDS_USBVIEW_SAVED_TO, szFileName); + } + + return (hr); +} + +/***************************************************************************** + +InitializeConsole() + +Initializes the std output in console + +*****************************************************************************/ +HRESULT InitializeConsole() +{ + HRESULT hr = S_OK; + + SetLastError(0); + + // Find if STD_OUTPUT is a console or has been redirected to a File + gbConsoleFile = IsStdOutFile(); + + if (!gbConsoleFile) + { + // Output is not redirected and GUI application do not have console by default, create a console + if(AllocConsole()) + { +#pragma warning(disable:4996) // We don' need the FILE * returned by freopen + // Reopen STDOUT , STDIN and STDERR + if((freopen("conout$", "w", stdout) != NULL) && + (freopen("conin$", "r", stdin) != NULL) && + (freopen("conout$","w", stderr) != NULL)) + { + gbConsoleInitialized = TRUE; + ghStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + } +#pragma warning(default:4996) + } + } + + if (INVALID_HANDLE_VALUE == ghStdOut || FALSE == gbConsoleInitialized) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + OOPS(); + } + return hr; +} + +/***************************************************************************** + +UnInitializeConsole() + +UnInitializes the console + +*****************************************************************************/ +VOID UnInitializeConsole() +{ + gbConsoleInitialized = FALSE; + FreeConsole(); +} + +/***************************************************************************** + +IsStdOutFile() + +Finds if the STD_OUTPUT has been redirected to a file +*****************************************************************************/ +BOOL IsStdOutFile() +{ + unsigned htype; + HANDLE hFile; + + // 1 = STDOUT + hFile = (HANDLE) _get_osfhandle(1); + htype = GetFileType(hFile); + htype &= ~FILE_TYPE_REMOTE; + + + // Check if file type is character file + if (FILE_TYPE_DISK == htype) + { + return TRUE; + } + + return FALSE; +} + + +/***************************************************************************** + +DisplayMessage() + +Displays a message to standard output +*****************************************************************************/ +VOID DisplayMessage(DWORD dwResId, ...) +{ + CHAR szFormat[4096]; + HRESULT hr = S_OK; + LPTSTR lpszMessage = NULL; + DWORD dwLen = 0; + va_list ap; + + va_start(ap, dwResId); + + // Initialize console if needed + if (!gbConsoleInitialized) + { + hr = InitializeConsole(); + if (FAILED(hr)) + { + OOPS(); + return; + } + } + + // Load the string resource + dwLen = LoadString(GetModuleHandle(NULL), + dwResId, + szFormat, + ARRAYSIZE(szFormat) + ); + + if(0 == dwLen) + { + PrintString("Unable to find message for given resource ID"); + + // Return if resource ID could not be found + return; + } + + dwLen = FormatMessage( + FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + szFormat, + dwResId, + 0, + (LPTSTR) &lpszMessage, + ARRAYSIZE(szFormat), + &ap); + + if (dwLen > 0) + { + PrintString(lpszMessage); + LocalFree(lpszMessage); + } + else + { + PrintString("Unable to find message for given ID"); + } + + va_end(ap); + return; +} + +/***************************************************************************** + +WStringToAnsiString() + +Converts the Wide char string to ANSI string and returns the allocated ANSI string. +*****************************************************************************/ +LPTSTR WStringToAnsiString(LPWSTR lpwszString) +{ + int strLen = 0; + LPTSTR szAnsiBuffer = NULL; + + szAnsiBuffer = LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(CHAR)); + + // Convert string from from WCHAR to ANSI + if (NULL != szAnsiBuffer) + { + strLen = WideCharToMultiByte( + CP_ACP, + 0, + lpwszString, + -1, + szAnsiBuffer, + MAX_PATH + 1, + NULL, + NULL); + + if (strLen > 0) + { + return szAnsiBuffer; + } + } + return NULL; +} + +/***************************************************************************** + +PrintString() + +Displays a string to standard output +*****************************************************************************/ +VOID PrintString(LPTSTR lpszString) +{ + DWORD dwBytesWritten = 0; + size_t Len = 0; + LPSTR lpOemString = NULL; + + if (INVALID_HANDLE_VALUE == ghStdOut || NULL == lpszString) + { + OOPS(); + // Return if invalid inputs + return; + } + + if (FAILED(StringCchLength(lpszString, OUTPUT_MESSAGE_MAX_LENGTH, &Len))) + { + OOPS(); + // Return if string is too long + return; + } + + if (gbConsoleFile) + { + // Console has been redirected to a file, ex: `usbview /savexml:xx > test.txt`. We need to use WriteFile instead of + // WriteConsole for text output. + lpOemString = (LPSTR) LocalAlloc(LPTR, (Len + 1) * sizeof(CHAR)); + if (lpOemString != NULL) + { + if (CharToOemBuff(lpszString, lpOemString, (DWORD) Len)) + { + WriteFile(ghStdOut, (LPVOID) lpOemString, (DWORD) Len, &dwBytesWritten, NULL); + } + else + { + OOPS(); + } + } + } + else + { + // Write to std out in console + WriteConsole(ghStdOut, (LPVOID) lpszString, (DWORD) Len, &dwBytesWritten, NULL); + } + + return; +} + +/***************************************************************************** + +WaitForKeyPress() + +Waits for key press in case of console +*****************************************************************************/ +VOID WaitForKeyPress() +{ + // Wait for key press if console + if (!gbConsoleFile && gbConsoleInitialized) + { + DisplayMessage(IDS_USBVIEW_PRESSKEY); + (VOID) _getch(); + } + return; +} + +/***************************************************************************** + +CreateMainWindow() + +*****************************************************************************/ + +BOOL +CreateMainWindow ( + int nCmdShow + ) +{ + RECT rc; + + InitCommonControls(); + + ghMainWnd = CreateDialog(ghInstance, + MAKEINTRESOURCE(IDD_MAINDIALOG), + NULL, + (DLGPROC) MainDlgProc); + + if (ghMainWnd == NULL) + { + OOPS(); + return FALSE; + } + + GetWindowRect(ghMainWnd, &rc); + + gBarLocation = (rc.right - rc.left) / 3; + + ResizeWindows(FALSE, 0); + + ShowWindow(ghMainWnd, nCmdShow); + + UpdateWindow(ghMainWnd); + + return TRUE; +} + + +/***************************************************************************** + +ResizeWindows() + +Handles resizing the two child windows of the main window. If +bSizeBar is true, then the sizing is happening because the user is +moving the bar. If bSizeBar is false, the sizing is happening +because of the WM_SIZE or something like that. + +*****************************************************************************/ + +VOID +ResizeWindows ( + BOOL bSizeBar, + int BarLocation + ) +{ + RECT MainClientRect; + RECT MainWindowRect; + RECT TreeWindowRect; + RECT StatusWindowRect; + int right; + + // Is the user moving the bar? + // + if (!bSizeBar) + { + BarLocation = gBarLocation; + } + + GetClientRect(ghMainWnd, &MainClientRect); + + GetWindowRect(ghStatusWnd, &StatusWindowRect); + + // Make sure the bar is in a OK location + // + if (bSizeBar) + { + if (BarLocation < + GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR) + { + return; + } + + if ((MainClientRect.right - BarLocation) < + GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR) + { + return; + } + } + + // Save the bar location + // + gBarLocation = BarLocation; + + // Move the tree window + // + MoveWindow(ghTreeWnd, + 0, + 0, + BarLocation, + MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top, + TRUE); + + // Get the size of the window (in case move window failed + // + GetWindowRect(ghTreeWnd, &TreeWindowRect); + GetWindowRect(ghMainWnd, &MainWindowRect); + + right = TreeWindowRect.right - MainWindowRect.left; + + // Move the edit window with respect to the tree window + // + MoveWindow(ghEditWnd, + right+SIZEBAR, + 0, + MainClientRect.right-(right+SIZEBAR), + MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top, + TRUE); + + // Move the Status window with respect to the tree window + // + MoveWindow(ghStatusWnd, + 0, + MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top, + MainClientRect.right, + StatusWindowRect.bottom - StatusWindowRect.top, + TRUE); +} + + +/***************************************************************************** + +MainWndProc() + +*****************************************************************************/ + +LRESULT CALLBACK +MainDlgProc ( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + + switch (uMsg) + { + + HANDLE_MSG(hWnd, WM_INITDIALOG, USBView_OnInitDialog); + HANDLE_MSG(hWnd, WM_CLOSE, USBView_OnClose); + HANDLE_MSG(hWnd, WM_COMMAND, USBView_OnCommand); + HANDLE_MSG(hWnd, WM_LBUTTONDOWN, USBView_OnLButtonDown); + HANDLE_MSG(hWnd, WM_LBUTTONUP, USBView_OnLButtonUp); + HANDLE_MSG(hWnd, WM_MOUSEMOVE, USBView_OnMouseMove); + HANDLE_MSG(hWnd, WM_SIZE, USBView_OnSize); + HANDLE_MSG(hWnd, WM_NOTIFY, USBView_OnNotify); + HANDLE_MSG(hWnd, WM_DEVICECHANGE, USBView_OnDeviceChange); + } + + return 0; +} + +/***************************************************************************** + +USBView_OnInitDialog() + +*****************************************************************************/ + +BOOL +USBView_OnInitDialog ( + HWND hWnd, + HWND hWndFocus, + LPARAM lParam + ) +{ + HFONT hFont; + HIMAGELIST himl; + HICON hicon; + DEV_BROADCAST_DEVICEINTERFACE broadcastInterface; + + UNREFERENCED_PARAMETER(lParam); + UNREFERENCED_PARAMETER(hWndFocus); + + // Register to receive notification when a USB device is plugged in. + broadcastInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + broadcastInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + + memcpy( &(broadcastInterface.dbcc_classguid), + &(GUID_DEVINTERFACE_USB_DEVICE), + sizeof(struct _GUID)); + + gNotifyDevHandle = RegisterDeviceNotification(hWnd, + &broadcastInterface, + DEVICE_NOTIFY_WINDOW_HANDLE); + + // Now register for Hub notifications. + memcpy( &(broadcastInterface.dbcc_classguid), + &(GUID_CLASS_USBHUB), + sizeof(struct _GUID)); + + gNotifyHubHandle = RegisterDeviceNotification(hWnd, + &broadcastInterface, + DEVICE_NOTIFY_WINDOW_HANDLE); + + gHubList.DeviceInfo = INVALID_HANDLE_VALUE; + InitializeListHead(&gHubList.ListHead); + gDeviceList.DeviceInfo = INVALID_HANDLE_VALUE; + InitializeListHead(&gDeviceList.ListHead); + + //end add + + ghTreeWnd = GetDlgItem(hWnd, IDC_TREE); + + //added + if ((himl = ImageList_Create(15, 15, + FALSE, 2, 0)) == NULL) + { + OOPS(); + } + + if(himl != NULL) + { + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_ICON)); + giGoodDevice = ImageList_AddIcon(himl, hicon); + + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_BADICON)); + giBadDevice = ImageList_AddIcon(himl, hicon); + + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_COMPUTER)); + giComputer = ImageList_AddIcon(himl, hicon); + + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_HUB)); + giHub = ImageList_AddIcon(himl, hicon); + + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NODEVICE)); + giNoDevice = ImageList_AddIcon(himl, hicon); + + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_SSICON)); + giGoodSsDevice = ImageList_AddIcon(himl, hicon); + + hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NOSSDEVICE)); + giNoSsDevice = ImageList_AddIcon(himl, hicon); + + TreeView_SetImageList(ghTreeWnd, himl, TVSIL_NORMAL); + // end add + } + + ghEditWnd = GetDlgItem(hWnd, IDC_EDIT); + +#ifdef H264_SUPPORT + // set the edit control to have a max text limit size + SendMessage(ghEditWnd, EM_LIMITTEXT, 0 /* USE DEFAULT MAX*/, 0); +#endif + + ghStatusWnd = GetDlgItem(hWnd, IDC_STATUS); + ghMainMenu = GetMenu(hWnd); + if (ghMainMenu == NULL) + { + OOPS(); + } + { + CHAR pszFont[256]; + CHAR pszHeight[8]; + + memset(pszFont, 0, sizeof(pszFont)); + LoadString(ghInstance, IDS_STANDARD_FONT, pszFont, sizeof(pszFont) - 1); + memset(pszHeight, 0, sizeof(pszHeight)); + LoadString(ghInstance, IDS_STANDARD_FONT_HEIGHT, pszHeight, sizeof(pszHeight) - 1); + + hFont = CreateFont((int) pszHeight[0], 0, 0, 0, + 400, 0, 0, 0, + 0, 1, 2, 1, + 49, pszFont); + } + SendMessage(ghEditWnd, + WM_SETFONT, + (WPARAM) hFont, + 0); + + RefreshTree(); + + return FALSE; +} + +/***************************************************************************** + +USBView_OnClose() + +*****************************************************************************/ + +VOID +USBView_OnClose ( + HWND hWnd + ) +{ + + UNREFERENCED_PARAMETER(hWnd); + + DestroyTree(); + + PostQuitMessage(0); +} + + +/***************************************************************************** + +AddItemInformationToFile() + +Saves the information about the current item to the list +*****************************************************************************/ +VOID +AddItemInformationToFile( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ) +{ + HRESULT hr = S_OK; + HANDLE hf = NULL; + DWORD dwBytesWritten = 0; + + hf = *((PHANDLE) pContext); + + ResetTextBuffer(); + + hr = UpdateTreeItemDeviceInfo(hTreeWnd, hTreeItem); + + if (FAILED(hr)) + { + OOPS(); + } + else + { + WriteFile(hf, GetTextBuffer(), GetTextBufferPos()*sizeof(CHAR), &dwBytesWritten, NULL); + } + + ResetTextBuffer(); +} + + + +/***************************************************************************** + +SaveAllInformationAsText() + +Saves the entire USB tree as a text file +*****************************************************************************/ +HRESULT +SaveAllInformationAsText( + LPTSTR lpstrTextFileName, + DWORD dwCreationDisposition + ) +{ + HRESULT hr = S_OK; + HANDLE hf = NULL; + + hf = CreateFile(lpstrTextFileName, + GENERIC_WRITE, + 0, + NULL, + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hf == INVALID_HANDLE_VALUE) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + OOPS(); + } + else + { + if (GetLastError() == ERROR_ALREADY_EXISTS) + { + // CreateFile() sets this error if we are overwriting an existing file + // Reset this error to avoid false alarms + SetLastError(0); + } + + if (ghTreeRoot == NULL) + { + // If tree has not been populated yet, try a refresh + RefreshTree(); + } + + if (ghTreeRoot) + { + + LockFile(hf, 0, 0, 0, 0); + WalkTreeTopDown(ghTreeRoot, AddItemInformationToFile, &hf, NULL); + UnlockFile(hf, 0, 0, 0, 0); + CloseHandle(hf); + + hr = S_OK; + } + else + { + hr = HRESULT_FROM_WIN32(GetLastError()); + OOPS(); + } + } + + ResetTextBuffer(); + return hr; +} + + +/***************************************************************************** + +USBView_OnCommand() + +*****************************************************************************/ + +VOID +USBView_OnCommand ( + HWND hWnd, + int id, + HWND hwndCtl, + UINT codeNotify + ) +{ + MENUITEMINFO menuInfo; + char szFile[MAX_PATH + 1]; + OPENFILENAME ofn; + HANDLE hf = NULL; + DWORD dwBytesWritten = 0; + int nTextLength = 0; + size_t lengthToNull = 0; + HRESULT hr = S_OK; + + UNREFERENCED_PARAMETER(hwndCtl); + UNREFERENCED_PARAMETER(codeNotify); + + //initialize save dialog variables + memset(szFile, 0, sizeof(szFile)); + memset(&ofn, 0, sizeof(OPENFILENAME)); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hWnd; + ofn.nFilterIndex = 1; + ofn.lpstrFile = szFile; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = 0; + ofn.lpstrTitle = NULL; + ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; + + + switch (id) + { + case ID_AUTO_REFRESH: + gDoAutoRefresh = !gDoAutoRefresh; + menuInfo.cbSize = sizeof(menuInfo); + menuInfo.fMask = MIIM_STATE; + menuInfo.fState = gDoAutoRefresh ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(ghMainMenu, + id, + FALSE, + &menuInfo); + break; + + case ID_SAVE: + { + // initialize the save file name + StringCchCopy(szFile, MAX_PATH, "USBView.txt"); + ofn.lpstrFilter = "Text\0*.TXT\0\0"; + ofn.lpstrDefExt = "txt"; + + //call dialog box + if (! GetSaveFileName(&ofn)) + { + OOPS(); + break; + } + + //create new file + hf = CreateFile((LPTSTR)ofn.lpstrFile, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hf == INVALID_HANDLE_VALUE) + { + OOPS(); + } + else + { + char *szText = NULL; + + //get data from display window to transfer to file + nTextLength = GetWindowTextLength(ghEditWnd); + nTextLength++; + + szText = ALLOC((DWORD)nTextLength); + if (NULL != szText) + { + GetWindowText(ghEditWnd, (LPSTR) szText, nTextLength); + + // + // Constrain length to the first null, which should be at + // the end of the window text. This prevents writing extra + // null characters. + // + if (StringCchLength(szText, nTextLength, &lengthToNull) == S_OK) + { + nTextLength = (int) lengthToNull; + + //lock the file, write to the file, unlock file + LockFile(hf, 0, 0, 0, 0); + + WriteFile(hf, szText, nTextLength, &dwBytesWritten, NULL); + + UnlockFile(hf, 0, 0, 0, 0); + } + else + { + OOPS(); + } + CloseHandle(hf); + FREE(szText); + } + else + { + OOPS(); + } + } + + break; + } + + case ID_SAVEALL: + { + // initialize the save file name + StringCchCopy(szFile, MAX_PATH, "USBViewAll.txt"); + ofn.lpstrFilter = "Text\0*.txt\0\0"; + ofn.lpstrDefExt = "txt"; + + //call dialog box + if (! GetSaveFileName(&ofn)) + { + OOPS(); + break; + } + + // Save the file, overwrite in case of UI since UI gives popup for confirmation + hr = SaveAllInformationAsText(ofn.lpstrFile, CREATE_ALWAYS); + if (FAILED(hr)) + { + OOPS(); + } + + break; + } + + case ID_SAVEXML: + { + // initialize the save file name + StringCchCopy(szFile, MAX_PATH, "USBViewAll.xml"); + ofn.lpstrFilter = "Xml\0*.xml\0\0"; + ofn.lpstrDefExt = "xml"; + + //call dialog box + if (! GetSaveFileName(&ofn)) + { + OOPS(); + break; + } + + // Save the file, overwrite in case of UI since UI gives popup for confirmation + hr = SaveAllInformationAsXml(ofn.lpstrFile, CREATE_ALWAYS); + if (FAILED(hr)) + { + OOPS(); + } + + break; + } + + case ID_CONFIG_DESCRIPTORS: + gDoConfigDesc = !gDoConfigDesc; + menuInfo.cbSize = sizeof(menuInfo); + menuInfo.fMask = MIIM_STATE; + menuInfo.fState = gDoConfigDesc ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(ghMainMenu, + id, + FALSE, + &menuInfo); + break; + + case ID_ANNOTATION: + gDoAnnotation = !gDoAnnotation; + menuInfo.cbSize = sizeof(menuInfo); + menuInfo.fMask = MIIM_STATE; + menuInfo.fState = gDoAnnotation ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(ghMainMenu, + id, + FALSE, + &menuInfo); + break; + + case ID_LOG_DEBUG: + gLogDebug = !gLogDebug; + menuInfo.cbSize = sizeof(menuInfo); + menuInfo.fMask = MIIM_STATE; + menuInfo.fState = gLogDebug ? MFS_CHECKED : MFS_UNCHECKED; + SetMenuItemInfo(ghMainMenu, + id, + FALSE, + &menuInfo); + break; + + case ID_ABOUT: + DialogBox(ghInstance, + MAKEINTRESOURCE(IDD_ABOUT), + ghMainWnd, + (DLGPROC) AboutDlgProc); + break; + + case ID_EXIT: + UnregisterDeviceNotification(gNotifyDevHandle); + UnregisterDeviceNotification(gNotifyHubHandle); + DestroyTree(); + PostQuitMessage(0); + break; + + case ID_REFRESH: + RefreshTree(); + break; + } +} + +/***************************************************************************** + +USBView_OnLButtonDown() + +*****************************************************************************/ + +VOID +USBView_OnLButtonDown ( + HWND hWnd, + BOOL fDoubleClick, + int x, + int y, + UINT keyFlags + ) +{ + + UNREFERENCED_PARAMETER(fDoubleClick); + UNREFERENCED_PARAMETER(x); + UNREFERENCED_PARAMETER(y); + UNREFERENCED_PARAMETER(keyFlags); + + gbButtonDown = TRUE; + SetCapture(hWnd); +} + +/***************************************************************************** + +USBView_OnLButtonUp() + +*****************************************************************************/ + +VOID +USBView_OnLButtonUp ( + HWND hWnd, + int x, + int y, + UINT keyFlags + ) +{ + + UNREFERENCED_PARAMETER(hWnd); + UNREFERENCED_PARAMETER(x); + UNREFERENCED_PARAMETER(y); + UNREFERENCED_PARAMETER(keyFlags); + + gbButtonDown = FALSE; + ReleaseCapture(); +} + +/***************************************************************************** + +USBView_OnMouseMove() + +*****************************************************************************/ + +VOID +USBView_OnMouseMove ( + HWND hWnd, + int x, + int y, + UINT keyFlags + ) +{ + UNREFERENCED_PARAMETER(hWnd); + UNREFERENCED_PARAMETER(y); + UNREFERENCED_PARAMETER(keyFlags); + + SetCursor(ghSplitCursor); + + if (gbButtonDown) + { + ResizeWindows(TRUE, x); + } +} + +/***************************************************************************** + +USBView_OnSize(); + +*****************************************************************************/ + +VOID +USBView_OnSize ( + HWND hWnd, + UINT state, + int cx, + int cy + ) +{ + UNREFERENCED_PARAMETER(hWnd); + UNREFERENCED_PARAMETER(state); + UNREFERENCED_PARAMETER(cx); + UNREFERENCED_PARAMETER(cy); + + ResizeWindows(FALSE, 0); +} + +/***************************************************************************** + +USBView_OnNotify() + +*****************************************************************************/ + +LRESULT +USBView_OnNotify ( + HWND hWnd, + int DlgItem, + LPNMHDR lpNMHdr + ) +{ + UNREFERENCED_PARAMETER(hWnd); + UNREFERENCED_PARAMETER(DlgItem); + + if (lpNMHdr->code == TVN_SELCHANGED) + { + HTREEITEM hTreeItem; + + hTreeItem = ((NM_TREEVIEW *)lpNMHdr)->itemNew.hItem; + + if (hTreeItem) + { + UpdateEditControl(ghEditWnd, + ghTreeWnd, + hTreeItem); + } + } + + return 0; +} + + +/***************************************************************************** + +USBView_OnDeviceChange() + +*****************************************************************************/ + +BOOL +USBView_OnDeviceChange ( + HWND hwnd, + UINT uEvent, + DWORD dwEventData + ) +{ + UNREFERENCED_PARAMETER(hwnd); + UNREFERENCED_PARAMETER(dwEventData); + + if (gDoAutoRefresh) + { + switch (uEvent) + { + case DBT_DEVICEARRIVAL: + case DBT_DEVICEREMOVECOMPLETE: + RefreshTree(); + break; + } + } + + return TRUE; +} + + + +/***************************************************************************** + +DestroyTree() + +*****************************************************************************/ + +VOID DestroyTree (VOID) +{ + // Clear the selection of the TreeView, so that when the tree is + // destroyed, the control won't try to constantly "shift" the + // selection to another item. + // + TreeView_SelectItem(ghTreeWnd, NULL); + + // Destroy the current contents of the TreeView + // + if (ghTreeRoot) + { + WalkTree(ghTreeRoot, CleanupItem, NULL); + + TreeView_DeleteAllItems(ghTreeWnd); + + ghTreeRoot = NULL; + } + + ClearDeviceList(&gDeviceList); + ClearDeviceList(&gHubList); +} + +/***************************************************************************** + +RefreshTree() + +*****************************************************************************/ + +VOID RefreshTree (VOID) +{ + CHAR statusText[128]; + ULONG devicesConnected; + + // Clear the edit control + // + SetWindowText(ghEditWnd, ""); + + // Destroy the current contents of the TreeView + // + DestroyTree(); + + // Create the root tree node + // + ghTreeRoot = AddLeaf(TVI_ROOT, 0, "My Computer", ComputerIcon); + + if (ghTreeRoot != NULL) + { + // Enumerate all USB buses and populate the tree + // + EnumerateHostControllers(ghTreeRoot, &devicesConnected); + + // + // Expand all tree nodes + // + WalkTree(ghTreeRoot, ExpandItem, NULL); + + // Update Status Line with number of devices connected + // + memset(statusText, 0, sizeof(statusText)); + StringCchPrintf(statusText, sizeof(statusText), +#ifdef H264_SUPPORT + "UVC Spec Version: %d.%d Version: %d.%d Devices Connected: %d Hubs Connected: %d", + UVC_SPEC_MAJOR_VERSION, UVC_SPEC_MINOR_VERSION, USBVIEW_MAJOR_VERSION, USBVIEW_MINOR_VERSION, + devicesConnected, TotalHubs); +#else + "Devices Connected: %d Hubs Connected: %d", + devicesConnected, TotalHubs); +#endif + + SetWindowText(ghStatusWnd, statusText); + } + else + { + OOPS(); + } + +} + +/***************************************************************************** + +AboutDlgProc() + +*****************************************************************************/ + +LRESULT CALLBACK +AboutDlgProc ( + HWND hwnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + UNREFERENCED_PARAMETER(lParam); + + switch (uMsg) + { + case WM_INITDIALOG: + { + HRESULT hr; + char TextBuffer[TEXT_ITEM_LENGTH]; + HWND hItem; + + hItem = GetDlgItem(hwnd, IDC_VERSION); + + if (hItem != NULL) + { + hr = StringCbPrintfA(TextBuffer, + sizeof(TextBuffer), + "USBView version: %d.%d", + USBVIEW_MAJOR_VERSION, + USBVIEW_MINOR_VERSION); + if (SUCCEEDED(hr)) + { + SetWindowText(hItem,TextBuffer); + } + } + + hItem = GetDlgItem(hwnd, IDC_UVCVERSION); + + if (hItem != NULL) + { + hr = StringCbPrintfA(TextBuffer, + sizeof(TextBuffer), + "USB Video Class Spec version: %d.%d", + UVC_SPEC_MAJOR_VERSION, + UVC_SPEC_MINOR_VERSION); + if (SUCCEEDED(hr)) + { + SetWindowText(hItem,TextBuffer); + } + } + } + break; + case WM_COMMAND: + + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + + EndDialog (hwnd, 0); + break; + } + break; + + } + + return FALSE; +} + + +/***************************************************************************** + +AddLeaf() + +*****************************************************************************/ + +HTREEITEM +AddLeaf ( + HTREEITEM hTreeParent, + LPARAM lParam, + _In_ LPTSTR lpszText, + TREEICON TreeIcon + ) +{ + TV_INSERTSTRUCT tvins; + HTREEITEM hti; + + memset(&tvins, 0, sizeof(tvins)); + + // Set the parent item + // + tvins.hParent = hTreeParent; + + tvins.hInsertAfter = TVI_LAST; + + // pszText and lParam members are valid + // + tvins.item.mask = TVIF_TEXT | TVIF_PARAM; + + // Set the text of the item. + // + tvins.item.pszText = lpszText; + + // Set the user context item + // + tvins.item.lParam = lParam; + + // Add the item to the tree-view control. + // + hti = TreeView_InsertItem(ghTreeWnd, &tvins); + + // added + tvins.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvins.item.hItem = hti; + + // Determine which icon to display for the device + // + switch (TreeIcon) + { + case ComputerIcon: + tvins.item.iImage = giComputer; + tvins.item.iSelectedImage = giComputer; + break; + + case HubIcon: + tvins.item.iImage = giHub; + tvins.item.iSelectedImage = giHub; + break; + + case NoDeviceIcon: + tvins.item.iImage = giNoDevice; + tvins.item.iSelectedImage = giNoDevice; + break; + + case GoodDeviceIcon: + tvins.item.iImage = giGoodDevice; + tvins.item.iSelectedImage = giGoodDevice; + break; + + case GoodSsDeviceIcon: + tvins.item.iImage = giGoodSsDevice; + tvins.item.iSelectedImage = giGoodSsDevice; + break; + + case NoSsDeviceIcon: + tvins.item.iImage = giNoSsDevice; + tvins.item.iSelectedImage = giNoSsDevice; + break; + + case BadDeviceIcon: + default: + tvins.item.iImage = giBadDevice; + tvins.item.iSelectedImage = giBadDevice; + break; + } + TreeView_SetItem(ghTreeWnd, &tvins.item); + + return hti; +} + + +/***************************************************************************** + +WalkTreeTopDown() + +*****************************************************************************/ + +VOID +WalkTreeTopDown( + _In_ HTREEITEM hTreeItem, + _In_ LPFNTREECALLBACK lpfnTreeCallback, + _In_opt_ PVOID pContext, + _In_opt_ LPFNTREENOTIFYCALLBACK lpfnTreeNotifyCallback + ) +{ + if (hTreeItem) + { + HTREEITEM hTreeChild = TreeView_GetChild(ghTreeWnd, hTreeItem); + HTREEITEM hTreeSibling = TreeView_GetNextSibling(ghTreeWnd, hTreeItem); + + // + // Call the lpfnCallBack on the node itself. + // + (*lpfnTreeCallback)(ghTreeWnd, hTreeItem, pContext); + + // + // Recursively call WalkTree on the node's first child. + // + + if (hTreeChild) + { + WalkTreeTopDown(hTreeChild, + lpfnTreeCallback, + pContext, + lpfnTreeNotifyCallback); + } + + // + // Recursively call WalkTree on the node's first sibling. + // + if (hTreeSibling) + { + WalkTreeTopDown(hTreeSibling, + lpfnTreeCallback, + pContext, + lpfnTreeNotifyCallback); + } + else + { + // If there are no more siblings, we have reached the end of + // list of child nodes. Call notify function + if (lpfnTreeNotifyCallback != NULL) + { + (*lpfnTreeNotifyCallback)(pContext); + } + } + } +} + +/***************************************************************************** + +WalkTree() + +*****************************************************************************/ + +VOID +WalkTree ( + _In_ HTREEITEM hTreeItem, + _In_ LPFNTREECALLBACK lpfnTreeCallback, + _In_opt_ PVOID pContext + ) +{ + if (hTreeItem) + { + // Recursively call WalkTree on the node's first child. + // + WalkTree(TreeView_GetChild(ghTreeWnd, hTreeItem), + lpfnTreeCallback, + pContext); + + // + // Call the lpfnCallBack on the node itself. + // + (*lpfnTreeCallback)(ghTreeWnd, hTreeItem, pContext); + + // + // + // Recursively call WalkTree on the node's first sibling. + // + WalkTree(TreeView_GetNextSibling(ghTreeWnd, hTreeItem), + lpfnTreeCallback, + pContext); + } +} + +/***************************************************************************** + +ExpandItem() + +*****************************************************************************/ + +VOID +ExpandItem ( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ) +{ + // + // Make this node visible. + // + UNREFERENCED_PARAMETER(pContext); + + TreeView_Expand(hTreeWnd, hTreeItem, TVE_EXPAND); +} + +/***************************************************************************** + +SaveAllInformationAsXML() + +Saves the entire USB tree as an XML file +*****************************************************************************/ +HRESULT +SaveAllInformationAsXml( + LPTSTR lpstrTextFileName, + DWORD dwCreationDisposition + ) +{ + HRESULT hr = S_OK; + + if (ghTreeRoot == NULL) + { + // If tree has not been populated yet, try a refresh + RefreshTree(); + } + if (ghTreeRoot) + { + WalkTreeTopDown(ghTreeRoot, AddItemInformationToXmlView, NULL, XmlNotifyEndOfNodeList); + + hr = SaveXml(lpstrTextFileName, dwCreationDisposition); + } + else + { + hr = E_FAIL; + OOPS(); + } + ResetTextBuffer(); + return hr; +} + +//***************************************************************************** +// +// AddItemInformationToXmlView +// +// hTreeItem - Handle of selected TreeView item for which information should +// be added to the XML View +// +//***************************************************************************** +VOID +AddItemInformationToXmlView( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ) +{ + TV_ITEM tvi; + PVOID info; + PCHAR tviName = NULL; + + UNREFERENCED_PARAMETER(pContext); + +#ifdef H264_SUPPORT + ResetErrorCounts(); +#endif + + tviName = (PCHAR) ALLOC(256); + + if (NULL == tviName) + { + return; + } + + // + // Get the name of the TreeView item, along with the a pointer to the + // info we stored about the item in the item's lParam. + // + + tvi.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM; + tvi.hItem = hTreeItem; + tvi.pszText = (LPSTR) tviName; + tvi.cchTextMax = 256; + + TreeView_GetItem(hTreeWnd, + &tvi); + + info = (PVOID)tvi.lParam; + + if (NULL != info) + { + // + // Add Item to XML object + // + switch (*(PUSBDEVICEINFOTYPE)info) + { + case HostControllerInfo: + XmlAddHostController(tviName, (PUSBHOSTCONTROLLERINFO) info); + break; + + case RootHubInfo: + XmlAddRootHub(tviName, (PUSBROOTHUBINFO) info); + break; + + case ExternalHubInfo: + XmlAddExternalHub(tviName, (PUSBEXTERNALHUBINFO) info); + break; + + case DeviceInfo: + XmlAddUsbDevice(tviName, (PUSBDEVICEINFO) info); + break; + } + + } + return; +} + +/***************************************************************************** + +DisplayLastError() + +*****************************************************************************/ + +DWORD +DisplayLastError( + _Inout_updates_bytes_(count) char *szString, + int count) +{ + LPVOID lpMsgBuf; + + // get the last error code + DWORD dwError = GetLastError(); + + // get the system message for this error code + if (FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL )) + { + StringCchPrintf(szString, count, "Error: %s", (LPTSTR)lpMsgBuf ); + } + + // Free the local buffer + LocalFree( lpMsgBuf ); + + // return the error + return dwError; +} + +#if DBG + +/***************************************************************************** + +Oops() + +*****************************************************************************/ + +VOID +Oops +( + _In_ PCHAR File, + ULONG Line + ) +{ + char szBuf[1024]; + LPTSTR lpMsgBuf; + DWORD dwGLE = GetLastError(); + + memset(szBuf, 0, sizeof(szBuf)); + + // get the system message for this error code + if (FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwGLE, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL)) + { + StringCchPrintf(szBuf, sizeof(szBuf), + "File: %s, Line %d\r\nGetLastError 0x%x %u %s\n", + File, Line, dwGLE, dwGLE, lpMsgBuf); + } + else + { + StringCchPrintf(szBuf, sizeof(szBuf), + "File: %s, Line %d\r\nGetLastError 0x%x %u\r\n", + File, Line, dwGLE, dwGLE); + } + OutputDebugString(szBuf); + + // Free the system allocated local buffer + LocalFree(lpMsgBuf); + + return; +} + +#endif diff --git a/tests/projects/windows/winsdk/usbview/uvcview.h b/tests/projects/windows/winsdk/usbview/uvcview.h new file mode 100644 index 000000000..d5c3f5786 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/uvcview.h @@ -0,0 +1,675 @@ +/*++ + +Copyright (c) 1997-2008 Microsoft Corporation + +Module Name: + + UVCVIEW.H + +Abstract: + + This is the header file for UVCVIEW + +Environment: + + user mode + +Revision History: + + 04-25-97 : created + 04/13/2005 : major bug fixing + +--*/ + +/***************************************************************************** + I N C L U D E S +*****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This is mostly a private USB Audio descriptor header +#include "usbdesc.h" + +// This is the inbox USBVideo driver descriptor header (copied locally) +#include "uvcdesc.h" + +/***************************************************************************** + P R A G M A S +*****************************************************************************/ + +#pragma once + +/***************************************************************************** + D E F I N E S +*****************************************************************************/ + +// define H264_SUPPORT to add H.264 support to uvcview.exe +#define H264_SUPPORT + +#define TEXT_ITEM_LENGTH 64 + +#ifdef DEBUG +#undef DBG +#define DBG 1 +#endif + +#if DBG +#define OOPS() Oops(__FILE__, __LINE__) +#else +#define OOPS() +#endif + +#if DBG + +#define ALLOC(dwBytes) MyAlloc(__FILE__, __LINE__, (dwBytes)) + +#define REALLOC(hMem, dwBytes) MyReAlloc((hMem), (dwBytes)) + +#define FREE(hMem) MyFree((hMem)) + +#define CHECKFORLEAKS() MyCheckForLeaks() + +#else + +#define ALLOC(dwBytes) GlobalAlloc(GPTR,(dwBytes)) + +#define REALLOC(hMem, dwBytes) GlobalReAlloc((hMem), (dwBytes), (GMEM_MOVEABLE|GMEM_ZEROINIT)) + +#define FREE(hMem) GlobalFree((hMem)) + +#define CHECKFORLEAKS() + +#endif + +#define DEVICE_CONFIGURATION_TEXT_LENGTH 10240 + +#define STR_INVALID_POWER_STATE "(invalid state) " +#define STR_UNKNOWN_CONTROLLER_FLAVOR "Unknown" + +FORCEINLINE +VOID +InitializeListHead( + _Out_ PLIST_ENTRY ListHead + ) +{ + ListHead->Flink = ListHead->Blink = ListHead; +} + +// +// BOOLEAN +// IsListEmpty( +// PLIST_ENTRY ListHead +// ); +// + +#define IsListEmpty(ListHead) \ + ((ListHead)->Flink == (ListHead)) + +// +// PLIST_ENTRY +// RemoveHeadList( +// PLIST_ENTRY ListHead +// ); +// + +#define RemoveHeadList(ListHead) \ + (ListHead)->Flink;\ + {RemoveEntryList((ListHead)->Flink)} + +// +// VOID +// RemoveEntryList( +// PLIST_ENTRY Entry +// ); +// + +#define RemoveEntryList(Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_Flink;\ + _EX_Flink = (Entry)->Flink;\ + _EX_Blink = (Entry)->Blink;\ + _EX_Blink->Flink = _EX_Flink;\ + _EX_Flink->Blink = _EX_Blink;\ + } + +// +// VOID +// InsertTailList( +// PLIST_ENTRY ListHead, +// PLIST_ENTRY Entry +// ); +// + +#define InsertTailList(ListHead,Entry) {\ + PLIST_ENTRY _EX_Blink;\ + PLIST_ENTRY _EX_ListHead;\ + _EX_ListHead = (ListHead);\ + _EX_Blink = _EX_ListHead->Blink;\ + (Entry)->Flink = _EX_ListHead;\ + (Entry)->Blink = _EX_Blink;\ + _EX_Blink->Flink = (Entry);\ + _EX_ListHead->Blink = (Entry);\ + } + +// global version for USB Video Class spec version (pre-release) +#define BCDVDC 0x0083 + +// A.2 Video Interface Subclass Codes +#define SC_VIDEO_INTERFACE_COLLECTION 0x03 + +// A.3 Video Interface Protocol Codes +#define PC_PROTOCOL_UNDEFINED 0x00 + +// USB Video Class spec version +#define NOT_UVC 0x0 +#define UVC10 0x100 +#define UVC11 0x110 + +#ifdef H264_SUPPORT +#define UVC15 0x150 +#endif + +#define OUTPUT_MESSAGE_MAX_LENGTH 1024 +#define MAX_DEVICE_PROP 200 +#define MAX_DRIVER_KEY_NAME 256 + +/***************************************************************************** + T Y P E D E F S +*****************************************************************************/ + +typedef enum _TREEICON +{ + ComputerIcon, + HubIcon, + NoDeviceIcon, + GoodDeviceIcon, + BadDeviceIcon, + GoodSsDeviceIcon, + NoSsDeviceIcon +} TREEICON; + +// Callback function for walking TreeView items +// +typedef VOID +(*LPFNTREECALLBACK)( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext +); + + +// Callback notification function called at end of every tree depth +typedef VOID +(*LPFNTREENOTIFYCALLBACK)(PVOID pContext); + +// +// Structure used to build a linked list of String Descriptors +// retrieved from a device. +// + +typedef struct _STRING_DESCRIPTOR_NODE +{ + struct _STRING_DESCRIPTOR_NODE *Next; + UCHAR DescriptorIndex; + USHORT LanguageID; + USB_STRING_DESCRIPTOR StringDescriptor[1]; +} STRING_DESCRIPTOR_NODE, *PSTRING_DESCRIPTOR_NODE; + +// +// A collection of device properties. The device can be hub, host controller or usb device +// +typedef struct _USB_DEVICE_PNP_STRINGS +{ + PCHAR DeviceId; + PCHAR DeviceDesc; + PCHAR HwId; + PCHAR Service; + PCHAR DeviceClass; + PCHAR PowerState; +} USB_DEVICE_PNP_STRINGS, *PUSB_DEVICE_PNP_STRINGS; + +typedef struct _DEVICE_INFO_NODE { + HDEVINFO DeviceInfo; + LIST_ENTRY ListEntry; + SP_DEVINFO_DATA DeviceInfoData; + SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceDetailData; + PSTR DeviceDescName; + ULONG DeviceDescNameLength; + PSTR DeviceDriverName; + ULONG DeviceDriverNameLength; + DEVICE_POWER_STATE LatestDevicePowerState; +} DEVICE_INFO_NODE, *PDEVICE_INFO_NODE; + +// +// Structures assocated with TreeView items through the lParam. When an item +// is selected, the lParam is retrieved and the structure it which it points +// is used to display information in the edit control. +// + +typedef enum _USBDEVICEINFOTYPE +{ + HostControllerInfo, + RootHubInfo, + ExternalHubInfo, + DeviceInfo +} USBDEVICEINFOTYPE, *PUSBDEVICEINFOTYPE; + +typedef struct _USBHOSTCONTROLLERINFO +{ + USBDEVICEINFOTYPE DeviceInfoType; + LIST_ENTRY ListEntry; + PCHAR DriverKey; + ULONG VendorID; + ULONG DeviceID; + ULONG SubSysID; + ULONG Revision; + USB_POWER_INFO USBPowerInfo[6]; + BOOL BusDeviceFunctionValid; + ULONG BusNumber; + USHORT BusDevice; + USHORT BusFunction; + PUSB_CONTROLLER_INFO_0 ControllerInfo; + PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; +} USBHOSTCONTROLLERINFO, *PUSBHOSTCONTROLLERINFO; + +typedef struct _USBROOTHUBINFO +{ + USBDEVICEINFOTYPE DeviceInfoType; + PUSB_NODE_INFORMATION HubInfo; + PUSB_HUB_INFORMATION_EX HubInfoEx; + PCHAR HubName; + PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps; + PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; + PDEVICE_INFO_NODE DeviceInfoNode; + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx; + +} USBROOTHUBINFO, *PUSBROOTHUBINFO; + +typedef struct _USBEXTERNALHUBINFO +{ + USBDEVICEINFOTYPE DeviceInfoType; + PUSB_NODE_INFORMATION HubInfo; + PUSB_HUB_INFORMATION_EX HubInfoEx; + PCHAR HubName; + PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo; + PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps; + PUSB_DESCRIPTOR_REQUEST ConfigDesc; + PUSB_DESCRIPTOR_REQUEST BosDesc; + PSTRING_DESCRIPTOR_NODE StringDescs; + PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2; // NULL if root HUB + PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; + PDEVICE_INFO_NODE DeviceInfoNode; + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx; +} USBEXTERNALHUBINFO, *PUSBEXTERNALHUBINFO; + + +// HubInfo, HubName may be in USBDEVICEINFOTYPE, so they can be removed +typedef struct +{ + USBDEVICEINFOTYPE DeviceInfoType; + PUSB_NODE_INFORMATION HubInfo; // NULL if not a HUB + PUSB_HUB_INFORMATION_EX HubInfoEx; // NULL if not a HUB + PCHAR HubName; // NULL if not a HUB + PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo; // NULL if root HUB + PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps; + PUSB_DESCRIPTOR_REQUEST ConfigDesc; // NULL if root HUB + PUSB_DESCRIPTOR_REQUEST BosDesc; // NULL if root HUB + PSTRING_DESCRIPTOR_NODE StringDescs; + PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2; // NULL if root HUB + PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; + PDEVICE_INFO_NODE DeviceInfoNode; + PUSB_HUB_CAPABILITIES_EX HubCapabilityEx; // NULL if not a HUB +} USBDEVICEINFO, *PUSBDEVICEINFO; + +typedef struct _STRINGLIST +{ +#ifdef H264_SUPPORT + ULONGLONG ulFlag; +#else + ULONG ulFlag; +#endif + PCHAR pszString; + PCHAR pszModifier; + +} STRINGLIST, * PSTRINGLIST; + +typedef struct _DEVICE_GUID_LIST { + HDEVINFO DeviceInfo; + LIST_ENTRY ListHead; +} DEVICE_GUID_LIST, *PDEVICE_GUID_LIST; + + +/***************************************************************************** + G L O B A L S +*****************************************************************************/ + +// +// USBVIEW.C +// + +BOOL gDoConfigDesc; +BOOL gDoAnnotation; +BOOL gLogDebug; +int TotalHubs; + +// +// ENUM.C +// + +PCHAR ConnectionStatuses[]; + +// +// DISPVID.C +// +DEFINE_GUID(YUY2_Format,0x32595559L,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); +DEFINE_GUID(NV12_Format,0x3231564EL,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); + +#ifdef H264_SUPPORT +DEFINE_GUID(H264_Format,0x34363248, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); +#endif + +// The following flags/variables are all initialized in Display.c InitializePerDeviceSettings() +// +// Save the default frame from the MJPEG, Uncompressed, Vendor and Frame Based Format descriptor +// Check for this when processing the individual Frame descriptors +UCHAR g_chMJPEGFrameDefault; +UCHAR g_chUNCFrameDefault; +UCHAR g_chVendorFrameDefault; +UCHAR g_chFrameBasedFrameDefault; + +// Spec version of UVC device +UINT g_chUVCversion; + +// Base address of the USBDEVICEINFO for device we're parsing +PUSBDEVICEINFO CurrentUSBDeviceInfo; + +// Base address of the Configuration descriptor we're parsing +PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigDesc; + +// Length of the current configuration descriptor +DWORD dwConfigLength; +// Our current position from the beginning of the config descriptor +DWORD dwConfigIndex; + +// +// DISPLAY.C +// +int gDeviceSpeed; + +// Save the current Configuration starting and ending addresses +// Used in ValidateDescAddress() +// +PUSB_CONFIGURATION_DESCRIPTOR g_pConfigDesc; +PSTRING_DESCRIPTOR_NODE g_pStringDescs; +PUCHAR g_descEnd; + +/***************************************************************************** + F U N C T I O N P R O T O T Y P E S +*****************************************************************************/ + +// +// USBVIEW.C +// + +HTREEITEM +AddLeaf ( + HTREEITEM hTreeParent, + LPARAM lParam, + _In_ LPTSTR lpszText, + TREEICON TreeIcon +); + +VOID +Oops +( + _In_ PCHAR File, + ULONG Line +); + +// +// DISPLAY.C +// + +EXTERN_C UINT IsIADDevice (PUSBDEVICEINFO info); +EXTERN_C UINT IsUVCDevice (PUSBDEVICEINFO info); +EXTERN_C PCHAR GetVendorString(USHORT idVendor); +EXTERN_C PCHAR GetLangIDString(USHORT idLang); +EXTERN_C UINT GetConfigurationSize (PUSBDEVICEINFO info); +EXTERN_C PUSB_COMMON_DESCRIPTOR +GetNextDescriptor( + _In_reads_bytes_(TotalLength) + PUSB_COMMON_DESCRIPTOR FirstDescriptor, + _In_ + ULONG TotalLength, + _In_ + PUSB_COMMON_DESCRIPTOR StartDescriptor, + _In_ long + DescriptorType + ); + +HRESULT +UpdateTreeItemDeviceInfo( + HWND hTreeWnd, + HTREEITEM hTreeItem + ); + +PCHAR +GetTextBuffer( +); + +BOOL +ResetTextBuffer( +); + +BOOL +CreateTextBuffer ( +); + +VOID +DestroyTextBuffer ( +); + +UINT +GetTextBufferPos ( +); + +VOID +UpdateEditControl ( + HWND hEditWnd, + HWND hTreeWnd, + HTREEITEM hTreeItem +); + + +VOID __cdecl +AppendBuffer ( + LPCTSTR lpFormat, + ... +); + +VOID __cdecl +AppendTextBuffer ( + LPCTSTR lpFormat, + ... +); + +VOID +DisplayStringDescriptor ( + UCHAR Index, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState +); + +PCHAR +GetStringFromList( + PSTRINGLIST slPowerState, + ULONG ulNumElements, + +#ifdef H264_SUPPORT + ULONGLONG ulFlag, +#else + ULONG ulFlag, +#endif + _In_ PCHAR szDefault + ); + +EXTERN_C PCHAR GetPowerStateString( + WDMUSB_POWER_STATE powerState + ); + +EXTERN_C PCHAR GetControllerFlavorString( + USB_CONTROLLER_FLAVOR flavor + ); + +EXTERN_C ULONG GetEhciDebugPort( + ULONG vendorId, + ULONG deviceId + ); + +VOID +WalkTreeTopDown( + _In_ HTREEITEM hTreeItem, + _In_ LPFNTREECALLBACK lpfnTreeCallback, + _In_opt_ PVOID pContext, + _In_opt_ LPFNTREENOTIFYCALLBACK lpfnTreeNotifyCallback + ); + +VOID RefreshTree (VOID); + +// +// ENUM.C +// + +VOID +EnumerateHostControllers ( + HTREEITEM hTreeParent, + ULONG *DevicesConnected + ); + + +VOID +CleanupItem ( + HWND hTreeWnd, + HTREEITEM hTreeItem, + PVOID pContext + ); + +DEVICE_POWER_STATE +AcquireDevicePowerState( + _Inout_ PDEVICE_INFO_NODE pNode + ); + +_Success_(return == TRUE) +BOOL +GetDeviceProperty( + _In_ HDEVINFO DeviceInfoSet, + _In_ PSP_DEVINFO_DATA DeviceInfoData, + _In_ DWORD Property, + _Outptr_ LPTSTR *ppBuffer + ); + +void +ClearDeviceList( + PDEVICE_GUID_LIST DeviceList + ); + +// +// DEBUG.C +// + +_Success_(return != NULL) +_Post_writable_byte_size_(dwBytes) +HGLOBAL +MyAlloc ( + _In_ PCHAR File, + ULONG Line, + DWORD dwBytes + ); + +_Success_(return != NULL) +_Post_writable_byte_size_(dwBytes) +HGLOBAL +MyReAlloc ( + HGLOBAL hMem, + DWORD dwBytes + ); + +HGLOBAL +MyFree ( + HGLOBAL hMem + ); + +VOID +MyCheckForLeaks ( + VOID + ); + +// +// DEVNODE.C +// + + +PUSB_DEVICE_PNP_STRINGS +DriverNameToDeviceProperties( + _In_reads_bytes_(cbDriverName) PCHAR DriverName, + _In_ size_t cbDriverName + ); + +VOID FreeDeviceProperties( + _In_ PUSB_DEVICE_PNP_STRINGS *ppDevProps + ); +// +// DISPAUD.C +// + +BOOL +DisplayAudioDescriptor ( + PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc, + UCHAR bInterfaceSubClass + ); + +// +// DISPVID.C +// + +BOOL +DisplayVideoDescriptor ( + PVIDEO_SPECIFIC VidCommonDesc, + UCHAR bInterfaceSubClass, + PSTRING_DESCRIPTOR_NODE StringDescs, + DEVICE_POWER_STATE LatestDevicePowerState + ); + +// +// DISPLAY.C +// + +BOOL +ValidateDescAddress ( + PUSB_COMMON_DESCRIPTOR commonDesc + ); diff --git a/tests/projects/windows/winsdk/usbview/uvcview.rc b/tests/projects/windows/winsdk/usbview/uvcview.rc new file mode 100644 index 000000000..6c7642ce3 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/uvcview.rc @@ -0,0 +1,152 @@ +#include +#include +#include "resource.h" +#include + +////////////////////////////////////////////////////////////////////////////// +// +// VERSION +// +#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) USB device viewer" +#define VER_INTERNALNAME_STR "USBView" +#define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR +#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1996-2011 All Rights Reserved." + +#define VER_FILETYPE VFT_APP +#define VER_FILESUBTYPE VFT2_UNKNOWN + +#include + + +////////////////////////////////////////////////////////////////////////////// +// +// ICON +// +IDI_ICON ICON DISCARDABLE "USB.ICO" +IDI_BADICON ICON DISCARDABLE "BANG.ICO" +IDI_COMPUTER ICON DISCARDABLE "MONITOR.ICO" +IDI_HUB ICON DISCARDABLE "HUB.ICO" +IDI_NODEVICE ICON DISCARDABLE "PORT.ICO" +IDI_NOSSDEVICE ICON DISCARDABLE "SSPORT.ICO" +IDI_SSICON ICON DISCARDABLE "SSUSB.ICO" + +////////////////////////////////////////////////////////////////////////////// +// +// Cursor +// +IDC_SPLIT CURSOR DISCARDABLE "SPLIT.CUR" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_MAINDIALOG DIALOGEX 0, 0, 415, 243 +STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | + WS_THICKFRAME +CAPTION "USB Device Viewer" +MENU IDR_MENU +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "Tree1",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_LINESATROOT | WS_BORDER | WS_TABSTOP, + 0,0,120,234,WS_EX_CLIENTEDGE + EDITTEXT IDC_EDIT,120,0,295,234,ES_MULTILINE | ES_READONLY | + WS_VSCROLL | WS_HSCROLL + CONTROL "Devices Connected: 0",IDC_STATUS,"msctls_statusbar32", + SBARS_SIZEGRIP, + 0,235,415,8 +END + + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 230, 117 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About USBView" +FONT 8, "MS Shell Dlg" +BEGIN + DEFPUSHBUTTON "OK",IDOK,90,100,50,14 + LTEXT "USB Device Viewer",IDC_STATIC,54,15,104,8 + LTEXT VER_LEGALCOPYRIGHT_STR,IDC_STATIC,54,45,145,8 + EDITTEXT IDC_VERSION,54,60,110,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + EDITTEXT IDC_UVCVERSION,54,75,110,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER + ICON IDI_ICON,IDC_STATIC,15,15,21,20 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Refresh\tF5", ID_REFRESH + MENUITEM SEPARATOR + MENUITEM "Save Current &View ..." ID_SAVE + MENUITEM "Save As (&txt) ...", ID_SAVEALL + MENUITEM "Save As (&xml) ...\tF2", ID_SAVEXML + MENUITEM SEPARATOR + + MENUITEM "E&xit", ID_EXIT + END + POPUP "&Options" + BEGIN + MENUITEM "&Auto Refresh", ID_AUTO_REFRESH, CHECKED + MENUITEM "Show &Config Descriptors", ID_CONFIG_DESCRIPTORS, CHECKED + MENUITEM SEPARATOR +// MENUITEM "&Show Description Annotations", ID_ANNOTATION, CHECKED + MENUITEM "&Log to debugger", ID_LOG_DEBUG + END + POPUP "&Help" + BEGIN + MENUITEM "&About", ID_ABOUT + END +END + +////////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDACCEL ACCELERATORS DISCARDABLE +BEGIN + VK_F5, ID_REFRESH, VIRTKEY,NOINVERT + VK_F2, ID_SAVEXML, VIRTKEY,NOINVERT +END + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_STRINGBASE "Base string" +END + +STRINGTABLE +BEGIN + IDS_STANDARD_FONT "Courier" + IDS_STANDARD_FONT_HEIGHT "\13" + IDS_STANDARD_FONT_WIDTH "\8" +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_USBVIEW_USAGE "usbview usage:\nusbview [/?]\n\t/? - this usage message.\ + \n\t/q quiet mode, does not display 'Press any key to continue ...\n\t\ + \nusbview [/q] [/f] /saveall:\ + \n\tsaveall - saves the USB tree view as a text file\ + \n\t/f - overwrite file if it already exists\n\nusbview [/q] [/f] /savexml:\ + \n\tsavexml - saves the USB tree view as a xml file\n\t/f - overwrite file if it already exists\n\n" + IDS_USBVIEW_PRESSKEY "Press any key to continue ...\n" + IDS_USBVIEW_INVALIDARG "Invalid argument: [%1]\n" + IDS_USBVIEW_FILE_EXISTS_TXT "File: [%1] already exists, try `usbview /f /saveall:[%1]` to force overwrite\n" + IDS_USBVIEW_FILE_EXISTS_XML "File: [%1] already exists, try `usbview /f /savexml:[%1]` to force overwrite\n" + IDS_USBVIEW_INTERNAL_ERROR "An internal error occured, please report this as a bug\n" + IDS_USBVIEW_SAVED_TO "Usbview information saved to file : [%1]\n" + IDS_USBVIEW_INVALID_FILENAME "The argument : [%1] is invalid or incomplete.\n" +END + diff --git a/tests/projects/windows/winsdk/usbview/vndrlist.h b/tests/projects/windows/winsdk/usbview/vndrlist.h new file mode 100644 index 000000000..ccf21267b --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/vndrlist.h @@ -0,0 +1,11036 @@ +/*++ + +Copyright (c) 1997-2008 Microsoft Corporation + +Module Name: + + VNDRLIST.H + +Abstract: + + This header file contains a list of all currently known USB Vendor IDs + and the vendor name associated with each Vendor ID. + +Source: + + http://www.usb.org + +Environment: + + Kernel & user mode + +Revision History: + + 04-25-97 : created + 03-28-03 : refreshed with latest list from usb.org + 05-04-05 : refreshed with latest list from usb.org + 05-02-07 : refreshed with latest list from usb.org + 03-19-08 : refreshed with latest list from usb.org + +--*/ + +#ifndef __VNDRLIST_H__ +#define __VNDRLIST_H__ + +// +// Vendor ID structure +// +typedef struct _VENDOR_ID { + USHORT usVendorID; + PCHAR szVendor; +} VENDOR_ID, *PVENDOR_ID; + +// +// This list built from information obtained from +// http://www.usb.org/developers/tools/ +// +// This information has not been independently verified and no claims +// are made here as to its accuracy. +// +// 10978 total +// +VENDOR_ID USBVendorIDs[] = +{ + { 0x0079, "Shenzhen Longshengwei Technology, Co., Ltd." }, + { 0x013A, "Aimgene Technology Co., Ltd" }, + { 0x03CC, "GN OTOMETRICS" }, + { 0x03E8, "EndPoints Inc." }, + { 0x03E9, "Thesys Microelectronics" }, + { 0x03EA, "Data Broadcasting Corp." }, + { 0x03EB, "Atmel Corporation" }, + { 0x03EC, "Iwatsu America Inc." }, + { 0x03ED, "Mitel Corporation" }, + { 0x03EE, "Mitsumi" }, + { 0x03F0, "HP Inc." }, + { 0x03F1, "Genoa Technology" }, + { 0x03F2, "Oak Technology, Inc" }, + { 0x03F3, "Adaptec, Inc." }, + { 0x03F4, "Diebold, Inc." }, + { 0x03F5, "Siemens Electromechanical" }, + { 0x03F7, "Tulip Computers International" }, + { 0x03F8, "Epson Imaging Technology Center" }, + { 0x03F9, "KeyTronic Corp." }, + { 0x03FB, "OPTi Inc." }, + { 0x03FC, "Elitegroup Computer Systems" }, + { 0x03FD, "Xilinx Inc." }, + { 0x03FE, "Farallon Comunications" }, + { 0x03FF, "Weitek Corporation" }, + { 0x0400, "National Semiconductor" }, + { 0x0401, "National Registry Inc." }, + { 0x0402, "ALi Corporation" }, + { 0x0403, "Future Technology Devices International Limited" }, + { 0x0404, "NCR Corporation" }, + { 0x0405, "inSilicon" }, + { 0x0406, "Fujitsu-ICL Computers" }, + { 0x0407, "Fujitsu Personal Systems, Inc." }, + { 0x0408, "Quanta Computer Inc." }, + { 0x0409, "NEC Corporation" }, + { 0x040A, "Eastman Kodak Company" }, + { 0x040B, "Weltrend Semiconductor" }, + { 0x040C, "VTech Computers Ltd" }, + { 0x040D, "VIA Technologies, Inc." }, + { 0x040E, "MCCI Corporation" }, + { 0x040F, "Echo Speech Corporation" }, + { 0x0410, "Isis Distributed Systems, Inc." }, + { 0x0411, "BUFFALO INC." }, + { 0x0412, "Award Software International" }, + { 0x0413, "Leadtek Research Inc." }, + { 0x0414, "Giga-Byte Technology Co., Ltd." }, + { 0x0416, "Nuvoton Technology Corp." }, + { 0x0417, "Symbios, Inc." }, + { 0x0418, "AST Research" }, + { 0x0419, "Samsung Info. Systems America Inc." }, + { 0x041A, "Phoenix Technologies Ltd." }, + { 0x041B, "d'TV" }, + { 0x041D, "S3 Incorporated" }, + { 0x041E, "Creative Labs" }, + { 0x041F, "LCS Telegraphics" }, + { 0x0420, "Chips and Technologies" }, + { 0x0421, "Nokia Corporation" }, + { 0x0422, "ADI Systems Inc." }, + { 0x0423, "CATC" }, + { 0x0424, "Microchip-SMSC" }, + { 0x0425, "Freescale Semiconductor Hong Kong Limited" }, + { 0x0426, "Integrated Device Technology" }, + { 0x0427, "Motorola Electronics Taiwan Ltd." }, + { 0x0428, "Advanced Gravis Computer Ltd." }, + { 0x0429, "Cirrus Logic Inc." }, + { 0x042A, "Ericsson Austrian, AG" }, + { 0x042C, "Innovative Semiconductors, Inc." }, + { 0x042D, "Micronics" }, + { 0x042E, "Acer, Inc.(2)" }, + { 0x042F, "Molex Inc." }, + { 0x0430, "Fujitsu Component Limited" }, + { 0x0431, "ITAC Systems, Inc." }, + { 0x0432, "Unisys Corp." }, + { 0x0433, "Alps Electric Inc." }, + { 0x0434, "Samsung Info. Systems America Inc.(2)" }, + { 0x0435, "Hyundai Electronics America" }, + { 0x0436, "Taugagreining HF" }, + { 0x0437, "Framatome Connectors USA" }, + { 0x0438, "Advanced Micro Devices" }, + { 0x0439, "Voice Technologies Group" }, + { 0x043C, "Lucid Designs" }, + { 0x043D, "Lexmark International Inc." }, + { 0x043E, "LG Electronics USA Inc." }, + { 0x043F, "RadiSys Corporation" }, + { 0x0440, "EIZO NANAO CORPORATION" }, + { 0x0441, "Winbond Systems Lab." }, + { 0x0442, "Cygnion Corp." }, + { 0x0443, "Gateway 2000" }, + { 0x0445, "Agere Systems" }, + { 0x0446, "NMB Technologies Corporation" }, + { 0x0447, "Momentum Microsystems" }, + { 0x0449, "Eldim" }, + { 0x044A, "Shamrock Technology Co., Ltd." }, + { 0x044B, "WSI" }, + { 0x044C, "CCL/ITRI" }, + { 0x044D, "Siemens Nixdorf AG" }, + { 0x044E, "Alps Electric Co., Ltd." }, + { 0x044F, "ThrustMaster, Inc." }, + { 0x0450, "DFI Inc." }, + { 0x0451, "Texas Instruments" }, + { 0x0452, "Mitsubishi Electric & Electronics US, Inc." }, + { 0x0453, "CMD Technology" }, + { 0x0454, "Vobis Microcomputer AGO" }, + { 0x0455, "Telematics International, Inc." }, + { 0x0456, "Analog Devices, Inc." }, + { 0x0457, "Silicon Integrated Systems Corp." }, + { 0x0458, "KYE Systems Corp." }, + { 0x0459, "Adobe Systems, Inc." }, + { 0x045A, "SONICblue Incorporated" }, + { 0x045B, "Renesas Electronics Corp." }, + { 0x045D, "Nortel Networks" }, + { 0x045E, "Microsoft Corporation" }, + { 0x0460, "Ace Cad Enterprise Co., Ltd." }, + { 0x0461, "Primax Electronics" }, + { 0x0463, "EATON" }, + { 0x0464, "AMP/Tycoelectronics" }, + { 0x0465, "Pacific Micro Computing" }, + { 0x0467, "AT&T Paradyne" }, + { 0x0468, "Wieson Technologies Co., Ltd." }, + { 0x046A, "CHERRY" }, + { 0x046B, "American Megatrends" }, + { 0x046C, "Toshiba Corporation, Digital Media Network Company" }, + { 0x046D, "Logitech Inc." }, + { 0x046E, "Behavior Tech Computer Corporation" }, + { 0x046F, "Crystal Semiconductor" }, + { 0x0471, "Philips Consumer Lifestyle BV" }, + { 0x0472, "Oracle" }, + { 0x0473, "Sanyo Information Business Co., Ltd." }, + { 0x0474, "Sanyo Electric Co. Ltd." }, + { 0x0475, "TECO Electric & Machinery Co., Ltd." }, + { 0x0476, "AESP" }, + { 0x0477, "Seagate Technology" }, + { 0x0478, "Connectix Corp." }, + { 0x0479, "Advanced Peripheral Laboratories" }, + { 0x047A, "Semtech Corporation" }, + { 0x047B, "Silitek Corp." }, + { 0x047D, "Kensington" }, + { 0x047E, "Avago Technologies Inc." }, + { 0x047F, "Plantronics, Inc." }, + { 0x0480, "Toshiba America Info. Systems, Inc." }, + { 0x0481, "Zenith Data Systems" }, + { 0x0482, "Kyocera Corporation" }, + { 0x0483, "STMicroelectronics" }, + { 0x0484, "Specialix" }, + { 0x0485, "Nokia Monitors" }, + { 0x0486, "ASUS Computers Inc." }, + { 0x0487, "Stewart Connector" }, + { 0x0488, "Cirque Corporation" }, + { 0x0489, "Foxconn - Hon Hai" }, + { 0x048A, "S-MOS Systems, Inc." }, + { 0x048C, "Alps Electric Ireland Ltd." }, + { 0x048D, "ITE Tech Inc." }, + { 0x048F, "Eicon Tech." }, + { 0x0490, "United Microelectronic Corporation (UMC)" }, + { 0x0491, "Capetronic Kaohsiung Corp." }, + { 0x0492, "Samsung Semiconductor, Inc." }, + { 0x0493, "MAG Technology Co., Ltd." }, + { 0x0495, "ESS Technology, Inc." }, + { 0x0496, "Micron Electronics" }, + { 0x0497, "Smile International, Inc." }, + { 0x0498, "Capetronic (Kaohsiung) Corp." }, + { 0x0499, "Yamaha Corporation" }, + { 0x049A, "Gandalf Technologies Ltd." }, + { 0x049B, "Curtis Computer Products" }, + { 0x049C, "Acer Advanced Labs, Inc." }, + { 0x049D, "VLSI Technology, Inc." }, + { 0x049F, "Compaq Computer Corporation" }, + { 0x04A0, "Digital Equipment Corp." }, + { 0x04A1, "SystemSoft Corporation" }, + { 0x04A2, "FirePower Systems" }, + { 0x04A3, "Trident Microsystems Inc." }, + { 0x04A4, "Hitachi, Ltd." }, + { 0x04A5, "BenQ Corporation" }, + { 0x04A6, "Nokia Display Products" }, + { 0x04A7, "Visioneer" }, + { 0x04A8, "Multivideo Labs, Inc." }, + { 0x04A9, "Canon Inc." }, + { 0x04AA, "Daewoo Teletech Co., Ltd." }, + { 0x04AB, "Chromatic Research" }, + { 0x04AC, "Micro Audiometrics Corp." }, + { 0x04AD, "Dooin Electronics" }, + { 0x04AE, "Brooktree Corporation" }, + { 0x04AF, "Winnov L.P." }, + { 0x04B0, "Nikon Corporation" }, + { 0x04B1, "Pan International" }, + { 0x04B3, "IBM Corporation" }, + { 0x04B4, "Cypress Semiconductor" }, + { 0x04B5, "ROHM Co., Ltd." }, + { 0x04B6, "Hint Corporation" }, + { 0x04B7, "Compal Electronics, Inc." }, + { 0x04B8, "Seiko Epson Corp." }, + { 0x04B9, "SafeNet, Inc." }, + { 0x04BA, "Toucan Systems Limited" }, + { 0x04BB, "I-O Data Device, Inc." }, + { 0x04BC, "Digital Systems Associates" }, + { 0x04BD, "Toshiba Electronics Taiwan Corp." }, + { 0x04BE, "Telia Research AB" }, + { 0x04BF, "TDK Corporation" }, + { 0x04C2, "Methode Electronics Far East Pte Ltd." }, + { 0x04C3, "Maxi Switch, Inc." }, + { 0x04C4, "Lockheed Martin Energy Research" }, + { 0x04C5, "Fujitsu Ltd." }, + { 0x04C6, "Toshiba America Electronic Components" }, + { 0x04C7, "Micro Macro Technologies" }, + { 0x04C8, "Konica Corporation" }, + { 0x04CA, "Lite-On Technology Corp." }, + { 0x04CB, "FUJIFILM Corporation" }, + { 0x04CC, "ST-Ericsson" }, + { 0x04CD, "Tatung Company of America, Inc." }, + { 0x04CE, "ScanLogic Corporation" }, + { 0x04CF, "Myson Century, Inc." }, + { 0x04D0, "Digi International" }, + { 0x04D1, "ITT Cannon" }, + { 0x04D2, "Altec Lansing Technologies, Inc." }, + { 0x04D3, "VidUS, Inc." }, + { 0x04D4, "LSI Logic Inc." }, + { 0x04D5, "Forte Technologies, Inc." }, + { 0x04D6, "Mentor Graphics" }, + { 0x04D7, "Oki Semiconductor" }, + { 0x04D8, "Microchip Technology Inc." }, + { 0x04D9, "Holtek Semiconductor, Inc." }, + { 0x04DA, "Panasonic Corporation" }, + { 0x04DB, "Hypertec Ltd." }, + { 0x04DC, "Huan Hsin Holdings Ltd." }, + { 0x04DD, "Sharp Corporation" }, + { 0x04DE, "MindShare, Inc." }, + { 0x04DF, "ePadLink" }, + { 0x04E1, "Iiyama Corporation" }, + { 0x04E2, "Exar Corporation" }, + { 0x04E3, "Zilog" }, + { 0x04E4, "ACC Microelectronics" }, + { 0x04E5, "Promise Technology" }, + { 0x04E6, "Identiv, Inc." }, + { 0x04E7, "Elo TouchSystems" }, + { 0x04E8, "Samsung Electronics Co., Ltd." }, + { 0x04E9, "PC-Tel, Inc." }, + { 0x04EA, "Sipex Corporation" }, + { 0x04EB, "Northstar Systems Corp." }, + { 0x04EC, "Tokyo Electron Device Limited" }, + { 0x04ED, "Annabooks" }, + { 0x04EF, "Pacific Electronic International, Inc." }, + { 0x04F0, "Daewoo Electronics Co., Ltd." }, + { 0x04F1, "Victor Company of Japan, Limited" }, + { 0x04F2, "Chicony Electronics Co., Ltd." }, + { 0x04F3, "ELAN Microelectronics Corportation" }, + { 0x04F4, "Harting Elektronik Inc." }, + { 0x04F5, "Fujitsu-ICL Systems, Inc." }, + { 0x04F6, "Norand Corporation" }, + { 0x04F7, "Newnex Technology Corp." }, + { 0x04F8, "FuturePlus Systems" }, + { 0x04F9, "Brother Industries, Ltd." }, + { 0x04FA, "Dallas Semiconductor" }, + { 0x04FB, "Biostar Microtech Int'l Corp." }, + { 0x04FC, "SUNPLUS TECHNOLOGY CO., LTD." }, + { 0x04FD, "Soliton Systems K.K." }, + { 0x04FE, "PFU Limited" }, + { 0x04FF, "E-CMOS Corp." }, + { 0x0500, "Siam United Hi-Tech" }, + { 0x0501, "Fujikura/DDK" }, + { 0x0502, "Acer, Inc." }, + { 0x0503, "Hitachi America Ltd." }, + { 0x0504, "Hayes Microcomputer Products" }, + { 0x0505, "Digital Home Corporation" }, + { 0x0506, "3Com Corporation" }, + { 0x0507, "Hosiden Corporation" }, + { 0x0508, "Clarion Co., Ltd." }, + { 0x0509, "Aztech Systems Ltd" }, + { 0x050A, "Cinch Connectors" }, + { 0x050B, "Cable System International" }, + { 0x050C, "InnoMedia, Inc." }, + { 0x050D, "Belkin International, Inc." }, + { 0x050E, "Neon Technology, Inc." }, + { 0x050F, "KC Technology Inc." }, + { 0x0510, "Sejin Electron Inc." }, + { 0x0511, "N*ABLE Technologies, Inc (Data Book)" }, + { 0x0512, "Hualon Microelectronics Corp." }, + { 0x0513, "digital-X, Inc." }, + { 0x0514, "FCI Electronics" }, + { 0x0515, "ACTC" }, + { 0x0516, "Longwell Electronics/Longwell Company" }, + { 0x0517, "Butterfly Communications" }, + { 0x0518, "EzKEY Corp." }, + { 0x0519, "Star Micronics Co., LTD" }, + { 0x051A, "WYSE Technology" }, + { 0x051C, "Shuttle Inc." }, + { 0x051D, "American Power Conversion" }, + { 0x051E, "Scientific Atlanta, Inc." }, + { 0x051F, "IO Systems Inc." }, + { 0x0520, "Taiwan Semiconductor Manufacturing Co." }, + { 0x0521, "Airborn Connectors" }, + { 0x0522, "ACON, Advanced-Connectek, Inc." }, + { 0x0523, "ATEN GMBH" }, + { 0x0524, "Sola Electronics" }, + { 0x0525, "PLX Technology, Inc." }, + { 0x0526, "Temic MHS S.A." }, + { 0x0527, "ALTRA" }, + { 0x0528, "ATI Technologies, Inc." }, + { 0x0529, "SafeNet Data Security (Israel) Ltd." }, + { 0x052A, "Crescent Heart Software" }, + { 0x052B, "Tekom Technologies, Inc" }, + { 0x052C, "Canon Development Americas" }, + { 0x052D, "Avid Electronics Corp." }, + { 0x052E, "Standard Microsystems Corp. (1)" }, + { 0x052F, "Unicore Software, Inc." }, + { 0x0530, "American Microsystems Inc." }, + { 0x0531, "Wacom Technology Corp." }, + { 0x0532, "Systech Corporation" }, + { 0x0533, "Alcatel Mobile Phones" }, + { 0x0534, "Motorola" }, + { 0x0535, "LIH TZU Electric Co., Ltd." }, + { 0x0536, "Hand Held Products (Honeywell International Inc.)" }, + { 0x0537, "Inventec Corporation" }, + { 0x0538, "The SCO Group" }, + { 0x0539, "Shyh Shiun Terminals Co. LTD" }, + { 0x053A, "Preh KeyTec GmbH" }, + { 0x053B, "Global Village Communication" }, + { 0x053C, "Institut of Microelectronic & Mechatronic Systems" }, + { 0x053D, "Silicon Architect" }, + { 0x053E, "Mobility Electronics" }, + { 0x053F, "Synopsys, Inc." }, + { 0x0540, "UniAccess AB" }, + { 0x0541, "Sirf Technology, Inc" }, + { 0x0542, "MICOM Communications Corp." }, + { 0x0543, "ViewSonic Corporation" }, + { 0x0544, "Cristie Electronics Ltd." }, + { 0x0545, "Veo" }, + { 0x0546, "Polaroid Corporation" }, + { 0x0547, "Anchor Chips Inc." }, + { 0x0548, "Tyan Computer Corp." }, + { 0x0549, "Pixera Corporation" }, + { 0x054A, "Fujitsu Microelectronics, Inc." }, + { 0x054B, "New Media Corporation" }, + { 0x054C, "Sony Corporation" }, + { 0x054D, "Try Corporation" }, + { 0x054E, "Proside Corporation" }, + { 0x054F, "WYSE Technology Taiwan" }, + { 0x0550, "Fuji Xerox Co., Ltd." }, + { 0x0551, "CompuTrend Systems, Inc." }, + { 0x0552, "Philips Monitors" }, + { 0x0553, "STMicroelectronics Imaging Division" }, + { 0x0554, "Dictaphone Corp." }, + { 0x0555, "ANAM S&T Co., Ltd." }, + { 0x0556, "Asahi Kasei Microdevices Corporation" }, + { 0x0557, "ATEN International Co. Ltd." }, + { 0x0558, "Truevision, Inc." }, + { 0x0559, "Cadence Design Systems, Inc." }, + { 0x055A, "Kenwood USA" }, + { 0x055B, "KnowledgeTek, Inc." }, + { 0x055C, "Proton Electronic Ind." }, + { 0x055D, "Samsung Electro-Mechanics Co." }, + { 0x055E, "Optoma Corporation" }, + { 0x055F, "Mustek Systems Inc." }, + { 0x0560, "Interface Corporation" }, + { 0x0561, "Oasis Design, Inc." }, + { 0x0562, "Telex Communications Inc." }, + { 0x0563, "Immersion Corporation" }, + { 0x0564, "Kodak Digital Product Center, Japan Ltd." }, + { 0x0565, "Peracom Networks, Inc." }, + { 0x0566, "Monterey International Corp." }, + { 0x0567, "Xyratex" }, + { 0x0568, "Quartz Ingenierie" }, + { 0x0569, "SegaSoft" }, + { 0x056A, "WACOM Co., Ltd." }, + { 0x056B, "Decicon Incorporated" }, + { 0x056C, "Belkin Research & Development" }, + { 0x056D, "EIZO Corporation" }, + { 0x056E, "Elecom Co., Ltd." }, + { 0x056F, "Korea Data Systems Co., Ltd." }, + { 0x0570, "Epson America" }, + { 0x0571, "XLR8, Inc." }, + { 0x0572, "Conexant Systems, Inc." }, + { 0x0573, "Zoran Corporation" }, + { 0x0574, "City University of Hong Kong" }, + { 0x0575, "Philips Creative Display Solutions" }, + { 0x0576, "BAFO/Quality Computer Accessories" }, + { 0x0577, "ELSA" }, + { 0x0578, "Intrinsix Corp." }, + { 0x0579, "GVC Corporation" }, + { 0x057A, "Samsung Electronics America" }, + { 0x057B, "Y-E Data, Inc." }, + { 0x057C, "AVM GmbH" }, + { 0x057D, "Shark Multimedia Inc." }, + { 0x057E, "Nintendo Co., Ltd." }, + { 0x057F, "QuickShot Limited" }, + { 0x0580, "Denron Inc." }, + { 0x0581, "Racal Data Group" }, + { 0x0582, "Roland Corporation" }, + { 0x0583, "Padix Co., Ltd." }, + { 0x0584, "RATOC Systems, Inc." }, + { 0x0585, "FlashPoint Technology, Inc." }, + { 0x0586, "ZyXEL Communications Corp" }, + { 0x0587, "Matsushita Kotobuki Electronics Industries America" }, + { 0x0588, "Sapien Design" }, + { 0x0589, "Victron" }, + { 0x058A, "Nohau Corporation" }, + { 0x058B, "Infineon Technologies" }, + { 0x058C, "In Focus Systems" }, + { 0x058D, "Micrel Semiconductor" }, + { 0x058E, "Tripath Technology Inc." }, + { 0x058F, "Alcor Micro, Corp." }, + { 0x0590, "OMRON Corporation" }, + { 0x0591, "Questra Consulting" }, + { 0x0592, "Powerware Corporation" }, + { 0x0593, "Incite" }, + { 0x0594, "Princeton Graphic Systems" }, + { 0x0595, "Zoran Microelectronics Ltd." }, + { 0x0596, "3M Touch Systems" }, + { 0x0597, "Trisignal Communications" }, + { 0x0598, "Niigata Canotec Co., Inc." }, + { 0x0599, "Brilliance Semiconductor Inc." }, + { 0x059A, "Spectrum Signal Processing Inc." }, + { 0x059B, "Iomega Corporation" }, + { 0x059C, "A-Trend Technology Co., Ltd." }, + { 0x059D, "Advanced Input Devices" }, + { 0x059E, "Intelligent Instrumentation" }, + { 0x059F, "LaCie" }, + { 0x05A0, "Vetronix Corporation" }, + { 0x05A1, "UKC Electronics Corporation" }, + { 0x05A2, "Fuji Film Microdevices Co. Ltd." }, + { 0x05A3, "TransDimension-NH LLC" }, + { 0x05A4, "Ortek Technology, Inc." }, + { 0x05A5, "Sampo Technology Corp." }, + { 0x05A6, "Cisco Systems, Inc." }, + { 0x05A7, "Bose Corporation" }, + { 0x05A8, "Spacetec IMC Corporation" }, + { 0x05A9, "OmniVision Technologies, Inc." }, + { 0x05AA, "Utilux South China Ltd." }, + { 0x05AB, "In-System Design" }, + { 0x05AC, "Apple" }, + { 0x05AD, "Y.C. Cable U.S.A., Inc" }, + { 0x05AE, "Synopsys, Inc.(2)" }, + { 0x05AF, "Sunrex Technology Corp." }, + { 0x05B0, "Fountain Technologies, Inc" }, + { 0x05B1, "First International Computer, Inc." }, + { 0x05B2, "Focus Electronics" }, + { 0x05B4, "HYUNDAI Electronics Industries Co., Ltd." }, + { 0x05B5, "Dialogic Corp" }, + { 0x05B6, "Proxima Corporation" }, + { 0x05B7, "Medianix Semiconductor, Inc." }, + { 0x05B8, "Sysgration" }, + { 0x05B9, "Philips Research Laboratories" }, + { 0x05BA, "DigitalPersona, Inc." }, + { 0x05BB, "Grey Cell Systems" }, + { 0x05BD, "RAFI GmbH & Co. KG" }, + { 0x05BE, "Tyco Electronics Corp., a TE Connectivity Ltd. company" }, + { 0x05BF, "S & S Research" }, + { 0x05C0, "Keil Software" }, + { 0x05C1, "MegaChips Corporation" }, + { 0x05C2, "Media Phonics (Suisse) S.A." }, + { 0x05C3, "VME Microsystems" }, + { 0x05C5, "Digi International Inc." }, + { 0x05C6, "Qualcomm, Inc" }, + { 0x05C7, "Qtronix Corp" }, + { 0x05C8, "Foxlink/Cheng Uei Precision Industry Co., Ltd" }, + { 0x05C9, "Semtech" }, + { 0x05CA, "Ricoh Company Ltd." }, + { 0x05CB, "PowerVision Technologies Inc." }, + { 0x05CC, "Neue ELSA GmbH" }, + { 0x05CD, "Silicom LTD." }, + { 0x05CE, "sci-worx GmbH" }, + { 0x05CF, "Sung Forn Co. LTD." }, + { 0x05D0, "GE Medical Systems Lunar" }, + { 0x05D1, "Brainboxes Limited" }, + { 0x05D2, "Wave Systems Corp." }, + { 0x05D3, "Tohoku Ricoh Co., Ltd." }, + { 0x05D5, "Super Gate Technology Co., LTD" }, + { 0x05D6, "Philips Semiconductors, CICT" }, + { 0x05D7, "Thomas & Betts" }, + { 0x05D8, "Ultima Electronics Corp." }, + { 0x05D9, "TPG IPB, Inc." }, + { 0x05DA, "Microtek International Inc." }, + { 0x05DB, "Sun Corporation" }, + { 0x05DC, "Lexar Media, Inc." }, + { 0x05DD, "Delta Electronics Inc." }, + { 0x05DE, "Crucial Technology" }, + { 0x05DF, "Silicon Vision Inc." }, + { 0x05E0, "Symbol Technologies" }, + { 0x05E1, "Syntek Semiconductor Co., Ltd." }, + { 0x05E2, "ElecVision Inc." }, + { 0x05E3, "Genesys Logic, Inc." }, + { 0x05E4, "Red Wing Corporation" }, + { 0x05E5, "Fuji Electric Co., Ltd." }, + { 0x05E6, "Keithley Instruments" }, + { 0x05E7, "EIZO Nanao Technologies Inc." }, + { 0x05E8, "ICC, Inc." }, + { 0x05E9, "Kawasaki Microelectronics America, Inc." }, + { 0x05EA, "Evergreen Systems International" }, + { 0x05EB, "FFC Limited" }, + { 0x05EC, "COM21, Inc." }, + { 0x05EE, "Cytechinfo Inc." }, + { 0x05EF, "Anko Electronic Co., Ltd." }, + { 0x05F0, "Canopus Co., Ltd." }, + { 0x05F2, "Dexin Corporation, Ltd." }, + { 0x05F3, "PI Engineering, Inc." }, + { 0x05F4, "Davis AS" }, + { 0x05F5, "Unixtar Technology Inc." }, + { 0x05F6, "Envision Peripherals, Inc." }, + { 0x05F7, "Silicon Portals Inc." }, + { 0x05F8, "Phase Metrics" }, + { 0x05F9, "Datalogic ADC" }, + { 0x05FA, "Siemens Telecommunications Systems Limited" }, + { 0x05FC, "Harman Multimedia" }, + { 0x05FD, "STD Manufacturing Ltd." }, + { 0x05FE, "CHIC TECHNOLOGY CORP" }, + { 0x05FF, "LeCroy Corporation" }, + { 0x0600, "Barco" }, + { 0x0601, "Jazz Hipster Corporation" }, + { 0x0602, "Vista Imaging Inc." }, + { 0x0603, "Novatek Microelectronics Corp." }, + { 0x0604, "Jean Co, Ltd." }, + { 0x0605, "Anchor C&C Co., Ltd." }, + { 0x0606, "Royal Information Electronics Co., Ltd." }, + { 0x0607, "Bridge Information Co., Ltd." }, + { 0x0608, "Genrad Ads" }, + { 0x0609, "SMK Manufacturing Inc." }, + { 0x060A, "Worth Data, Inc." }, + { 0x060B, "Solid Year Co., LTD." }, + { 0x060C, "EEH Datalink Gmbh" }, + { 0x060D, "Auctor Corporation" }, + { 0x060E, "Transmonde Technologies, Inc." }, + { 0x060F, "Joinsoon Electronics Mfg. Co., Ltd." }, + { 0x0610, "Costar Electronics Inc." }, + { 0x0611, "JVCKENWOOD Nagaoka Corp." }, + { 0x0612, "TV Interactive Corp." }, + { 0x0613, "TransAct Technologies Incorporated" }, + { 0x0614, "Bio-Rad Laboratories" }, + { 0x0615, "Quabbin Wire & Cable Co., INC." }, + { 0x0616, "Future Techno Designs PVT. LTD." }, + { 0x0617, "Swiss Federal Institute of Technology" }, + { 0x0618, "Chia Shin Technology Corp." }, + { 0x0619, "Seiko Instruments Inc." }, + { 0x061A, "Veridicom2" }, + { 0x061B, "Promptus Communications, Inc." }, + { 0x061C, "Act Labs, Ltd." }, + { 0x061D, "Quatech, Inc." }, + { 0x061E, "Nissei Electric Co." }, + { 0x0620, "Alaris, Inc." }, + { 0x0621, "ODU-Steckverbindungssysteme GmbH & Co. KG" }, + { 0x0622, "Iotech, Inc." }, + { 0x0623, "Littelfuse, Inc." }, + { 0x0624, "Avocent Corporation" }, + { 0x0625, "TiMedia Technology Co., Ltd." }, + { 0x0626, "Nippon Systems Development Co., Ltd." }, + { 0x0627, "Adomax Technology Co., Ltd." }, + { 0x0628, "Tasking Software Inc." }, + { 0x0629, "Zida Technologies Limited" }, + { 0x062A, "MosArt Semiconductor Corp." }, + { 0x062B, "Greatlink Electronics Taiwan Ltd." }, + { 0x062C, "Institute for Information Industry" }, + { 0x062D, "Taiwan Tai-Hao Enterprises Co. Ltd." }, + { 0x062E, "JPC-MAIN SUPER Inc." }, + { 0x062F, "Sin Sheng Terminal & Machine Inc." }, + { 0x0630, "ORL" }, + { 0x0631, "JUJO Electronics Corporation" }, + { 0x0632, "Marquette Medical Systems, Inc." }, + { 0x0633, "Cyrix Corporation" }, + { 0x0634, "Micron Technology, Inc." }, + { 0x0635, "Methode Electronics, Inc." }, + { 0x0636, "Sierra Imaging, Inc." }, + { 0x0637, "Gunz Limited" }, + { 0x0638, "Avision, Inc." }, + { 0x0639, "Chrontel, Inc." }, + { 0x063A, "Techwin Corporation" }, + { 0x063B, "Taugagreining HF (2)" }, + { 0x063C, "Yamaichi Electronics Co., Ltd. (Sakura)" }, + { 0x063D, "Fong Kai Industrial Co., Ltd." }, + { 0x063E, "RealMedia Technology, Inc." }, + { 0x063F, "New Technology Cable Ltd." }, + { 0x0640, "Hitex Development Tools" }, + { 0x0641, "Woods Industries, Inc." }, + { 0x0642, "VIA Medical Corporation" }, + { 0x0643, "NOVATUS, Inc." }, + { 0x0644, "TEAC Corporation" }, + { 0x0645, "Ethentica Inc." }, + { 0x0647, "Acton Research Corporation" }, + { 0x0649, "Weli Science Co., Ltd" }, + { 0x064A, "Technical Corp." }, + { 0x064B, "Analog Devices, Inc. Development Tools" }, + { 0x064C, "Ji-Haw Industrial Co., Ltd" }, + { 0x064D, "TriTech Microelectronics Ltd" }, + { 0x064E, "Suyin Corporation" }, + { 0x064F, "WIBU-Systems AG" }, + { 0x0650, "Dynapro Systems" }, + { 0x0651, "Likom Technology Sdn. Bhd." }, + { 0x0652, "Stargate Solutions, Inc." }, + { 0x0653, "CNF Inc." }, + { 0x0654, "Granite Microsystems, Inc." }, + { 0x0655, "Space Shuttle Hi-Tech Co.,Ltd." }, + { 0x0656, "Glory Mark Electronic Ltd." }, + { 0x0657, "Tekcon Electronics Corp." }, + { 0x0658, "Sigma Designs, Inc." }, + { 0x0659, "AETHRA" }, + { 0x065A, "Optoelectronics Co., Ltd." }, + { 0x065B, "Tracewell Systems" }, + { 0x065C, "Brentwood Medical Technology Corp." }, + { 0x065D, "ATTO Technology, Inc." }, + { 0x065E, "Silicon Graphics" }, + { 0x065F, "Good Way Technology Co., Ltd. & GWC technology Inc" }, + { 0x0660, "TSAY-E (BVI) International Inc." }, + { 0x0661, "Hamamatsu Photonics K.K." }, + { 0x0662, "Kansai Electric Co., Ltd." }, + { 0x0663, "Topmax Electronic Co., Ltd." }, + { 0x0664, "ET&T" }, + { 0x0665, "WayTech Development, Inc." }, + { 0x0667, "Antona Corporation" }, + { 0x0668, "WordWand" }, + { 0x0669, "Oce' Printing Systems GmbH" }, + { 0x066A, "Total Technologies, Ltd." }, + { 0x066B, "SCM Microsystems Japan, Inc." }, + { 0x066C, "ASK ASA" }, + { 0x066D, "Entrega Technologies Inc." }, + { 0x066E, "Acer Semiconductor America, Inc." }, + { 0x066F, "Freescale Semiconductor, Inc. - Sigmatel" }, + { 0x0670, "Sequel Imaging, Inc." }, + { 0x0671, "Keisoku Giken Co., Ltd." }, + { 0x0672, "Labtec Inc." }, + { 0x0673, "HCL Peripherals Limited" }, + { 0x0674, "Key Mouse Electronic Enterprise Co., Ltd." }, + { 0x0675, "DrayTek Corp." }, + { 0x0676, "Teles AG" }, + { 0x0677, "Aiwa Co., Ltd." }, + { 0x0678, "ACARD Technology Corp." }, + { 0x0679, "WaterGate Software, Inc." }, + { 0x067A, "ADS ANKER GmbH" }, + { 0x067B, "Prolific Technology, Inc." }, + { 0x067C, "Efficient Networks, Inc." }, + { 0x067D, "Hohner Corp." }, + { 0x067E, "Intermec Technologies (S) Pte Ltd." }, + { 0x067F, "Virata Ltd." }, + { 0x0680, "Realtek Semiconductor Corp., CPP Div." }, + { 0x0681, "Siemens Information and Communication Products" }, + { 0x0683, "Dataq Instruments, Inc." }, + { 0x0684, "Cytec Corporation" }, + { 0x0685, "ISDN*tek" }, + { 0x0686, "KONICA MINOLTA TECHNOLOGY CENTER, INC." }, + { 0x0687, "Sycard Technology" }, + { 0x0688, "Microprocess Ingenierie" }, + { 0x0689, "Elesys Inc." }, + { 0x068A, "Pertech Inc." }, + { 0x068B, "Potrans International, Inc." }, + { 0x068C, "Tokin Corporation, Card Media Systems Department" }, + { 0x068D, "Medical Measurement Systems B.V." }, + { 0x068E, "CH Products" }, + { 0x068F, "Nihon Kohden Corporation" }, + { 0x0690, "Golden Bridge Electech Inc." }, + { 0x0691, "Denter System Co., Ltd." }, + { 0x0692, "Klippel GmbH" }, + { 0x0693, "Hagiwara Solutions Co., Ltd." }, + { 0x0694, "The LEGO Company" }, + { 0x0695, "ODU-USA, Inc." }, + { 0x0696, "Carroll Touch" }, + { 0x0697, "Oxford Instruments (Medical Systems Division)" }, + { 0x0698, "Chuntex (CTX)" }, + { 0x0699, "Tektronix, Inc." }, + { 0x069A, "Askey Computer Corporation" }, + { 0x069B, "Technicolor SA" }, + { 0x069C, "HST High Soft Tech GmbH" }, + { 0x069D, "Hughes Network Systems (HNS)" }, + { 0x069E, "Welcat Inc." }, + { 0x069F, "Tron b.v." }, + { 0x06A0, "USB Systems Design" }, + { 0x06A1, "Alexon Co., Ltd." }, + { 0x06A2, "Topro Technology Inc." }, + { 0x06A3, "Logitech Europe S.A." }, + { 0x06A4, "Xiamen Doowell Electron Co., Ltd." }, + { 0x06A5, "Divio" }, + { 0x06A7, "MicroStore, Inc." }, + { 0x06A8, "Topaz Systems, Inc." }, + { 0x06A9, "Westell" }, + { 0x06AA, "Sysgration Ltd." }, + { 0x06AB, "Johnathon Freeman Technologies" }, + { 0x06AC, "Fujitsu Laboratories of America, Inc." }, + { 0x06AD, "Greatland Electronics Taiwan Ltd." }, + { 0x06AE, "Eurofins Digital Testing Belgium" }, + { 0x06AF, "Harting, Inc. of North America" }, + { 0x06B0, "Alva B.V." }, + { 0x06B1, "Signtech USA, Ltd." }, + { 0x06B2, "N*ABLE Technologies, Inc." }, + { 0x06B3, "Galil Motion Control" }, + { 0x06B4, "Citron GmbH" }, + { 0x06B5, "Stanford Research Systems" }, + { 0x06B6, "Leda Media Products" }, + { 0x06B8, "Pixela Corporation" }, + { 0x06B9, "Thomson Telecom" }, + { 0x06BA, "Smooth Cord & Connector Co., Ltd." }, + { 0x06BB, "EDA Inc." }, + { 0x06BC, "Oki Data Corporation" }, + { 0x06BD, "AGFA-Gevaert NV" }, + { 0x06BE, "AME Optimedia Technology Co. Ltd." }, + { 0x06BF, "Leoco Corporation" }, + { 0x06C0, "AllSpirit Co., Ltd." }, + { 0x06C2, "Microlynx Systems Ltd." }, + { 0x06C3, "Foss Tecator AB" }, + { 0x06C4, "Bizlink Technology, Inc." }, + { 0x06C5, "Hagenuk, GmbH" }, + { 0x06C6, "Infowave Software Inc." }, + { 0x06C7, "Storm Technology Inc." }, + { 0x06C8, "SIIG, Inc." }, + { 0x06C9, "Taxan (Europe) Ltd." }, + { 0x06CA, "Newer Technology, Inc." }, + { 0x06CB, "Synaptics Inc." }, + { 0x06CC, "Terayon Communication Systems" }, + { 0x06CD, "Keyspan" }, + { 0x06CE, "Contec Co., Ltd." }, + { 0x06CF, "Spheron VR- Bonnet und Steuerwald GdbR" }, + { 0x06D0, "LapLink, Inc." }, + { 0x06D1, "Daewoo Electronics Co Ltd" }, + { 0x06D2, "Pioneer Microsystems" }, + { 0x06D3, "Mitsubishi Electric Corporation" }, + { 0x06D4, "Cisco Systems(2)" }, + { 0x06D5, "Toshiba America Electronic Components, Inc." }, + { 0x06D6, "Aashima Technology B.V." }, + { 0x06D7, "Network Computing Devices (NCD)" }, + { 0x06D8, "Technical Marketing Research, Inc." }, + { 0x06D9, "Atmel-TEMIC Semiconductor GmbH" }, + { 0x06DA, "Phoenixtec Power Co., Ltd." }, + { 0x06DB, "Paradyne" }, + { 0x06DC, "Foxlink Image Technology Co., Ltd." }, + { 0x06DD, "Impact Technologies" }, + { 0x06DE, "Heisei Technology Co., Ltd." }, + { 0x06E0, "Multi-Tech Systems, Inc." }, + { 0x06E1, "ADS Technologies, Inc." }, + { 0x06E2, "Trio Motion Technology Limited" }, + { 0x06E4, "Alcatel Microelectronics" }, + { 0x06E5, "Lusher Technologies" }, + { 0x06E6, "Tiger Jet Network, Inc." }, + { 0x06E7, "Universal Electronics Inc." }, + { 0x06E8, "Braemar Inc." }, + { 0x06E9, "Nippon Electric Industry Co., Ltd." }, + { 0x06EA, "Sirius Technologies Limited" }, + { 0x06EB, "PC Expert Tech. Co., Ltd." }, + { 0x06EC, "ADInstruments Ltd." }, + { 0x06ED, "Datastor Technology" }, + { 0x06EF, "I.A.C. Geometrische Ingenieurs B.V." }, + { 0x06F0, "T.N.C Industrial Co., Ltd." }, + { 0x06F1, "Opcode Systems Inc." }, + { 0x06F2, "Emine Technology Company" }, + { 0x06F3, "Flexion Systems Ltd." }, + { 0x06F4, "First Person Gaming" }, + { 0x06F5, "Midian Production Distribution" }, + { 0x06F6, "Wintrend Technology Co., Ltd." }, + { 0x06F7, "Wish Technologies" }, + { 0x06F8, "Guillemot Corporation" }, + { 0x06F9, "Asyst Electronic" }, + { 0x06FA, "HSD S.r.L" }, + { 0x06FB, "Hitachi Device Engineering Ltd." }, + { 0x06FC, "Motorola Semiconductor Products Sector/US" }, + { 0x06FD, "Boston Acoustics" }, + { 0x06FE, "Gallant Computer, Inc." }, + { 0x06FF, "Mediacom Technologies Pte Ltd." }, + { 0x0701, "Supercomal Wire & Cable SDN. BHD." }, + { 0x0702, "PixStream Incorporated" }, + { 0x0703, "Bvtech Industry Inc." }, + { 0x0704, "Vorum Research Corporation" }, + { 0x0705, "NKK Corporation" }, + { 0x0706, "Ariel Corporation" }, + { 0x0707, "SMC Networks, Inc." }, + { 0x0708, "Putercom Co., Ltd." }, + { 0x0709, "Parthus Technologies" }, + { 0x070A, "Oki Electric Industry Co., Ltd." }, + { 0x070B, "Hasco Int., Inc." }, + { 0x070C, "Titan Electronics Inc." }, + { 0x070D, "Comoss Electronic Co., Ltd." }, + { 0x070E, "Excel Cell Electronic Co., Ltd." }, + { 0x070F, "Oce' -Technologies B.V." }, + { 0x0710, "Connect Tech Inc." }, + { 0x0711, "Magic Control Technology Corp." }, + { 0x0712, "Verity Instruments, Inc." }, + { 0x0713, "Interval Research Corp." }, + { 0x0714, "New Motion International Co., Ltd" }, + { 0x0715, "Liang Tei Co., Ltd." }, + { 0x0716, "Oxus Research S.A." }, + { 0x0717, "ZNK Corporation" }, + { 0x0718, "Imation Corp." }, + { 0x0719, "Tremon Enterprises Co., Ltd." }, + { 0x071A, "FLIR Explosives" }, + { 0x071B, "Domain Technologies, Inc." }, + { 0x071C, "Xionics Document Technologies, Inc." }, + { 0x071D, "Dialogic Corporation" }, + { 0x071E, "Ariston Technologies" }, + { 0x071F, "ARS Technologies Ltd." }, + { 0x0720, "Keyence Corporation" }, + { 0x0721, "HMedia Technology Inc." }, + { 0x0722, "Consero" }, + { 0x0723, "Centillium Communications Corporation" }, + { 0x0724, "Lawson Labs, Inc." }, + { 0x0725, "Applied Precision Inc." }, + { 0x0726, "Vanguard International Semiconductor-America" }, + { 0x0727, "C&H Technologies, Inc." }, + { 0x0728, "Avermedia" }, + { 0x0729, "CY&S Industrial Co., Ltd." }, + { 0x072A, "Luminex Corporation" }, + { 0x072B, "Dnova Corporation" }, + { 0x072C, "OTSO" }, + { 0x072D, "Able Communications, Inc." }, + { 0x072E, "Sunix Co., Ltd." }, + { 0x072F, "Advanced Card Systems Ltd." }, + { 0x0730, "Indus Instruments" }, + { 0x0731, "Susteen, Inc." }, + { 0x0732, "Goldfull Electronics & Telecommunications Corp." }, + { 0x0733, "ViewQuest Technologies, Inc." }, + { 0x0734, "LASAT Communications A/S" }, + { 0x0735, "Asuscom Network, Inc." }, + { 0x0736, "Lorom Industrial Co., Ltd." }, + { 0x0737, "Snap-on Diagnostics" }, + { 0x0738, "Mad Catz, Inc." }, + { 0x0739, "Cue Network Corporation" }, + { 0x073A, "Chaplet Systems, Inc." }, + { 0x073B, "Suncom Technologies" }, + { 0x073C, "Industrial Electronic Engineers, Inc." }, + { 0x073D, "Eutronsec Spa" }, + { 0x073E, "Sigma Itec, Inc." }, + { 0x073F, "Data Electronics (Aust) Pty, Ltd." }, + { 0x0740, "Full Enterprise Corp." }, + { 0x0741, "Momentum US Inc." }, + { 0x0742, "Stollmann EtV GmbH" }, + { 0x0743, "Bonig und Kallenback oHG" }, + { 0x0744, "GMK Electronic Design GmbH" }, + { 0x0745, "Syntech Information Co., Ltd." }, + { 0x0746, "ONKYO Corporation" }, + { 0x0747, "Labway Corporation" }, + { 0x0748, "Strong Man Enterprise Co., Ltd." }, + { 0x0749, "EVer Electronics Corp." }, + { 0x074A, "Ming Fortune Industry Co., Ltd." }, + { 0x074B, "Polestar Tech. Corp." }, + { 0x074C, "C-C-C Group PLC" }, + { 0x074D, "Micronas GmbH" }, + { 0x074E, "Digital Stream Corporation" }, + { 0x074F, "Microflip, Inc" }, + { 0x0750, "Innovative Integration" }, + { 0x0751, "Info Network Systems" }, + { 0x0752, "Non-Standard, TSG" }, + { 0x0753, "Mocom Softeare GmbH & Co. KG" }, + { 0x0754, "SyQuest Technology" }, + { 0x0755, "Aureal Semiconductor" }, + { 0x0756, "RSI Systems" }, + { 0x0757, "Network Technologies, Inc." }, + { 0x0758, "Carl Zeiss Jena GmbH" }, + { 0x0759, "Cellvision Systems, Inc." }, + { 0x075A, "SEL Inc." }, + { 0x075B, "Sophisticated Circuits, Inc." }, + { 0x075C, "Ulan Co., Ltd." }, + { 0x075D, "Microdowell SRL" }, + { 0x075E, "ABIT Corporation" }, + { 0x075F, "CITEL Technologies, Ltd." }, + { 0x0760, "JL Cooper Electronics" }, + { 0x0761, "MasTech, Inc." }, + { 0x0762, "Coretex Corporation" }, + { 0x0763, "M-Audio" }, + { 0x0764, "Cyber Power Systems, Inc." }, + { 0x0765, "X-Rite Incorporated" }, + { 0x0766, "Jess-Link Products Co., Ltd. (JPC)" }, + { 0x0767, "Tokheim Corporation" }, + { 0x0768, "Camtel Technology Corp." }, + { 0x0769, "SURECOM Technology Corp." }, + { 0x076A, "Conceptual Systems" }, + { 0x076B, "HID Global GmbH" }, + { 0x076C, "Partner Tech" }, + { 0x076D, "Denso Corporation" }, + { 0x076E, "Kuan Tech Enterprise Co., Ltd." }, + { 0x076F, "Jhen Vei Electronic Co., Ltd." }, + { 0x0770, "Welch Allyn, Inc - Medical Division" }, + { 0x0771, "MicroCraft" }, + { 0x0772, "TFL LAN, Inc" }, + { 0x0773, "Spital Sangyo Co., Ltd." }, + { 0x0774, "AmTRAN Technology Co., Ltd." }, + { 0x0775, "Longshine Electronics Corp." }, + { 0x0776, "Inalways Corporation" }, + { 0x0777, "Comda Advanced Technology Corporation" }, + { 0x0778, "Volex, Inc." }, + { 0x0779, "Fairchild Semiconductor" }, + { 0x077A, "NIDEC SANKYO CORPORATION" }, + { 0x077B, "Linksys" }, + { 0x077C, "Forward Electronics Co., Ltd." }, + { 0x077D, "Griffin Technology LLC" }, + { 0x077E, "Softing GmbH" }, + { 0x077F, "Well Excellent & Most Corp." }, + { 0x0780, "ORGA Kartensysteme GmbH" }, + { 0x0781, "Western Digital, Sandisk" }, + { 0x0782, "Trackerball" }, + { 0x0783, "C3PO, S.L." }, + { 0x0784, "Pretec Corporation" }, + { 0x0785, "Willnet Inc." }, + { 0x0786, "Jeil Data Systems Co., Ltd." }, + { 0x0787, "Abera System Corp" }, + { 0x0788, "3Cam Technology, Inc" }, + { 0x0789, "Logitec Corporation" }, + { 0x078A, "Tandy Electronics (China) Ltd." }, + { 0x078B, "Happ Controls" }, + { 0x078C, "CalComp" }, + { 0x078D, "Presto Technologies Inc." }, + { 0x078E, "San Shih Electrical Enterprise Co. Ltd." }, + { 0x078F, "Troy XCD, Inc." }, + { 0x0790, "Pro-Image Manufacturing Co., Ltd" }, + { 0x0791, "Copartner Technology Corporation" }, + { 0x0792, "Axis Communications AB" }, + { 0x0793, "Wha Yu Industrial Co., Ltd." }, + { 0x0794, "ABL Electronics Corporation" }, + { 0x0795, "RealChip Inc." }, + { 0x0796, "Certicom Corp." }, + { 0x0797, "Grandtech Semiconductor Corporation" }, + { 0x0798, "F.J. Tieman BV" }, + { 0x0799, "Boulder Creek Engineering" }, + { 0x079A, "Aptec Instruments" }, + { 0x079B, "Sagem SA" }, + { 0x079C, "Sun Communications Inc." }, + { 0x079D, "Alfadata Computer Corp." }, + { 0x079E, "Tokin Corporation" }, + { 0x079F, "VMETRO asa" }, + { 0x07A0, "Leiderdorp Instruments" }, + { 0x07A1, "Digicom Spa" }, + { 0x07A2, "National Technical Systems" }, + { 0x07A3, "ONNTO Corp." }, + { 0x07A4, "Be Incorporated" }, + { 0x07A5, "Tietech Co., Ltd." }, + { 0x07A6, "Infineon-ADMtek Co., Ltd." }, + { 0x07A7, "Mediatronix BV" }, + { 0x07A8, "Home Office PSDB" }, + { 0x07A9, "Sandmartin Company Ltd." }, + { 0x07AA, "Corega Inc." }, + { 0x07AB, "Freecom Technologies" }, + { 0x07AC, "Fortress U&T Ltd." }, + { 0x07AD, "ECO Chemie" }, + { 0x07AE, "C&C Technic Taiwan Co., Ltd." }, + { 0x07AF, "Microtech International, Inc." }, + { 0x07B0, "Billion Electric Co., Ltd" }, + { 0x07B1, "IMP, Inc." }, + { 0x07B2, "Motorola BCS" }, + { 0x07B3, "Plustek, Inc." }, + { 0x07B4, "OLYMPUS CORPORATION" }, + { 0x07B5, "Mega World International Ltd." }, + { 0x07B6, "Marubun Corp." }, + { 0x07B7, "TIME Interconnect Ltd." }, + { 0x07B8, "AboCom Systems, Inc." }, + { 0x07B9, "Reynolds Medical" }, + { 0x07BA, "Accurate Technologies, Inc." }, + { 0x07BB, "Intelogis Inc" }, + { 0x07BC, "Canon Computer Systems, Inc." }, + { 0x07BD, "Webgear Inc." }, + { 0x07BE, "Veridicom" }, + { 0x07BF, "TestQuest, Inc." }, + { 0x07C0, "Code Mercenaries" }, + { 0x07C1, "Keisokugiken Corporation" }, + { 0x07C2, "Varatouch Technology Inc." }, + { 0x07C3, "J-Works, Inc." }, + { 0x07C4, "Datafab Systems Inc." }, + { 0x07C5, "APG Cash Drawer" }, + { 0x07C6, "ShareWave, Inc." }, + { 0x07C7, "Powertech Industrial Co., Ltd." }, + { 0x07C8, "B.U.G., Inc." }, + { 0x07C9, "Allied Telesis Inc" }, + { 0x07CA, "AVerMedia Technologies, Inc." }, + { 0x07CB, "Kingmax Technology Inc." }, + { 0x07CC, "LIWANLI Innovation Co., Ltd" }, + { 0x07CD, "Hteck Corp." }, + { 0x07CE, "Nidec-Shimpo Corp." }, + { 0x07CF, "Casio Computer Co., Ltd." }, + { 0x07D0, "Dazzle Multimedia" }, + { 0x07D2, "Aptio Products Inc." }, + { 0x07D3, "Cyberdata Corp." }, + { 0x07D4, "Aloka Co., Ltd." }, + { 0x07D5, "Radiant Systems, Inc." }, + { 0x07D6, "MENICX International Co., Ltd." }, + { 0x07D7, "GCC Technologies, Inc." }, + { 0x07D8, "Network Suginami Kokoto" }, + { 0x07D9, "Compuapps" }, + { 0x07DA, "Arasan Chip Systems Inc." }, + { 0x07DB, "Mental Models, Inc." }, + { 0x07DC, "OCTAL-Engenharia de Sistemas S.A." }, + { 0x07DD, "Hampshire Company, Inc." }, + { 0x07DE, "Best Data Products" }, + { 0x07DF, "David Electronics Company, Ltd." }, + { 0x07E0, "NCP Engineering" }, + { 0x07E1, "Acer Netxus Incorporated" }, + { 0x07E2, "Elmeg GmbH & Co., Ltd." }, + { 0x07E3, "Planex Communications, Inc." }, + { 0x07E4, "Movado Enterprise Co., Ltd." }, + { 0x07E5, "QPS, Inc." }, + { 0x07E6, "Allied Cable Corporation" }, + { 0x07E7, "Mirvo Toys, Inc." }, + { 0x07E8, "Labsystems" }, + { 0x07E9, "Sanyo Technosound Co., Ltd." }, + { 0x07EA, "Iwatsu Electric Co., Ltd." }, + { 0x07EB, "Double-H Technology Co., Ltd." }, + { 0x07EC, "Taiyo Electric Wire & Cable Co., Ltd." }, + { 0x07ED, "Precision MicroDynamics, Inc." }, + { 0x07EE, "Logware GmbH" }, + { 0x07EF, "Suite Technology Systems" }, + { 0x07F0, "PS Communications Ltd." }, + { 0x07F1, "Picostar, Inc." }, + { 0x07F2, "BPT Enterprises" }, + { 0x07F3, "L3 Systems" }, + { 0x07F4, "Joritel International B.V." }, + { 0x07F5, "Amiable Technologies, Inc." }, + { 0x07F6, "Circuit Assembly Corp." }, + { 0x07F7, "Century Corporation" }, + { 0x07F8, "Eskape Labs" }, + { 0x07F9, "Dotop Technology, Inc." }, + { 0x07FA, "FHLP" }, + { 0x07FB, "Digi-Tek, Inc." }, + { 0x07FC, "Protec Microsystems" }, + { 0x07FD, "Mark of the Unicorn, Inc." }, + { 0x07FE, "Net Eyes, Inc." }, + { 0x07FF, "Sectra AB" }, + { 0x0800, "Kortex International" }, + { 0x0801, "Mag-Tek" }, + { 0x0802, "Mako Technologies, LLC" }, + { 0x0803, "Zoom Telephonics, Inc." }, + { 0x0804, "Neuron Corporation" }, + { 0x0805, "Iruma Soft Co., Ltd." }, + { 0x0806, "Clinton Electronics Corp." }, + { 0x0807, "SIIX Corporation" }, + { 0x0808, "InfiMed, Inc." }, + { 0x0809, "Genicom LP" }, + { 0x080A, "Evermuch Technology Co., Ltd." }, + { 0x080B, "Cross Match Technologies, Inc." }, + { 0x080C, "Datalogic S.p.A." }, + { 0x080D, "TECO Image Systems Co., Ltd." }, + { 0x080E, "Sound Technology, Inc." }, + { 0x080F, "Deschutes Corporation" }, + { 0x0810, "Personal Communication Systems, Inc." }, + { 0x0811, "Fimet" }, + { 0x0812, "E-Tech, Inc." }, + { 0x0813, "Mattel, Inc." }, + { 0x0814, "EBI Systems, Inc." }, + { 0x0815, "Scintrex" }, + { 0x0816, "ABB Automation Products AB" }, + { 0x0817, "Interzeag Medical Technology" }, + { 0x0818, "NTT Electronics Corporation" }, + { 0x0819, "Syncrosoft GMBH" }, + { 0x081A, "MG Logic Pte Ltd." }, + { 0x081B, "Indigita Corporation" }, + { 0x081C, "MIPSYS" }, + { 0x081D, "VlerZwo Software GbR" }, + { 0x081E, "AlphaSmart, Inc." }, + { 0x081F, "Totsu Engineering, Inc." }, + { 0x0820, "Verax Engineering" }, + { 0x0821, "A.T. Cross" }, + { 0x0822, "REUDO Corporation" }, + { 0x0823, "Tactex Controls, Inc." }, + { 0x0824, "M.S.E. GmbH" }, + { 0x0825, "GC Protronics" }, + { 0x0826, "Data Transit" }, + { 0x0827, "BroadLogic, Inc." }, + { 0x0828, "Sato Corporation" }, + { 0x0829, "DirecTV Broadband" }, + { 0x082A, "Object Co., Ltd." }, + { 0x082B, "TrophyTrex" }, + { 0x082C, "Japan Digital Laboratory Co., Ltd." }, + { 0x082D, "Handspring, Inc." }, + { 0x082E, "Suni Imaging Microsystems, Inc." }, + { 0x082F, "ACACIA" }, + { 0x0830, "Palm Inc." }, + { 0x0831, "Chong Tsi Su Enterprise Co., Ltd" }, + { 0x0832, "Kouwell Electronics Corp." }, + { 0x0833, "Sourcenext Corporation" }, + { 0x0834, "Ciponic Technology Co., Ltd." }, + { 0x0835, "Action Star Technology Co., Ltd." }, + { 0x0836, "Evertz Microsystems Ltd." }, + { 0x0837, "Renishaw PLC" }, + { 0x0838, "Precision MicroControl Corporation" }, + { 0x0839, "Samsung Techwin" }, + { 0x083A, "Accton Technology Corporation" }, + { 0x083B, "Dr. Neuhaus Telekommunikation GmbH" }, + { 0x083C, "Jaeger Messtechnik GmbH" }, + { 0x083D, "Nakayo Telecommunication, Inc." }, + { 0x083E, "2-Tel B.V." }, + { 0x083F, "Boca Global, Inc." }, + { 0x0840, "Argosy Research Inc." }, + { 0x0841, "Rioport.com Inc." }, + { 0x0842, "ESA MESSTECHNIK GMBH" }, + { 0x0843, "Mcom As" }, + { 0x0844, "Welland Industrial Co., Ltd." }, + { 0x0845, "EES Technik fur Musik" }, + { 0x0846, "NETGEAR, Inc." }, + { 0x0847, "Interack Communications Inc." }, + { 0x0848, "Accton Technology Co., Ltd." }, + { 0x0849, "SC&T International, Inc." }, + { 0x084A, "Wipro Limited" }, + { 0x084B, "Castlewood Systems" }, + { 0x084C, "The Japan Steel Works, Ltd." }, + { 0x084D, "Minton Optic Industry Co., Ltd." }, + { 0x084E, "KidBoard, Inc. dba KBGear Interactive" }, + { 0x084F, "EMPEG Ltd" }, + { 0x0850, "FastPoint Technologies, Inc." }, + { 0x0851, "Macronix International Co., Ltd." }, + { 0x0852, "CSEM" }, + { 0x0853, "Topre Corporation" }, + { 0x0854, "Active Wire, Inc." }, + { 0x0855, "JMBS Developpements" }, + { 0x0856, "B&B Electronics" }, + { 0x0857, "Gerber Scientific Products, Inc." }, + { 0x0858, "Hitachi Maxell Ltd." }, + { 0x0859, "Minolta Systems Laboratory, Inc." }, + { 0x085A, "Xircom" }, + { 0x085B, "Kurt Manufacturing" }, + { 0x085C, "Color Vision Inc." }, + { 0x085D, "Ambient Technologies, Inc." }, + { 0x085E, "NaftEL Technologies LTD." }, + { 0x085F, "Canberra Industries" }, + { 0x0860, "Momentum Data System" }, + { 0x0861, "Cambridge Research Systems Ltd." }, + { 0x0862, "Teletrol Systems, Inc." }, + { 0x0863, "Filanet Corporation" }, + { 0x0864, "Roper International Ltd." }, + { 0x0865, "MICROLAB" }, + { 0x0866, "PEI Electronics, Inc." }, + { 0x0867, "Data Translation, Inc." }, + { 0x0868, "Electrical Geodesics, Inc." }, + { 0x0869, "Visual Interaction" }, + { 0x086A, "Emagic Soft-und Hardware Gmbh" }, + { 0x086B, "ROHM Co. Ltd." }, + { 0x086C, "DeTeWe" }, + { 0x086D, "ICE Technology" }, + { 0x086E, "System TALKS Inc." }, + { 0x086F, "MEC IMEX INC-HPT" }, + { 0x0870, "Metricom, Inc." }, + { 0x0871, "Merge Technologies Inc." }, + { 0x0872, "Broadxent, Inc." }, + { 0x0873, "Xpeed Inc." }, + { 0x0874, "A-Tec Subsystem, Inc." }, + { 0x0875, "Mecel AB" }, + { 0x0876, "3M Home Health Systems" }, + { 0x0877, "Lew Engineering" }, + { 0x0878, "SYSTEC Computer Gmbh" }, + { 0x0879, "Comtrol Corporation" }, + { 0x087A, "Getemed GmbH" }, + { 0x087B, "Cornerstone Peripherals Technology" }, + { 0x087C, "ADESSO/Kbtek America Inc." }, + { 0x087D, "JATON Corporation" }, + { 0x087E, "Fujitsu Computer Products of America" }, + { 0x087F, "QualCore Logic Inc" }, + { 0x0880, "APT Technologies Inc." }, + { 0x0881, "Sistemas Y Redes Telematicas, Sire S.L." }, + { 0x0882, "Rightec Research" }, + { 0x0883, "Recording Industry Association of America (RIAA)" }, + { 0x0884, "USB Systems" }, + { 0x0885, "Boca Research, Inc." }, + { 0x0887, "Hannstar Electronics Corp." }, + { 0x0889, "Current Works, Inc." }, + { 0x088A, "TechTools" }, + { 0x088B, "MassWorks" }, + { 0x088C, "Swecoin AB" }, + { 0x088D, "Engineering Spirit" }, + { 0x088E, "Pace Anti-Piracy, Inc." }, + { 0x088F, "Husky Computers Limited" }, + { 0x0890, "Consultronics Ltd." }, + { 0x0891, "Drager Medizintechnik Gmbh." }, + { 0x0892, "DioGraphy Inc." }, + { 0x0893, "Bartec" }, + { 0x0894, "TSI Incorporated" }, + { 0x0895, "Kanitech A/S" }, + { 0x0896, "Starseed Enterprises AG" }, + { 0x0897, "Lauterbach GmbH" }, + { 0x0898, "3M Canada" }, + { 0x0899, "Grieshaber & Co. AG" }, + { 0x089A, "Koepruelue Engineering" }, + { 0x089B, "Digital-3, LLC." }, + { 0x089C, "United Technologies Research Cntr." }, + { 0x089D, "Icron Technologies Corporation" }, + { 0x089E, "NST Co., Ltd." }, + { 0x089F, "Primex Aerospace Co." }, + { 0x08A0, "Logic Meca Co., Ltd." }, + { 0x08A1, "Studio Zee" }, + { 0x08A2, "Millennia Systems, Inc." }, + { 0x08A3, "Hyowon Software" }, + { 0x08A4, "YTG Smartech Inc." }, + { 0x08A5, "e9 Inc." }, + { 0x08A6, "Toshiba Tec Corporation" }, + { 0x08A7, "General Cybernetics Inc." }, + { 0x08A8, "Andrea Electronics" }, + { 0x08A9, "CWAV" }, + { 0x08AA, "Kernel Productions, Inc." }, + { 0x08AB, "Innolab Pte. Ltd." }, + { 0x08AC, "Macraigor Systems LLC" }, + { 0x08AD, "Toyota Technical Development Corporation (TTDC)" }, + { 0x08AE, "Macally (Mace Group, Inc.)" }, + { 0x08AF, "Hamilton Co." }, + { 0x08B0, "Metrohm Ltd." }, + { 0x08B1, "High Technology Laboratory s.r.l" }, + { 0x08B2, "BIOTRONIK GmbH & Co." }, + { 0x08B3, "Voice It Worldwide, Inc." }, + { 0x08B4, "Sorenson Communications" }, + { 0x08B5, "Correlator.com" }, + { 0x08B6, "Imagek, Inc." }, + { 0x08B7, "NATSU Corporation Limited" }, + { 0x08B8, "J. Gordon Electronic Design, Inc." }, + { 0x08B9, "General Wireless Operations Inc" }, + { 0x08BA, "Fujitsu General Limited" }, + { 0x08BB, "Texas Instruments Japan" }, + { 0x08BC, "Dr. G. Schuhfried GmbH" }, + { 0x08BD, "Citizen Watch Co., Ltd." }, + { 0x08BE, "Meilenstein GmbH" }, + { 0x08BF, "Nova Engineering, Inc." }, + { 0x08C0, "Braintronics B.V." }, + { 0x08C1, "Timestep Electronics Ltd." }, + { 0x08C2, "ArgoCraft Co., Ltd." }, + { 0x08C3, "Precise Biometrics" }, + { 0x08C4, "Proxim CBU" }, + { 0x08C5, "Moreton Bay" }, + { 0x08C6, "Scalex Corporation" }, + { 0x08C7, "TAI TWUN ENTERPRISE CO., LTD." }, + { 0x08C8, "2Wire, Inc" }, + { 0x08C9, "Nippon Telegraph and Telephone Corp." }, + { 0x08CA, "AIPTEK International Inc." }, + { 0x08CB, "Cyber Innovate, Inc." }, + { 0x08CC, "ifak system GmbH" }, + { 0x08CD, "Jue Hsun Ind. Corp." }, + { 0x08CE, "Long Well Electronics Corp." }, + { 0x08CF, "Productivity Enhancement Products" }, + { 0x08D0, "Tasco Electronics Co., Inc." }, + { 0x08D1, "Smartbridges Pte. Ltd." }, + { 0x08D2, "Dialog4 System Engineering Gmbh." }, + { 0x08D3, "Virtual Ink" }, + { 0x08D4, "Siemens PC Systeme GmbH" }, + { 0x08D5, "Cambridge Heart, Inc." }, + { 0x08D6, "Itautec Philco S.A." }, + { 0x08D7, "Opticon, Inc." }, + { 0x08D8, "Huntsville Microsystems, Inc." }, + { 0x08D9, "Increment P Corporation" }, + { 0x08DA, "A W Electronics, Inc." }, + { 0x08DB, "IXXAT Automation GmbH" }, + { 0x08DC, "Animo Limited" }, + { 0x08DD, "Billionton Systems, Inc." }, + { 0x08DE, "Touchstone Software" }, + { 0x08DF, "Spyrus Inc." }, + { 0x08E0, "Geodesic Designs, Inc." }, + { 0x08E1, "LSI JAPAN Co., Ltd" }, + { 0x08E2, "SafeNet China Ltd." }, + { 0x08E3, "OLITEC" }, + { 0x08E4, "Pioneer Corporation" }, + { 0x08E5, "LITRONIC" }, + { 0x08E6, "Gemalto SA" }, + { 0x08E7, "PAN-INTERNATIONAL WIRE & CABLE (M) SDN BHD" }, + { 0x08E8, "Integrated Memory Logic" }, + { 0x08E9, "Extended Systems, Inc." }, + { 0x08EA, "Ericsson Inc." }, + { 0x08EB, "Asulab SA" }, + { 0x08EC, "M-Systems Flash Disk Pioneers" }, + { 0x08ED, "Instrumentation Metrics, Inc." }, + { 0x08EE, "CCSI/HESSO" }, + { 0x08EF, "PixelVision" }, + { 0x08F0, "CardScan Inc." }, + { 0x08F1, "CTI Electronics Corporation" }, + { 0x08F2, "Constance Technology Co., Ltd." }, + { 0x08F3, "Wintime Electronics Corp." }, + { 0x08F4, "Telia ProSoft AB" }, + { 0x08F5, "SYSTEC Co., Ltd." }, + { 0x08F6, "Logic 3 International Limited" }, + { 0x08F7, "Vernier Software" }, + { 0x08F8, "Keen Top International Enterprise Co., Ltd." }, + { 0x08F9, "Wipro Technologies" }, + { 0x08FA, "CAERE" }, + { 0x08FB, "Socket Mobile, Inc." }, + { 0x08FC, "Sicon International" }, + { 0x08FD, "Digianswer A/S" }, + { 0x08FE, "GDSYSTEMS" }, + { 0x08FF, "AuthenTec, Inc." }, + { 0x0901, "VST Technologies" }, + { 0x0902, "iDream Technologies Pte Ltd" }, + { 0x0903, "Infolibria" }, + { 0x0904, "Frank Audiodata" }, + { 0x0905, "ISDG" }, + { 0x0906, "FARADAY Technology Corp." }, + { 0x0907, "Addison Technology Europe B.V." }, + { 0x0908, "Siemens Automation & Drives" }, + { 0x0909, "Audio-Technica Corp." }, + { 0x090A, "Trumpion Microelectronics Inc" }, + { 0x090B, "Neurosmith" }, + { 0x090C, "Silicon Motion, Inc. - Taiwan" }, + { 0x090D, "MULTIPORT Computer Vertriebs GmbH" }, + { 0x090E, "Shining Technology, Inc." }, + { 0x090F, "Fujitsu Devices Inc." }, + { 0x0910, "Alation Systems, Inc." }, + { 0x0911, "Philips Speech Processing" }, + { 0x0912, "Voquette, Inc." }, + { 0x0913, "Asante' Technologies, Inc." }, + { 0x0914, "Bally Gaming, Inc." }, + { 0x0915, "GlobespanVirata, Inc." }, + { 0x0916, "DH electronics GmbH" }, + { 0x0917, "SmartDisk Corporation" }, + { 0x0918, "Planet Portal.com" }, + { 0x0919, "Sound Vision Inc." }, + { 0x091A, "Inter-Cable Systems, Inc." }, + { 0x091B, "Raleigh Technology Corporation" }, + { 0x091C, "Bormann EDV + Zubehoer GmbH" }, + { 0x091D, "A. K. Barns Ltd." }, + { 0x091E, "Garmin International" }, + { 0x091F, "U-JIN Mesco Co., Ltd." }, + { 0x0920, "Echelon Corporation" }, + { 0x0921, "GoHubs, inc." }, + { 0x0922, "Dymo Corporation" }, + { 0x0923, "IC Media Corporation" }, + { 0x0924, "Xerox Corporation" }, + { 0x0925, "Lakeview Research" }, + { 0x0926, "Sound Devices, LLC" }, + { 0x0927, "Summus, Ltd." }, + { 0x0928, "Oxford Semiconductor Ltd." }, + { 0x0929, "American Biometric Company" }, + { 0x092A, "Toshiba Information & Industrial Sys. And Services" }, + { 0x092B, "Sena Technologies, Inc." }, + { 0x092C, "Shanghai Bell Company Limited" }, + { 0x092D, "OYO Instruments" }, + { 0x092E, "Markpoint AB" }, + { 0x092F, "Northern Embedded Science" }, + { 0x0930, "Toshiba Corporation" }, + { 0x0931, "Harmonic Data Systems Ltd." }, + { 0x0932, "Crescentec Corporation" }, + { 0x0933, "Quantum Corp." }, + { 0x0934, "Spirent Communications" }, + { 0x0935, "Accurite Technologies, Inc." }, + { 0x0936, "DynamicNakedAudio Inc." }, + { 0x0937, "Scania CV AB" }, + { 0x0938, "Virtual DSP Corporation" }, + { 0x0939, "Lumberg, Inc." }, + { 0x093A, "Pixart Imaging, Inc." }, + { 0x093B, "Plextor LLC" }, + { 0x093C, "Intrepid Control Systems, Inc." }, + { 0x093D, "InnoSync, Inc." }, + { 0x093E, "J.S.T. Mfg. Co., Ltd." }, + { 0x093F, "OLYMPIA Telecom Vertriebs GmbH" }, + { 0x0940, "Japan Storage Battery Co., Ltd." }, + { 0x0941, "Photobit Corporation" }, + { 0x0942, "i2Go.com, LLC" }, + { 0x0943, "HCL Technologies Ltd." }, + { 0x0944, "KORG, Inc." }, + { 0x0945, "PASCO Scientific" }, + { 0x0946, "GEMSTAR TECHOLOGY DEVELOPMENT LIMITED" }, + { 0x0947, "Videonics, Inc." }, + { 0x0948, "Kronauer Music In Digital" }, + { 0x0949, "Hitachi Kokusai Electric Inc." }, + { 0x094A, "Luckytech Technology Co., Ltd" }, + { 0x094B, "Linkup Systems Corporation" }, + { 0x094C, "Metanetics Corporation" }, + { 0x094D, "Cable Television Laboratories" }, + { 0x094E, "Head Acoustics" }, + { 0x094F, "Yano Electric Co., Ltd." }, + { 0x0950, "TechniSat Sateliltenfernsehprodukte Gmbh" }, + { 0x0951, "Kingston Technology Company" }, + { 0x0952, "DCOM Enterprise Co., Ltd." }, + { 0x0953, "PLG" }, + { 0x0954, "RPM Systems Corporation" }, + { 0x0955, "NVIDIA" }, + { 0x0956, "BSquare Corporation" }, + { 0x0957, "Agilent Technologies, Inc." }, + { 0x0958, "BioLink Technologies International, Inc." }, + { 0x0959, "Cologne Chip AG" }, + { 0x095A, "Portsmith" }, + { 0x095B, "Medialogic Corporation" }, + { 0x095C, "K-Tec Electronics" }, + { 0x095D, "Polycom, Inc." }, + { 0x095E, "USB Design Labs" }, + { 0x095F, "TTO Engineering" }, + { 0x0960, "Bcom Electronics, Inc." }, + { 0x0961, "Portatec Corporation" }, + { 0x0962, "SAMx" }, + { 0x0963, "Instrument Solutions" }, + { 0x0964, "Bitran Corporation" }, + { 0x0965, "PAR Technologies, Inc." }, + { 0x0966, "HanGo Electronics Co., Ltd." }, + { 0x0967, "Acer NeWeb Corporation" }, + { 0x0969, "Magellan Corp." }, + { 0x096A, "Koizumi Computer, Inc." }, + { 0x096B, "ML Electronics Ltd." }, + { 0x096C, "GOPEL electronic GmbH" }, + { 0x096D, "PennyLan" }, + { 0x096E, "Feitian Technologies Co., Ltd." }, + { 0x096F, "Memory Link" }, + { 0x0970, "K.S. Vector Co., Ltd." }, + { 0x0971, "GretagMacbeth AG" }, + { 0x0972, "Musicbird" }, + { 0x0973, "Axalto" }, + { 0x0974, "Eye Communication Systems, Inc" }, + { 0x0975, "OL'E Communications, Inc." }, + { 0x0976, "Adirondack Wire & Cable" }, + { 0x0977, "Lightsurf Technologies" }, + { 0x0978, "Beckhoff Gmbh" }, + { 0x0979, "Jeilin Technology Corp., Ltd." }, + { 0x097A, "Minds At Work LLC" }, + { 0x097B, "Knudsen Engineering Limited" }, + { 0x097C, "Marunix Co., Ltd." }, + { 0x097D, "Rosun Technologies, Inc." }, + { 0x097E, "Biopac Systems Inc." }, + { 0x097F, "Barun Electronics Co. Ltd." }, + { 0x0980, "Posh Mfg. Ltd." }, + { 0x0981, "Oak Technology Ltd." }, + { 0x0982, "Covadis S.A." }, + { 0x0983, "Nissha Printing Co., Ltd." }, + { 0x0984, "Apricorn" }, + { 0x0985, "Cab Produkttechnik" }, + { 0x0986, "Panasonic Electric Works Co., Ltd." }, + { 0x0987, "MicroSpeed Inc" }, + { 0x0988, "Teraoka Seiko Co. Ltd" }, + { 0x0989, "Digitel Co. LTD" }, + { 0x098A, "Neopost" }, + { 0x098B, "Kingtel Telecommunication Corp." }, + { 0x098C, "Vitana Corporation" }, + { 0x098D, "INDesign" }, + { 0x098E, "Integrated Intellectual Property Inc." }, + { 0x098F, "TEXIO CORPORATION" }, + { 0x0990, "General Instrument Corp." }, + { 0x0992, "Bandai Co., Ltd." }, + { 0x0993, "NuvoMedia, Inc." }, + { 0x0994, "Dionex Softron GmbH" }, + { 0x0995, "Simple Jet Technology Co., Ltd." }, + { 0x0996, "Integrated Telecom Express, Inc." }, + { 0x0997, "Xerox Corporation/Non-Networked Products" }, + { 0x0998, "Atech Totalsolution Co., Ltd." }, + { 0x0999, "Ocean Optics, Inc." }, + { 0x099A, "ZIPPY TECHNOLOGY CORP." }, + { 0x099B, "HIROTA SEISAKUSHO LTD." }, + { 0x099C, "Florida Probe, Inc." }, + { 0x099D, "NEC San-ei Instruments, Ltd." }, + { 0x099E, "Trimble" }, + { 0x099F, "Summa N.V." }, + { 0x09A0, "Altec Computersysteme GmbH" }, + { 0x09A1, "ELMO COMPANY, LIMITED" }, + { 0x09A2, "Telemann Co., Ltd." }, + { 0x09A3, "PairGain Technologies" }, + { 0x09A4, "Contech Research, Inc." }, + { 0x09A5, "VCON Telecommunications" }, + { 0x09A6, "Poinchips" }, + { 0x09A7, "Data Transmission Network Corp." }, + { 0x09A8, "Lin Shiung Enterprise Co., Ltd." }, + { 0x09A9, "Smart Card Technologies Co., Ltd." }, + { 0x09AA, "Intersil Corporation" }, + { 0x09AB, "Japan Cash Machine Co., Ltd." }, + { 0x09AC, "DIGIGRAM" }, + { 0x09AD, "The MITRE Corporation" }, + { 0x09AE, "Tripp Lite" }, + { 0x09AF, "G.i.N. mbH" }, + { 0x09B0, "Fargo Electronics, Inc." }, + { 0x09B1, "Ositech Communications Incorporated" }, + { 0x09B2, "Franklin Electronic Publishers" }, + { 0x09B3, "Simplex Solution Inc." }, + { 0x09B4, "MDS Gateways" }, + { 0x09B5, "Celltrix Technology Co., Ltd." }, + { 0x09B6, "SmithMyers Communications Limited" }, + { 0x09B7, "FAIRLIGHT ESP" }, + { 0x09B8, "PhoeniX . Incorporated" }, + { 0x09B9, "CentLand inc." }, + { 0x09BA, "Chumtronix N.V." }, + { 0x09BB, "Eule Industrie- & Datentechnik GmbH & Co. KG" }, + { 0x09BC, "Audivo GmbH" }, + { 0x09BD, "Haptix Creation Pte Ltd" }, + { 0x09BE, "Prosisa Overseas LLC" }, + { 0x09BF, "Auerswald GmbH & Co. KG" }, + { 0x09C0, "Molecular Devices LLC" }, + { 0x09C1, "ARRIS International" }, + { 0x09C2, "NISCA Corporation" }, + { 0x09C3, "ACTIVCARD, INC." }, + { 0x09C4, "ACTiSYS Corporation" }, + { 0x09C5, "Memory Corporation" }, + { 0x09C6, "Inovatec S.p.A." }, + { 0x09C7, "PUBCOMPANY s.r.l." }, + { 0x09C8, "Carrot Systems Inc." }, + { 0x09C9, "U.S. Digital Corp." }, + { 0x09CA, "BMC Messsysteme GmbH" }, + { 0x09CB, "Flir Systems" }, + { 0x09CC, "Workbit Corporation" }, + { 0x09CD, "Psion Connect Ltd." }, + { 0x09CE, "City Electronics Ltd." }, + { 0x09CF, "Electronics Testing Center, Taiwan" }, + { 0x09D1, "NeoMagic Inc." }, + { 0x09D2, "Vreelin Engineering Inc." }, + { 0x09D3, "COM ONE" }, + { 0x09D4, "Asahi Engineering Co., Ltd." }, + { 0x09D5, "DigiTech" }, + { 0x09D6, "Berkeley Varitronics Systems" }, + { 0x09D7, "NovAtel Inc." }, + { 0x09D8, "Elatec GmbH" }, + { 0x09D9, "Jungo" }, + { 0x09DA, "A-FOUR TECH CO., LTD." }, + { 0x09DB, "Measurement Computing Corporation" }, + { 0x09DC, "AIMEX Corporation" }, + { 0x09DD, "Fellowes Inc." }, + { 0x09DE, "ViQuest Technology" }, + { 0x09DF, "Addonics Technologies Corp." }, + { 0x09E0, "Johnson Matthey PLC, Trading as Tracerco" }, + { 0x09E1, "Intellon Corporation" }, + { 0x09E2, "Surface Imaging Systems (S.I.S.)" }, + { 0x09E3, "WIZnet" }, + { 0x09E4, "Unidata" }, + { 0x09E5, "Jo-Dan International, Inc." }, + { 0x09E6, "Silutia, Inc." }, + { 0x09E7, "Real 3D, Inc." }, + { 0x09E8, "AKAI professional M.I. Corp." }, + { 0x09E9, "CHEN-SOURCE INC." }, + { 0x09EA, "ShareCall Technologies" }, + { 0x09EB, "Sonicbox, Inc." }, + { 0x09EC, "COINT Multimedia Systems" }, + { 0x09ED, "Viking Sewing Machines AB" }, + { 0x09EE, "Jesmay Electronics Co., Ltd." }, + { 0x09EF, "XITEL PTY Limited" }, + { 0x09F0, "Perpetual Technologies, LLC" }, + { 0x09F1, "Eshed Robotec" }, + { 0x09F2, "hema Elektronik GmbH" }, + { 0x09F3, "GoFlight, Inc." }, + { 0x09F4, "Microlink Corporation" }, + { 0x09F5, "ARESCOM" }, + { 0x09F6, "RocketChips, Inc." }, + { 0x09F7, "EDU-SCIENCE (H.K.) LIMITED" }, + { 0x09F8, "SoftConnex Technologies, Inc." }, + { 0x09F9, "Bay Associates" }, + { 0x09FA, "Mtek Vision" }, + { 0x09FB, "Altera" }, + { 0x09FC, "Silicon Mountain Design" }, + { 0x09FD, "MM - Manager Memory" }, + { 0x09FE, "Goldteck International Inc." }, + { 0x09FF, "Gain Technology Corp." }, + { 0x0A00, "Liquid Audio" }, + { 0x0A01, "ViA, Inc." }, + { 0x0A02, "DIATECNIC" }, + { 0x0A03, "Globe Wireless, Inc." }, + { 0x0A04, "Star, Inc." }, + { 0x0A05, "University of Kansas" }, + { 0x0A06, "BSQUARE Slicon Valley" }, + { 0x0A07, "Ontrak Control Systems Inc." }, + { 0x0A08, "Lorenz GmbH" }, + { 0x0A09, "Datadesk Technologies Inc." }, + { 0x0A0A, "LIEWENTHAL ELECTRONICS LTD." }, + { 0x0A0B, "Cybex Computer Products Corporation" }, + { 0x0A0C, "MIRAD" }, + { 0x0A0D, "VIPS France" }, + { 0x0A0E, "AGFEO" }, + { 0x0A0F, "Liesegang" }, + { 0x0A10, "Combinova AB" }, + { 0x0A11, "Xentec Incorporated" }, + { 0x0A12, "Cambridge Silicon Radio Ltd." }, + { 0x0A13, "Telebyte Inc." }, + { 0x0A14, "Spacelabs Healthcare" }, + { 0x0A15, "Scalar Corporation" }, + { 0x0A16, "Trek Technology (S) Pte Ltd" }, + { 0x0A17, "HOYA Corporation" }, + { 0x0A18, "Heidelberger Druckmaschinen AG" }, + { 0x0A19, "Hua Geng Technologies Inc." }, + { 0x0A1A, "Astro-Med, Inc." }, + { 0x0A1B, "Wolfvision GmbH" }, + { 0x0A1C, "Micro Systemation AB" }, + { 0x0A1D, "T-Nova Deutsche Telekom Innovationsgesellschaft" }, + { 0x0A1E, "Netcraft (Pty) Ltd." }, + { 0x0A1F, "Tesco Co." }, + { 0x0A20, "SystemBase Co., Ltd." }, + { 0x0A21, "Physio-Control, Inc." }, + { 0x0A22, "Century Semiconductor USA, Inc." }, + { 0x0A23, "NDS Technologies Israel Ltd." }, + { 0x0A24, "Boca Design, Inc." }, + { 0x0A25, "3M Germany" }, + { 0x0A26, "Cyberware" }, + { 0x0A27, "Datacard Group" }, + { 0x0A28, "Ensure Technologies, Inc." }, + { 0x0A29, "Marketcast" }, + { 0x0A2A, "Fortune Electronics & Plastic (International) Ltd." }, + { 0x0A2B, "Muller & Sebastiani Elektronik GmbH" }, + { 0x0A2C, "Ak Modul Bus Computer GmbH" }, + { 0x0A2D, "Advanced Measurement Technology" }, + { 0x0A2E, "ONE-O-ONE iSOLUTIONS" }, + { 0x0A2F, "Prime Systems, Inc." }, + { 0x0A30, "WAW-Tronics" }, + { 0x0A31, "Data System Co., Ltd." }, + { 0x0A32, "Addatel ApS" }, + { 0x0A33, "Intermind Inc." }, + { 0x0A34, "TG3 Electronics, Inc." }, + { 0x0A35, "Radikal Technologies" }, + { 0x0A36, "GS Technical Support Center" }, + { 0x0A37, "Concept Development" }, + { 0x0A38, "I.R.I.S." }, + { 0x0A39, "Gilat Satellite Networks Ltd." }, + { 0x0A3A, "PentaMedia Co., Ltd." }, + { 0x0A3B, "Hitachi Information Technology Co., Ltd." }, + { 0x0A3C, "NTT DoCoMo,Inc." }, + { 0x0A3D, "Varo Vision" }, + { 0x0A3E, "REINHARDT System- und Messelectronic GmbH" }, + { 0x0A3F, "Swissonic AG" }, + { 0x0A40, "PaloDEx Group Oy" }, + { 0x0A41, "SEKONIC corporation" }, + { 0x0A42, "Medtronic Functional Diagnostics" }, + { 0x0A43, "Boca Systems Inc." }, + { 0x0A44, "TurboLinux" }, + { 0x0A45, "Look&Say co., Ltd." }, + { 0x0A46, "Davicom Semiconductor, Inc." }, + { 0x0A47, "Hirose Electric Co., Ltd." }, + { 0x0A48, "I/O Interconnect" }, + { 0x0A4A, "propagamma kommunikation" }, + { 0x0A4B, "Fujitsu Media Devices Limited" }, + { 0x0A4C, "COMPUTEX Co., Ltd." }, + { 0x0A4D, "Evolution Electronics Ltd." }, + { 0x0A4E, "Steinberg Soft-und Hardware GmbH" }, + { 0x0A4F, "Litton Systems Inc." }, + { 0x0A50, "Mimaki Engineering Co., Ltd." }, + { 0x0A51, "Sony Electronics Inc." }, + { 0x0A52, "JEBSEE ELECTRONICS CO., LTD." }, + { 0x0A53, "Portable Peripheral Co., Ltd." }, + { 0x0A54, "Applied Signal Technology, Inc." }, + { 0x0A55, "ThermoQuest Corporation" }, + { 0x0A56, "EAE electronics GmbH" }, + { 0x0A57, "Joachim Koopmann Software" }, + { 0x0A58, "DIGIDENT LTD." }, + { 0x0A59, "Convergence Instruments" }, + { 0x0A5B, "EASICS NV" }, + { 0x0A5C, "Broadcom Corp." }, + { 0x0A5D, "Diatrend Corporation" }, + { 0x0A5E, "Spinnaker Systems Inc." }, + { 0x0A5F, "Zebra Technologies" }, + { 0x0A60, "Future Networks, Inc." }, + { 0x0A61, "DTI sa" }, + { 0x0A62, "MPMan.com, Inc." }, + { 0x0A63, "Prism Media Products Ltd." }, + { 0x0A64, "Padcom Inc." }, + { 0x0A65, "FullAudio, Inc." }, + { 0x0A66, "ClearCube Technology" }, + { 0x0A67, "Medeli Electronics Co, Ltd." }, + { 0x0A68, "COMAIDE Corporation" }, + { 0x0A69, "Chroma ate Inc." }, + { 0x0A6A, "Newcom Inc." }, + { 0x0A6B, "Green House Co., Ltd." }, + { 0x0A6C, "Integrated Circuit Systems Inc." }, + { 0x0A6D, "UPS Manufacturing" }, + { 0x0A6E, "Benwin" }, + { 0x0A6F, "Core Technology, Inc." }, + { 0x0A70, "International Game Technology" }, + { 0x0A71, "VIPColor Technologies USA, Inc." }, + { 0x0A72, "Sanwa Denshi" }, + { 0x0A73, "SYDEC N.V." }, + { 0x0A74, "Adaptive Networks, Inc." }, + { 0x0A75, "Jeol USA, Inc." }, + { 0x0A76, "I-Jam Multi-Media, LLC" }, + { 0x0A77, "Janome Sewing Machine Co., Ltd." }, + { 0x0A78, "GREATSUN" }, + { 0x0A79, "Geocast Network Systems, Inc." }, + { 0x0A7A, "Towitoko AG" }, + { 0x0A7B, "R & D Co., Ltd." }, + { 0x0A7C, "QUANCOM Informationssysteme GmbH" }, + { 0x0A7D, "Intertek NSTL" }, + { 0x0A7E, "Octagon Systems Corporation" }, + { 0x0A7F, "AVerMedia MicroSystems" }, + { 0x0A80, "Rexon Technology Corp., Ltd" }, + { 0x0A81, "CHESEN ELECTRONICS CORP." }, + { 0x0A82, "SYSCAN" }, + { 0x0A83, "NextComm, Inc." }, + { 0x0A84, "Maui Innovative Peripherals" }, + { 0x0A85, "IDEXX LABS" }, + { 0x0A86, "NITGen Co., Ltd." }, + { 0x0A87, "Tucker-Davis Technologies, Inc." }, + { 0x0A88, "PAH-RAN TECH., INC." }, + { 0x0A89, "Active Company" }, + { 0x0A8A, "American Magnetics" }, + { 0x0A8B, "Intelliworxx Inc." }, + { 0x0A8C, "Tecmar" }, + { 0x0A8D, "Picturetel" }, + { 0x0A8E, "Japan Aviation Electronics Industry Ltd. (JAE)" }, + { 0x0A8F, "Young Chang Co. Ltd." }, + { 0x0A90, "Candy Technology Co., Ltd." }, + { 0x0A91, "Globlink Technology Inc." }, + { 0x0A92, "EGO SYStems Inc." }, + { 0x0A93, "C Technologies AB (publ)" }, + { 0x0A94, "Intersense" }, + { 0x0A95, "Origin Instruments Corporation" }, + { 0x0A96, "Evation.com" }, + { 0x0A97, "Guardware Systems Ltd." }, + { 0x0A98, "TECHNO ART CO., LTD" }, + { 0x0A99, "Talon Technology" }, + { 0x0A9A, "Business Navigator" }, + { 0x0A9B, "Input/Output Inc." }, + { 0x0A9C, "Applied Cytometry Systems" }, + { 0x0A9D, "Jung & Dusch GmbH" }, + { 0x0A9E, "Performance Concepts, Inc." }, + { 0x0A9F, "Sim-Addicts Design Group" }, + { 0x0AA0, "Vtech Communications Ltd." }, + { 0x0AA1, "Amer.com" }, + { 0x0AA2, "Delta Tau Data Systems, Inc." }, + { 0x0AA3, "Lava Computer Mfg. Inc." }, + { 0x0AA4, "Develco Elektronik" }, + { 0x0AA5, "First International Digital" }, + { 0x0AA6, "Perception Digital Limited" }, + { 0x0AA7, "Wincor Nixdorf GmbH & Co KG" }, + { 0x0AA8, "TriGem Computer, Inc." }, + { 0x0AA9, "Baromtec Co." }, + { 0x0AAA, "Japan CBM Corporation" }, + { 0x0AAB, "Vision Shape Europe SA." }, + { 0x0AAC, "iCompression Inc." }, + { 0x0AAD, "Rohde & Schwarz GmbH & Co. KG" }, + { 0x0AAE, "NEC infrontia Corporation" }, + { 0x0AAF, "digitalway co., ltd." }, + { 0x0AB0, "Arrow Strong Electronics CO. LTD" }, + { 0x0AB1, "Feig Electronic GmbH" }, + { 0x0AB2, "Sintefex Audio LDA" }, + { 0x0AB3, "CANON FINETECH INC." }, + { 0x0AB4, "esd electronic system design gmbh" }, + { 0x0AB5, "Beckman Coulter, Inc." }, + { 0x0AB6, "Labsystems Oy" }, + { 0x0AB7, "Cross electronics, inc." }, + { 0x0AB8, "TelePhotogenics, Inc." }, + { 0x0AB9, "Identcode Ltd." }, + { 0x0ABA, "University of Geneva" }, + { 0x0ABB, "Travsys BV" }, + { 0x0ABC, "Life-Tech, Inc." }, + { 0x0ABD, "Wako Rubber Industries Co., Ltd." }, + { 0x0ABE, "STEREOLINK.COM" }, + { 0x0ABF, "DeVaSys" }, + { 0x0AC0, "Nidek Co., Ltd." }, + { 0x0AC1, "MicroDatec GmbH" }, + { 0x0AC2, "BrainMaster Technologies, Inc." }, + { 0x0AC3, "ON Semiconductor (System Solutions Co., Ltd)" }, + { 0x0AC4, "LECO CORPORATION" }, + { 0x0AC5, "I & C Corporation" }, + { 0x0AC6, "Singing Electrons, Inc." }, + { 0x0AC7, "Panwest Corporation" }, + { 0x0AC8, "Vimicro Corporation" }, + { 0x0AC9, "Micro Solutions, Inc." }, + { 0x0ACA, "The Open Group" }, + { 0x0ACB, "DEICY CORPORATION" }, + { 0x0ACC, "Koga Electronics Co." }, + { 0x0ACD, "ID Tech" }, + { 0x0ACE, "ZyDAS Technology Corporation" }, + { 0x0ACF, "Intoto, Inc." }, + { 0x0AD0, "Intellix Corp." }, + { 0x0AD1, "Remotec Technology Ltd." }, + { 0x0AD2, "Service & Quality Technology Co., Ltd." }, + { 0x0AD3, "Bolton Engineering, Inc." }, + { 0x0AD4, "TIGEREX ENTERPRISE CO., LTD." }, + { 0x0AD5, "kuwatec, Inc." }, + { 0x0AD6, "Vir A/S" }, + { 0x0AD7, "Lynium L.L.C." }, + { 0x0AD8, "Aidonic Corporation" }, + { 0x0AD9, "Avolites Ltd." }, + { 0x0ADA, "Data Encryption Systems Ltd" }, + { 0x0ADB, "T.A.M. Co., Ltd." }, + { 0x0ADC, "KE Knestel Elektronik GmbH" }, + { 0x0ADD, "Alliance Distribution" }, + { 0x0ADE, "Microft Co., Ltd." }, + { 0x0ADF, "Arial Phone L.L.C." }, + { 0x0AE0, "Collins Medical" }, + { 0x0AE1, "Protein Solutions, Inc." }, + { 0x0AE2, "NERA SATCOM ASA" }, + { 0x0AE3, "Allion Labs, Inc." }, + { 0x0AE4, "Taito Corporation" }, + { 0x0AE5, "MacroSystem Digital Video AG" }, + { 0x0AE6, "EVI, Inc." }, + { 0x0AE7, "Neodym Systems Inc." }, + { 0x0AE8, "System Support Co., Ltd." }, + { 0x0AE9, "North Shore Circuit Design L.L.P." }, + { 0x0AEA, "SciEssence, LLC" }, + { 0x0AEB, "TTP Communications Ltd." }, + { 0x0AEC, "Neodio Technologies Corporation" }, + { 0x0AED, "ScottCare Corporation" }, + { 0x0AEE, "Max Co., Ltd." }, + { 0x0AEF, "Simple Systems, Ltd." }, + { 0x0AF0, "Option NV" }, + { 0x0AF1, "KYOEI Co., Ltd." }, + { 0x0AF2, "CARTS, LLC" }, + { 0x0AF3, "Scale Master Technology, LLC." }, + { 0x0AF4, "ARTRONICS CO. LTD" }, + { 0x0AF5, "Nakamichi" }, + { 0x0AF6, "SILVER I CO., LTD." }, + { 0x0AF7, "B2C2, Inc." }, + { 0x0AF8, "Taiwan Regular Electronics Co., Ltd." }, + { 0x0AF9, "NEW AFA TECHNOLOGY CO., LTD" }, + { 0x0AFA, "DMC Co., Ltd." }, + { 0x0AFB, "OO-ALC/TISMD-CAPRE" }, + { 0x0AFC, "Zaptronix Ltd" }, + { 0x0AFD, "Tateno Dennou, Inc." }, + { 0x0AFE, "Cummins Engine Company" }, + { 0x0AFF, "Jump Zone Network Products, Inc." }, + { 0x0B00, "INGENICO" }, + { 0x0B01, "Techno-Holon Corporation" }, + { 0x0B02, "Avery Weigh-Tronix" }, + { 0x0B03, "ARCA TECHNOLOGIES, LTD." }, + { 0x0B04, "EURESYS S.A." }, + { 0x0B05, "ASUSTek Computer Inc." }, + { 0x0B06, "Digital Ink, Inc." }, + { 0x0B07, "Telebau GmbH" }, + { 0x0B08, "Lightwell Co., Ltd ZAX Division" }, + { 0x0B09, "Allophonic Electronics L.t.d." }, + { 0x0B0A, "FARO Technologies INC." }, + { 0x0B0B, "Datamax Corporation" }, + { 0x0B0C, "Todos Data System AB" }, + { 0x0B0D, "Project Lab" }, + { 0x0B0E, "GN Audio" }, + { 0x0B0F, "AVID Technology" }, + { 0x0B10, "Pcally" }, + { 0x0B11, "I Tech Solutions Co., Ltd." }, + { 0x0B12, "T-Metrics, Inc." }, + { 0x0B13, "Practical Micro Design, Inc." }, + { 0x0B14, "Real Sport, Inc." }, + { 0x0B15, "Actia Do Brasil Ind. E. Com. Ltda." }, + { 0x0B16, "onscreen24" }, + { 0x0B17, "Scantron Corporation" }, + { 0x0B18, "Shimizu Works, Hitachi Air Conditioning Systems Co" }, + { 0x0B19, "Color Kinetics Inc." }, + { 0x0B1B, "Bematech Ind. Com. Equip. Elect. S.A." }, + { 0x0B1C, "York Electronics Centre" }, + { 0x0B1D, "Erich Jaeger GmbH" }, + { 0x0B1E, "Electronic Warfare Associates, Inc. (EWA)" }, + { 0x0B1F, "Insyde Software Corp." }, + { 0x0B20, "TransDimension Inc." }, + { 0x0B21, "Yokogawa Electric Corporation" }, + { 0x0B22, "Japan System Development Co. Ltd." }, + { 0x0B23, "Pan-Asia Electronics Co., Ltd." }, + { 0x0B24, "ITX E-Globaledge Corporation" }, + { 0x0B25, "Advanced Programming Concepts, Inc." }, + { 0x0B26, "Applied Scientific Instrumentation Inc." }, + { 0x0B27, "Ritek Corporation" }, + { 0x0B28, "Kenwood Corporation" }, + { 0x0B29, "Intertex Data AB" }, + { 0x0B2A, "Glotrex Co., Ltd." }, + { 0x0B2C, "Village Center, Inc." }, + { 0x0B2D, "Akatsuki Electronic work & study Corp." }, + { 0x0B2E, "CTL Inc." }, + { 0x0B2F, "Clarkspur Design, Inc." }, + { 0x0B30, "NewHeights Software" }, + { 0x0B31, "Kyowa Electronic Instruments Co., Ltd." }, + { 0x0B32, "Utrecht University MBF" }, + { 0x0B33, "Contour Design, Inc." }, + { 0x0B34, "KNP Technologies" }, + { 0x0B35, "Solutions Cubed" }, + { 0x0B36, "Iizuna Signal Processing Lab Inc." }, + { 0x0B37, "Hitachi ULSI Systems Co., Ltd." }, + { 0x0B39, "Omnidirectional Control Technology Inc." }, + { 0x0B3A, "IPaxess" }, + { 0x0B3B, "Bromax Communications, Inc." }, + { 0x0B3C, "Olivetti S.p.A" }, + { 0x0B3E, "Kikusui Electronics Corporation" }, + { 0x0B3F, "Mitec Systems, Inc." }, + { 0x0B40, "RF Solutions Ltd." }, + { 0x0B41, "Hal Corporation" }, + { 0x0B42, "LENZE GmbH & Co KG" }, + { 0x0B43, "Sixth Avenue Designs" }, + { 0x0B44, "Programa Tools, Inc." }, + { 0x0B45, "Event Electronics, LLC" }, + { 0x0B46, "Nuark Co., Ltd." }, + { 0x0B47, "Sportbug.com, Inc" }, + { 0x0B48, "TechnoTrend AG" }, + { 0x0B49, "ASCII Corporation" }, + { 0x0B4A, "Pocket Pyro, Inc." }, + { 0x0B4B, "XFX Creation Inc." }, + { 0x0B4C, "Comvurgent" }, + { 0x0B4D, "Graphtec" }, + { 0x0B4E, "Musical Electronics Ltd." }, + { 0x0B4F, "Neuralog, Inc." }, + { 0x0B50, "Starlight Marketing (H.K.) Ltd." }, + { 0x0B51, "USB KITS" }, + { 0x0B52, "Zight Corporation" }, + { 0x0B54, "Sinbon Electronics Co., Ltd." }, + { 0x0B55, "Sendtek Corporation" }, + { 0x0B56, "TYI Systems Ltd." }, + { 0x0B57, "Hanwang Technology Co., LTD." }, + { 0x0B59, "Lake Communications Ltd." }, + { 0x0B5A, "Corel Corporation" }, + { 0x0B5B, "Anritsu Corporation" }, + { 0x0B5C, "IDEAL Industries Inc." }, + { 0x0B5D, "Music Playground Inc." }, + { 0x0B5E, "Luciol Instruments" }, + { 0x0B5F, "Green Electronics Co., Ltd." }, + { 0x0B60, "SiConnect Ltd." }, + { 0x0B61, "NEC Display Solutions, Ltd." }, + { 0x0B62, "Orange Micro, Inc." }, + { 0x0B63, "ADLink Technology Inc." }, + { 0x0B64, "Wonderful Wire Cable Co., Ltd" }, + { 0x0B65, "Expert Magnetics Corp." }, + { 0x0B66, "Cybiko Inc." }, + { 0x0B67, "Fairbanks Scales" }, + { 0x0B68, "SenDEC Corporation" }, + { 0x0B69, "CacheVision" }, + { 0x0B6A, "Maxim Integrated Products" }, + { 0x0B6B, "Ashling Microsystems Ltd." }, + { 0x0B6C, "FreeSystems Pte Ltd" }, + { 0x0B6D, "The Graphics Network Limited" }, + { 0x0B6E, "Neurosoft, Inc." }, + { 0x0B6F, "Nagano Japan Radio Co., Ltd" }, + { 0x0B70, "PortalPlayer, Inc." }, + { 0x0B71, "SHIN-EI Sangyo Co., Ltd." }, + { 0x0B72, "Embedded Wireless Technology Co. Ltd." }, + { 0x0B73, "Computone Corp." }, + { 0x0B75, "Roland DG Corporation" }, + { 0x0B76, "Pro-Tech Services Inc." }, + { 0x0B77, "RJS, Inc." }, + { 0x0B78, "ATSKY" }, + { 0x0B79, "Sunrise Telecom, Inc." }, + { 0x0B7A, "Zeevo, Inc." }, + { 0x0B7B, "Taiko Denki Co., Ltd." }, + { 0x0B7C, "ITRAN Communications Ltd." }, + { 0x0B7D, "Astrodesign, Inc." }, + { 0x0B7E, "Kurusugawa Electronics Incorporate" }, + { 0x0B7F, "Scantech BV" }, + { 0x0B80, "Omtronix Engineering Corp." }, + { 0x0B81, "id3 Semiconductors" }, + { 0x0B82, "TravRoute, a division of ALK Associates, Inc." }, + { 0x0B83, "OCTAX Microscience" }, + { 0x0B84, "Rextron Technology, Inc." }, + { 0x0B85, "Elkat Electronics (M) SDN. BHD." }, + { 0x0B86, "Exputer Systems, Inc." }, + { 0x0B87, "Plus-One I & T Inc." }, + { 0x0B88, "Sigma Koki Co., Ltd. Technology Center" }, + { 0x0B89, "Advanced Digital Broadcast Ltd." }, + { 0x0B8A, "YARC Systems Corporation" }, + { 0x0B8B, "American Microsystems, Ltd." }, + { 0x0B8C, "SMART Technologies Inc." }, + { 0x0B8D, "Microsystems Development Technologies, Inc." }, + { 0x0B8E, "Dartcom" }, + { 0x0B8F, "Visual Environment" }, + { 0x0B90, "DACTRON INC." }, + { 0x0B91, "DesignTech International, Inc." }, + { 0x0B92, "SINAR AG" }, + { 0x0B93, "Marantz Japan, Inc." }, + { 0x0B94, "NEOREX Co., Ltd." }, + { 0x0B95, "ASIX Electronics Corporation" }, + { 0x0B96, "SEWON TELECOM" }, + { 0x0B97, "O2Micro, Inc." }, + { 0x0B98, "Playmates Toys Inc." }, + { 0x0B99, "Audio International, Inc." }, + { 0x0B9A, "Namco Limited" }, + { 0x0B9B, "Dipl.-Ing. Stefan Kunde" }, + { 0x0B9C, "Melco Embroidery Systems" }, + { 0x0B9D, "Softprotec Co." }, + { 0x0B9E, "Asylum Research" }, + { 0x0B9F, "Chippo Technologies" }, + { 0x0BA0, "Turtle Industry Co., Ltd." }, + { 0x0BA1, "Jowit Company Limited" }, + { 0x0BA2, "Line Media Research CO., LTD." }, + { 0x0BA3, "Taiko Electric Works, Ltd." }, + { 0x0BA4, "Nagano Oki Electric Co., Ltd." }, + { 0x0BA5, "Clemex Technologies Inc." }, + { 0x0BA6, "3DM Devices Inc" }, + { 0x0BA7, "CVC Networks Co., Ltd." }, + { 0x0BA8, "CastleNet Technology Inc." }, + { 0x0BA9, "Misawa Homes Co., Ltd." }, + { 0x0BAA, "Dr. Gerhard Schmidt GmbH" }, + { 0x0BAB, "House Ear Institute" }, + { 0x0BAC, "Biometric Access Corporation" }, + { 0x0BAD, "Festo Didactic Ltd/Ltee" }, + { 0x0BAE, "IGEN International, Inc." }, + { 0x0BAF, "U.S. Robotics" }, + { 0x0BB0, "Concord Camera Corp." }, + { 0x0BB1, "Infinilink Corporation" }, + { 0x0BB2, "Ambit Microsystems Corporation" }, + { 0x0BB3, "Ofuji Technology" }, + { 0x0BB4, "HTC Corporation" }, + { 0x0BB5, "Murata Manufacturing Co., Ltd." }, + { 0x0BB6, "Network Alchemy" }, + { 0x0BB7, "Joytech Computer Company Limited" }, + { 0x0BB8, "Renesas Technology Sales Co., Ltd." }, + { 0x0BB9, "Eiger M & C CO., LTD." }, + { 0x0BBA, "ZACCESS Systems" }, + { 0x0BBB, "General Meters Corporation" }, + { 0x0BBC, "Assistive Technology, Inc." }, + { 0x0BBD, "System Connection, Inc" }, + { 0x0BBE, "ShibaSoku Co., Ltd." }, + { 0x0BBF, "Algo Communication Products Ltd." }, + { 0x0BC0, "Knilink Technology Inc." }, + { 0x0BC1, "FUW YNG ELECTRONICS COMPANY LTD" }, + { 0x0BC2, "Seagate Technology LLC" }, + { 0x0BC3, "IPWireless, Inc." }, + { 0x0BC4, "Microcube Corp." }, + { 0x0BC5, "JCN Co., Ltd." }, + { 0x0BC6, "ExWAY Inc." }, + { 0x0BC7, "X10 Wireless Technology, Inc." }, + { 0x0BC8, "Telmax Communications" }, + { 0x0BC9, "ECI Telecom Ltd" }, + { 0x0BCA, "Startek Engineering Incorporated" }, + { 0x0BCB, "Perfect Technic Enterprise Co. LTD" }, + { 0x0BCC, "Dolphin Interactive" }, + { 0x0BCD, "Mbeware Inc." }, + { 0x0BCE, "I-TEC hanshin Incorporated Company" }, + { 0x0BCF, "Chuo-Engineering Ltd." }, + { 0x0BD0, "Trenz Electronic" }, + { 0x0BD1, "Blue Sky Labs, Inc." }, + { 0x0BD2, "Union Biometrica" }, + { 0x0BD3, "OPHIR OPTRONICS LTD" }, + { 0x0BD4, "NISSIN INC." }, + { 0x0BD5, "Rabbit House Corporation" }, + { 0x0BD6, "Renaissance Learning Inc." }, + { 0x0BD7, "Andrew Pargeter & Associates" }, + { 0x0BD8, "Gamry Instruments, Inc." }, + { 0x0BD9, "Liberty Instruments, Inc." }, + { 0x0BDA, "Realtek Semiconductor Corp." }, + { 0x0BDB, "Ericsson AB" }, + { 0x0BDC, "Y Media Corporation" }, + { 0x0BDD, "Orange PCS" }, + { 0x0BDE, "Thuris Corporation" }, + { 0x0BDF, "PopcomNet Co., Ltd" }, + { 0x0BE0, "Silicon Magic Co., LTD" }, + { 0x0BE1, "COM DEV Wireless" }, + { 0x0BE2, "Kanda Tsushin Kogyo Co., LTD" }, + { 0x0BE3, "TOYO Corporation" }, + { 0x0BE4, "Elka International Ltd." }, + { 0x0BE5, "DOME Imaging Systems, Inc" }, + { 0x0BE6, "Wonderful Photoelectricity (DongGuan), Co., Ltd." }, + { 0x0BE7, "Zanthic Technologies Inc." }, + { 0x0BE8, "M@inNet Communication" }, + { 0x0BE9, "Realistic Interactive, Inc." }, + { 0x0BEA, "Bryce Office Systems" }, + { 0x0BEB, "RPA Electronics Design, LLC" }, + { 0x0BEC, "Idaho Technology" }, + { 0x0BED, "MEI, Inc." }, + { 0x0BEE, "LTK International Limited" }, + { 0x0BEF, "Way2Call Communications" }, + { 0x0BF0, "Pace Micro Technology PLC" }, + { 0x0BF1, "Intracom S.A." }, + { 0x0BF2, "Konexx" }, + { 0x0BF3, "CTI Co., Ltd." }, + { 0x0BF4, "Kuraya-Sanseido Co., Ltd." }, + { 0x0BF5, "Xactex Corporation" }, + { 0x0BF6, "Addonics Technologies, Inc." }, + { 0x0BF7, "Sunny Giken Inc." }, + { 0x0BF8, "Fujitsu Technology Solutions GmbH" }, + { 0x0BF9, "QPICT, Inc." }, + { 0x0BFA, "NKE Corporation" }, + { 0x0BFB, "Grass Valley Group" }, + { 0x0BFC, "Zero Mass Products Inc." }, + { 0x0BFD, "KVASER AB" }, + { 0x0BFE, "Morphy Planning & Co., Ltd" }, + { 0x0BFF, "Damotech Inc." }, + { 0x0C00, "ATM Computer" }, + { 0x0C01, "K-One Telecom Co., Ltd." }, + { 0x0C02, "Shinko Seisakusho Co., LTD" }, + { 0x0C03, "SAXA Inc." }, + { 0x0C04, "MOTO Development Group, Inc." }, + { 0x0C05, "Appian Graphics" }, + { 0x0C06, "Hasbro, Inc." }, + { 0x0C07, "Infinite Data Storage LTD" }, + { 0x0C08, "ei Corporation" }, + { 0x0C09, "Comjet Information System" }, + { 0x0C0A, "Highpoint Technologies, Inc." }, + { 0x0C0B, "Dura Micro, Inc." }, + { 0x0C0C, "OPTIKON 2000 S.P.A." }, + { 0x0C0D, "Callify Communications & Software Ltd." }, + { 0x0C0E, "Korea eBook Inc." }, + { 0x0C0F, "IDS Innomic GmbH" }, + { 0x0C10, "Silicon Wave" }, + { 0x0C11, "Multigon Industries" }, + { 0x0C12, "Zeroplus Technology Co; LTD" }, + { 0x0C13, "Orion Electronics International" }, + { 0x0C14, "Parallel Technologies, Inc." }, + { 0x0C15, "Iris Graphics" }, + { 0x0C16, "Gyration, Inc." }, + { 0x0C17, "Cyberboard A/S" }, + { 0x0C18, "SynerTek Korea, Inc." }, + { 0x0C19, "cyberPIXIE, Inc." }, + { 0x0C1A, "Silicon Motion, Inc." }, + { 0x0C1B, "MIPS TECHNOLOGIES" }, + { 0x0C1C, "Hang Zhou Silan Microelectronics Co. Ltd" }, + { 0x0C1D, "Digital Audio Corporation" }, + { 0x0C1E, "TAKAYA CORP." }, + { 0x0C1F, "Magicard Ltd" }, + { 0x0C20, "Viditec Inc." }, + { 0x0C21, "Lunatronic" }, + { 0x0C22, "TallyGenicom LP" }, + { 0x0C23, "Lernout + Hauspie (L + H)" }, + { 0x0C24, "Taiyo Yuden Co., Ltd." }, + { 0x0C25, "Sampo Corporation" }, + { 0x0C26, "Icom Inc." }, + { 0x0C27, "RF Ideas" }, + { 0x0C28, "ICCC" }, + { 0x0C29, "SOGECLAIR aerospace" }, + { 0x0C2A, "AFP Imaging Corp." }, + { 0x0C2B, "AT system" }, + { 0x0C2C, "Controller Technologies Corporation" }, + { 0x0C2D, "Scientific Data Systems, Inc." }, + { 0x0C2E, "Honeywell Scanning & Mobility" }, + { 0x0C2F, "Starcover GmbH" }, + { 0x0C30, "MUTOH EUROPE N.V." }, + { 0x0C31, "Cosmo Techs Co., Ltd." }, + { 0x0C32, "Weibel Scientific A/S" }, + { 0x0C33, "GN Otometrics A/S" }, + { 0x0C34, "Interisa Electronica" }, + { 0x0C35, "Eagletron Inc." }, + { 0x0C36, "E INK CORPORATION" }, + { 0x0C37, "e.Digital" }, + { 0x0C38, "Der An Electric Wire & Cable Co. Ltd." }, + { 0x0C39, "Aeroflex" }, + { 0x0C3A, "Furui Precise Component (Kunshan) Co., Ltd" }, + { 0x0C3B, "Komatsu Ltd." }, + { 0x0C3C, "Radius Co., Ltd." }, + { 0x0C3D, "Innocom, Inc." }, + { 0x0C3E, "NEXTCELL INC." }, + { 0x0C3F, "Street Smart Security" }, + { 0x0C40, "Navini Networks, Inc" }, + { 0x0C41, "findtheDOT" }, + { 0x0C42, "OMAX Corporation" }, + { 0x0C43, "BIOMETRIKA" }, + { 0x0C44, "Motorola iDEN" }, + { 0x0C45, "Sonix Technology Co., Ltd." }, + { 0x0C46, "WaveRider Communications, Inc" }, + { 0x0C47, "TECAN Group AG" }, + { 0x0C48, "MARPOSS S.p.A." }, + { 0x0C49, "Gigahertz-Optik GmbH" }, + { 0x0C4A, "ALGE-TIMING GmbH & Co" }, + { 0x0C4B, "REINER Kartengeraete GmbH & Co.KG" }, + { 0x0C4C, "Needham's Electronics Inc" }, + { 0x0C4D, "ICHIRO.ORG" }, + { 0x0C4E, "Sonic Innovations, Inc." }, + { 0x0C4F, "01dB-Stell" }, + { 0x0C50, "Forvus Research Inc." }, + { 0x0C51, "Trax Softworks, Inc." }, + { 0x0C52, "Sealevel Systems, Inc." }, + { 0x0C53, "ViewPLUS Inc." }, + { 0x0C54, "GLORY LTD." }, + { 0x0C55, "Spectrum Digital Inc." }, + { 0x0C56, "Billion Bright (HK) Corporation Limited" }, + { 0x0C57, "Imaginative Design Operation Co. Ltd." }, + { 0x0C58, "Vidar Systems Corporation" }, + { 0x0C59, "Dong Guan Shinko Wire Co., Ltd." }, + { 0x0C5A, "TRS International Mfg., Inc." }, + { 0x0C5B, "EDEC Co., Ltd." }, + { 0x0C5C, "Obbligato Objectives" }, + { 0x0C5D, "Musitronics GmbH" }, + { 0x0C5E, "Xytronix Research & Design" }, + { 0x0C5F, "WAVESYSTEMS" }, + { 0x0C60, "Apogee Electronics Corporation" }, + { 0x0C61, "Network Security Technology Co." }, + { 0x0C62, "Chant Sincere Co., Ltd" }, + { 0x0C63, "Toko, Inc." }, + { 0x0C64, "Signality System Engineering Co., Ltd." }, + { 0x0C65, "Eminence Enterprise Co., Ltd." }, + { 0x0C66, "REXON ELECTRONICS CORP." }, + { 0x0C67, "Concept Telecom Ltd" }, + { 0x0C68, "Whanam Electronics Co., Ltd." }, + { 0x0C69, "COMPUTechnic AG" }, + { 0x0C6A, "Ackerman Computer Sciences" }, + { 0x0C6B, "Spectrum Techniques, Inc" }, + { 0x0C6C, "JETI Technische Instrumente GmbH" }, + { 0x0C6D, "Aardvark" }, + { 0x0C6E, "Zaxus Limited" }, + { 0x0C6F, "SCC Research" }, + { 0x0C70, "MCT Elektronikladen" }, + { 0x0C71, "Fa. Hydrotechnik" }, + { 0x0C72, "PEAK-System-Technik" }, + { 0x0C73, "Omega Well Monitoring" }, + { 0x0C74, "Optronic Laboratories, Inc." }, + { 0x0C75, "Ripmax Plc" }, + { 0x0C76, "Solid State System Co., Ltd." }, + { 0x0C77, "SIPIX GROUP LIMITED" }, + { 0x0C78, "Detto Corporation" }, + { 0x0C79, "NuConnex Technologies PTE LTD" }, + { 0x0C7A, "Wing-Span Enterprise Co., Ltd." }, + { 0x0C7B, "Link Instruments, Inc." }, + { 0x0C7C, "TMS International BV" }, + { 0x0C7E, "KIRK telecom" }, + { 0x0C7F, "SoftBaugh, Inc." }, + { 0x0C80, "Optim Electronics" }, + { 0x0C81, "Dragon State Ltd." }, + { 0x0C82, "Impeccable Instruments, LLC" }, + { 0x0C83, "Cylink" }, + { 0x0C84, "Howell Instruments, Inc." }, + { 0x0C85, "Lectra Systemes" }, + { 0x0C86, "NDA Technologies, Inc." }, + { 0x0C87, "Aubit, Ltd." }, + { 0x0C88, "Kyocera Wireless Inc." }, + { 0x0C89, "Honda Tsushin Kogyo Co., Ltd" }, + { 0x0C8A, "Cast Lighting Limited" }, + { 0x0C8B, "Wavefly Corporation" }, + { 0x0C8C, "Coactive Networks" }, + { 0x0C8D, "Greenlee Textron, Inc." }, + { 0x0C8E, "Cesscom Co., Ltd." }, + { 0x0C8F, "Applied Microsystems" }, + { 0x0C90, "American Arium" }, + { 0x0C91, "FPGA Information" }, + { 0x0C92, "Nixvue Systems PTE LTD" }, + { 0x0C93, "Alara Inc." }, + { 0x0C94, "SAGEM Denmark" }, + { 0x0C95, "Kyushu-Kyohan Co., Ltd." }, + { 0x0C96, "TOPCON Positioning Systems" }, + { 0x0C97, "GRE America, Inc." }, + { 0x0C98, "Berkshire Products, Inc." }, + { 0x0C99, "Innochips Co., Ltd." }, + { 0x0C9A, "Hanool Robotics Corp" }, + { 0x0C9B, "Jobin Yvon, Inc." }, + { 0x0C9C, "Brand Innovators" }, + { 0x0C9D, "DyOcean" }, + { 0x0C9E, "PLEXUS MULTIMEDIA PTE LTD" }, + { 0x0C9F, "Extenex Corporation" }, + { 0x0CA0, "Robert Bosch GmbH - Automotive Aftermarket" }, + { 0x0CA1, "Mentor Engineering, Inc." }, + { 0x0CA2, "Zyfer" }, + { 0x0CA3, "SEGA CORPORATION" }, + { 0x0CA4, "ST&T INSTRUMENT CORP." }, + { 0x0CA5, "BAE SYSTEMS CANADA INC." }, + { 0x0CA6, "Castles Technology Co. Ltd." }, + { 0x0CA7, "Information Systems Laboratories" }, + { 0x0CA8, "Digital Audio Labs, Inc." }, + { 0x0CA9, "Institut fuer Rundfunktechnik" }, + { 0x0CAA, "Allied Telesis K.K." }, + { 0x0CAB, "Melon Technos Co., Ltd." }, + { 0x0CAC, "NEC Electronics (Europe) GmbH" }, + { 0x0CAD, "Motorola Solutions" }, + { 0x0CAE, "swissvoice ag" }, + { 0x0CAF, "Buslink" }, + { 0x0CB0, "Flying Pig Systems" }, + { 0x0CB1, "Innovonics, Inc." }, + { 0x0CB2, "Softmark" }, + { 0x0CB3, "FitzSimons Automation" }, + { 0x0CB4, "PalmMicro Communications, Inc." }, + { 0x0CB5, "Esel International Company Ltd." }, + { 0x0CB6, "Celestix Networks PTE LTD" }, + { 0x0CB7, "Singatron Enterprise Co. Ltd." }, + { 0x0CB8, "Opticis Co., Ltd." }, + { 0x0CB9, "VTECH INFORMATIONS LTD." }, + { 0x0CBA, "Trust Electronic (Shanghai) Co., Ltd." }, + { 0x0CBB, "Shanghai Darong Electronics Co., Ltd." }, + { 0x0CBC, "PALMAX Technology Co., Ltd." }, + { 0x0CBD, "Pentel Co., Ltd. (Electronics Equipment Div.)" }, + { 0x0CBE, "Keryx Technologies, Inc." }, + { 0x0CBF, "Union Genius Computer Co., Ltd" }, + { 0x0CC0, "Kuon Yi Industrial Corp." }, + { 0x0CC2, "Timex Corporation" }, + { 0x0CC3, "Rimage Corporation" }, + { 0x0CC4, "emsys Embedded Systems GmbH" }, + { 0x0CC5, "SENDO" }, + { 0x0CC6, "INTERMAGIC CORP." }, + { 0x0CC7, "Kontron Medical AG" }, + { 0x0CC8, "Technotools Corporation" }, + { 0x0CC9, "BroadMAX Technologies, Inc." }, + { 0x0CCA, "Amphenol Corporation" }, + { 0x0CCB, "SKNET CORPORATION LTD." }, + { 0x0CCC, "DOMEX TECHNOLOGY CORPORATION" }, + { 0x0CCD, "TerraTec Electronic GmbH" }, + { 0x0CCE, "Optical Imaging Inc." }, + { 0x0CCF, "T&D CORPORATION" }, + { 0x0CD0, "Art Haven 9 Co., Ltd" }, + { 0x0CD1, "Premier Technologies, Inc." }, + { 0x0CD2, "C-MAP SRL" }, + { 0x0CD3, "Pretorian Manufacturing Ltd" }, + { 0x0CD4, "Amplex" }, + { 0x0CD5, "Colorado Circuitworks, Inc." }, + { 0x0CD6, "Scheldt & Bachmann GmbH" }, + { 0x0CD7, "NEWCHIP S.r.l." }, + { 0x0CD8, "JS Digitech, Inc." }, + { 0x0CD9, "Shin Din Cable Ltd." }, + { 0x0CDA, "INTERFACE K.K." }, + { 0x0CDB, "OSMOOZE S.A." }, + { 0x0CDC, "HIJI HIGH-TECH CO., LTD." }, + { 0x0CDD, "Fidelica Microsystems, Inc." }, + { 0x0CDE, "Z-Com INC." }, + { 0x0CDF, "BUZZ-VC" }, + { 0x0CE0, "ZAPEX Research Ltd." }, + { 0x0CE1, "Pepperoni Light" }, + { 0x0CE2, "Eltech Solutions Inc." }, + { 0x0CE3, "MaxVision Corporation" }, + { 0x0CE4, "JOOHONG" }, + { 0x0CE5, "Hemisphere West" }, + { 0x0CE6, "First Silicon Solutions, Inc." }, + { 0x0CE7, "Bakker IT Services BV" }, + { 0x0CE8, "Interflex Datensysteme GmbH" }, + { 0x0CE9, "Pico Technology Limited" }, + { 0x0CEA, "PRO TECH COMMUNICATIONS INC." }, + { 0x0CEB, "Sophia Systems Co., Ltd." }, + { 0x0CEC, "Cyverse Corp." }, + { 0x0CED, "MAYCOM Audio Systems b.v." }, + { 0x0CEE, "Gaitmat II" }, + { 0x0CEF, "Contex A/S" }, + { 0x0CF0, "Cadac Electronics plc." }, + { 0x0CF1, "e-CONN ELECTRONIC CO., LTD." }, + { 0x0CF2, "ENE Technology Inc." }, + { 0x0CF3, "Qualcomm Atheros, Inc." }, + { 0x0CF4, "Fomtex Corporation" }, + { 0x0CF5, "Cellink Co., Ltd." }, + { 0x0CF6, "Compucable Corporation" }, + { 0x0CF7, "ishoni Networks" }, + { 0x0CF8, "Clarisys Incorporated" }, + { 0x0CF9, "Central System Research Co., Ltd." }, + { 0x0CFA, "Inviso, Inc." }, + { 0x0CFB, "SEnergy Corporation" }, + { 0x0CFC, "Konica-Minolta" }, + { 0x0CFD, "Hitex UK Ltd." }, + { 0x0CFE, "L.J. Technical Systems Ltd." }, + { 0x0CFF, "SAFA MEDIA CO., LTD." }, + { 0x0D00, "Polar Instruments Ltd" }, + { 0x0D01, "Red Bird LLC" }, + { 0x0D02, "Vestibular Technolgies" }, + { 0x0D03, "Triad Spectrum Ltd." }, + { 0x0D04, "Addmaster Corporation" }, + { 0x0D05, "Chung Nam Electronics Co. Ltd." }, + { 0x0D06, "telos EDV Systementwicklung GmbH" }, + { 0x0D07, "TAUREUS s.r.o." }, + { 0x0D08, "UTStarcom (Hangzhou) Telecom Co., Ltd" }, + { 0x0D09, "MMELECTRONICS" }, + { 0x0D0A, "Colourfull Creations" }, + { 0x0D0B, "Contemporary Controls" }, + { 0x0D0C, "Astron Electronics Co., Ltd." }, + { 0x0D0D, "MKNet Corporation" }, + { 0x0D0E, "Hybrid Networks, Inc" }, + { 0x0D0F, "Feng Shin Cable Co. Ltd." }, + { 0x0D10, "Elastic Networks" }, + { 0x0D11, "Maspro Denkoh Corp." }, + { 0x0D12, "Hansol Electronics Inc." }, + { 0x0D13, "BMF CORPORATION" }, + { 0x0D14, "Array Comm, Inc." }, + { 0x0D15, "OnStream b.v." }, + { 0x0D16, "Hi-Touch Imaging Technologies Co., Ltd." }, + { 0x0D17, "NALTEC, Inc." }, + { 0x0D18, "coaXmedia" }, + { 0x0D19, "Shanghai Hank Connection Co., Ltd." }, + { 0x0D1A, "COMTECH SYSTEMS, INC" }, + { 0x0D1B, "EC Engineering, LLC" }, + { 0x0D1C, "MACSEMA, INC" }, + { 0x0D1D, "GEMAC mbH" }, + { 0x0D1E, "Eone Inc." }, + { 0x0D1F, "imc MessSysteme GmbH" }, + { 0x0D20, "Malcom Co., Ltd." }, + { 0x0D22, "Rojone Pty Ltd" }, + { 0x0D23, "SATAKE USA INC." }, + { 0x0D24, "Trapper Data AB" }, + { 0x0D25, "PENTTECH Engineering Systems AB" }, + { 0x0D26, "Micro-Vu" }, + { 0x0D27, "CLEARJET GmbH" }, + { 0x0D28, "ARM Ltd" }, + { 0x0D29, "Eng Resource Inc" }, + { 0x0D2A, "FIELDSERVER TECHNOLOGIES" }, + { 0x0D2B, "DAINIPPON SCREEN" }, + { 0x0D2C, "3M Library Systems" }, + { 0x0D2D, "GigaSysNet" }, + { 0x0D2E, "Feedback Instruments Ltd" }, + { 0x0D2F, "Andamiro Co., Ltd." }, + { 0x0D30, "Vision Electronics Co., Ltd." }, + { 0x0D31, "Arizona Cooperative Power" }, + { 0x0D32, "Leo Hui Electric Wire & Cable Co., Ltd." }, + { 0x0D33, "AirSpeak Inc." }, + { 0x0D34, "Moxi Digital, Inc." }, + { 0x0D35, "Dah Kun Co., Ltd." }, + { 0x0D36, "Tellabs" }, + { 0x0D37, "PRISM" }, + { 0x0D38, "Nihon Culture-soft Service Co., Ltd." }, + { 0x0D3A, "Posiflex Technologies, Inc." }, + { 0x0D3B, "SANYO TECNICA Co., Ltd." }, + { 0x0D3C, "SRI CABLE TECHNOLOGY LTD." }, + { 0x0D3D, "TANGTOP TECHNOLOGY CO., LTD." }, + { 0x0D3E, "Fitcom, inc." }, + { 0x0D3F, "MTS Systems Corporation" }, + { 0x0D40, "Ascor Inc." }, + { 0x0D41, "Ta Yun Electronic Technology Co., Ltd." }, + { 0x0D42, "FULL DER CO., LTD." }, + { 0x0D43, "iCableSystem Co., Ltd." }, + { 0x0D44, "AFG Elektronik GmbH" }, + { 0x0D45, "Union Data Corporation" }, + { 0x0D46, "KOBIL Systems GmbH" }, + { 0x0D47, "KOPEK PACIFIC LTD." }, + { 0x0D48, "PROMETHEAN" }, + { 0x0D49, "Maxtor" }, + { 0x0D4A, "NF Corporation" }, + { 0x0D4B, "Grape Systems Inc." }, + { 0x0D4C, "TEDAS AG" }, + { 0x0D4D, "Coherent Inc." }, + { 0x0D4E, "Agere Systems Netherland BV" }, + { 0x0D4F, "EADS AIRBUS FRANCE" }, + { 0x0D50, "Cleware GmbH" }, + { 0x0D51, "Volex (Asia) Pte Ltd" }, + { 0x0D52, "YAMAHA Motor Co., Ltd" }, + { 0x0D53, "HMI Co., Ltd." }, + { 0x0D54, "HOLON Corporation" }, + { 0x0D55, "ASKA Technologies Inc." }, + { 0x0D56, "AVLAB Technology, Inc." }, + { 0x0D57, "SOLOMON Microtech Ltd." }, + { 0x0D59, "CDS electronics bv" }, + { 0x0D5A, "Hoshino Metal Industries, Ltd." }, + { 0x0D5B, "LOGIC CORPORATION" }, + { 0x0D5C, "Eumitcom Technology Inc." }, + { 0x0D5D, "Telesis Technologies, Inc." }, + { 0x0D5E, "MYACOM LTD" }, + { 0x0D5F, "CSI, Inc." }, + { 0x0D60, "IVL Technologies Ltd." }, + { 0x0D61, "MEILU ELECTRONICS (SHENZHEN) CO., LTD." }, + { 0x0D62, "Darfon Electronics Corp." }, + { 0x0D63, "Fritz Gegauf AG" }, + { 0x0D64, "DXG Technology Corp." }, + { 0x0D65, "KMJP CO., LTD." }, + { 0x0D66, "TMT" }, + { 0x0D67, "Advanet Inc." }, + { 0x0D68, "Super Link Electronics Co., Ltd." }, + { 0x0D69, "NSI" }, + { 0x0D6A, "eMegaTech International Corp." }, + { 0x0D6B, "And-Or Logic" }, + { 0x0D6C, "CANMAX Technology Ltd." }, + { 0x0D6D, "Mitsubishi Elec. Micro-Computer App. Software Co." }, + { 0x0D6E, "Forum Trading Ltd. (UK)" }, + { 0x0D70, "Try Computer Co. LTD." }, + { 0x0D71, "Hirakawa Hewtech Corp." }, + { 0x0D72, "Winmate Communication Inc." }, + { 0x0D73, "Hit's Communications INC." }, + { 0x0D74, "Dreams Come True Co., Ltd." }, + { 0x0D75, "LET'S Corporation, Ltd." }, + { 0x0D76, "MFP Korea, Inc." }, + { 0x0D77, "Power Sentry/Newpoint" }, + { 0x0D78, "Japan Distributor Corporation" }, + { 0x0D79, "Assistive Technology Engineering Lab" }, + { 0x0D7A, "MARX CryptoTech LP" }, + { 0x0D7B, "Wellco Technology Co., Ltd." }, + { 0x0D7C, "Taiwan Line Tek Electronic Co., Ltd." }, + { 0x0D7D, "Add-On Technology Co., Ltd." }, + { 0x0D7E, "American Computer & Digital Components" }, + { 0x0D7F, "Essential Reality LLC" }, + { 0x0D80, "H.R. Silvine Electronics Inc." }, + { 0x0D81, "TechnoVision" }, + { 0x0D83, "Think Outside, Inc." }, + { 0x0D84, "ELECTRO-SYSTEM Co., Ltd." }, + { 0x0D85, "Identix Incorporated" }, + { 0x0D86, "Marconi" }, + { 0x0D87, "Dolby Laboratories Inc." }, + { 0x0D88, "Miyoshi Corp." }, + { 0x0D89, "Oz Software" }, + { 0x0D8A, "KING JIM CO., LTD." }, + { 0x0D8B, "Ascom Telecommunications Ltd." }, + { 0x0D8C, "C-MEDIA ELECTRONICS INC." }, + { 0x0D8D, "Promotion & Display Technology Ltd." }, + { 0x0D8E, "Global Sun Technology Inc." }, + { 0x0D8F, "Pitney Bowes" }, + { 0x0D90, "Sure-Fire Electrical Corporation" }, + { 0x0D91, "ALPHA PROJECT Co., Ltd." }, + { 0x0D92, "Mega & Game" }, + { 0x0D93, "Nishitomo Co., Ltd." }, + { 0x0D94, "Advanced Logic Technology (ALT)" }, + { 0x0D95, "Numonics Corp." }, + { 0x0D96, "Skanhex Technology Inc." }, + { 0x0D97, "Santa Barbara Instrument Group (SBIG)" }, + { 0x0D98, "Mars Semiconductor Corp." }, + { 0x0D99, "Trazer Technologies Inc." }, + { 0x0D9A, "RTX Telecom A/S" }, + { 0x0D9B, "Tat Shing Electrical Co." }, + { 0x0D9C, "Chee Chen Hi-Technology Co., Ltd." }, + { 0x0D9D, "Sanwa Supply Inc" }, + { 0x0D9E, "Avaya" }, + { 0x0D9F, "Powercom Co., Ltd." }, + { 0x0DA0, "Danger Research" }, + { 0x0DA1, "Suzhou Peter's Precise Industrial Co., Ltd." }, + { 0x0DA2, "Land Instruments International Ltd." }, + { 0x0DA3, "Nippon Electro-Sensory Devices Corporation" }, + { 0x0DA4, "POLAR ELECTRO OY" }, + { 0x0DA5, "TOKYO MAGNETIC PRINTING CO., LTD." }, + { 0x0DA6, "Aimtron Technology Corp." }, + { 0x0DA7, "IOGEAR, Inc." }, + { 0x0DA8, "softDSP Co., Ltd." }, + { 0x0DA9, "DigiLife Technology Inc." }, + { 0x0DAA, "Derelek" }, + { 0x0DAB, "Diasonic Technology Co., Ltd." }, + { 0x0DAC, "Smart Card Technology, Inc." }, + { 0x0DAD, "Westover Scientific" }, + { 0x0DAE, "SERIAL SYSTEM LTD" }, + { 0x0DAF, "NXTV, Inc." }, + { 0x0DB0, "Micro-Star International Co., Ltd." }, + { 0x0DB1, "Wen Te Electronics Co., Ltd." }, + { 0x0DB2, "Shian Hwi Plug Parts, Plastic Factory" }, + { 0x0DB3, "Tekram Technology Co. Ltd." }, + { 0x0DB4, "Chung Fu Chen Yeh Enterprise Corporation" }, + { 0x0DB5, "Azio Ltd." }, + { 0x0DB6, "SIMS Valley Co., Ltd." }, + { 0x0DB7, "ELCON Systemtechnik GmbH" }, + { 0x0DB8, "Garear Taiwan Co., Ltd." }, + { 0x0DB9, "EMKAY" }, + { 0x0DBA, "DIGIDESIGN" }, + { 0x0DBB, "Luna Analytics, Inc." }, + { 0x0DBC, "A&D Company, Limited" }, + { 0x0DBD, "Bruker Biospin" }, + { 0x0DBE, "Jiuh Shiuh Precision Industry Co., Ltd." }, + { 0x0DBF, "Jess-Link International" }, + { 0x0DC0, "G7 Solutions" }, + { 0x0DC1, "Tamagawa Seiki Co., Ltd." }, + { 0x0DC3, "Athena Smartcard Solutions Inc." }, + { 0x0DC4, "inXtron, Inc." }, + { 0x0DC5, "SDK Co, Ltd." }, + { 0x0DC6, "Precision Squared Technology Corporation" }, + { 0x0DC7, "First Cable Line, Inc." }, + { 0x0DC8, "WINTEC Corporation" }, + { 0x0DC9, "Arvel Corp." }, + { 0x0DCA, "SMaL Camera Technologies, Inc." }, + { 0x0DCB, "RocketPod, Inc." }, + { 0x0DCC, "Largan Digital" }, + { 0x0DCD, "NetworkFab Corporation" }, + { 0x0DCE, "E-MU Systems, Inc., d.b.a. E-MU/ENSONIQ" }, + { 0x0DCF, "Analytik Jena AG" }, + { 0x0DD0, "Access Solutions" }, + { 0x0DD1, "Contek Electronics Co., Ltd." }, + { 0x0DD2, "Power Quotient International Co., Ltd." }, + { 0x0DD3, "MediaQ" }, + { 0x0DD4, "Custom Engineering SPA" }, + { 0x0DD5, "California Micro Devices" }, + { 0x0DD6, "TECHKON GmbH" }, + { 0x0DD7, "KOCOM CO., LTD" }, + { 0x0DD8, "Netac Technology Co., Ltd." }, + { 0x0DD9, "HighSpeed Surfing" }, + { 0x0DDA, "Integrated Silicon Solution, Inc" }, + { 0x0DDB, "Tamarack Inc." }, + { 0x0DDC, "Takaotec" }, + { 0x0DDD, "Datelink Technology Co., Ltd." }, + { 0x0DDE, "UBICOM, INC" }, + { 0x0DDF, "DriveCam Video Systems" }, + { 0x0DE1, "Vidicode Datacommunicatie BV" }, + { 0x0DE2, "Acom Data" }, + { 0x0DE3, "RFTECH CO., LTD." }, + { 0x0DE4, "Aron Digital Inc." }, + { 0x0DE5, "Secure2Net, Inc. USA" }, + { 0x0DE6, "Dentsply Int'l - Gendex Dental Division" }, + { 0x0DE7, "USBmicro" }, + { 0x0DE8, "Delsy Electronic Components AG" }, + { 0x0DE9, "Technische Industrie TACX BV" }, + { 0x0DEA, "UTECH Electronic (D.G.) Co., Ltd." }, + { 0x0DEB, "Lean Horn Co." }, + { 0x0DEC, "Callserve Communications Ltd." }, + { 0x0DED, "Novasonics" }, + { 0x0DEE, "Lifetime Memory Products" }, + { 0x0DEF, "Full Rise Electronic Co., Ltd." }, + { 0x0DF0, "GE Yokogawa Medical Systems, Ltd." }, + { 0x0DF1, "Envoy Medical Corporation" }, + { 0x0DF2, "Nisshin Electronics Co., Ltd." }, + { 0x0DF3, "VeriTek Co., Ltd." }, + { 0x0DF4, "Net & Sys Co., Ltd." }, + { 0x0DF5, "Yamatake Corporation" }, + { 0x0DF6, "Sitecom Europe B.V." }, + { 0x0DF7, "Mobile Action Technology Inc." }, + { 0x0DF8, "Hoya Computer Co., Ltd." }, + { 0x0DF9, "Nice Fountain Industrial Co., Ltd." }, + { 0x0DFA, "Toyo Networks & System Integration Co., Ltd." }, + { 0x0DFB, "Daisy Technology" }, + { 0x0DFC, "General Touch Technology Co., Ltd." }, + { 0x0DFD, "Suruga Seiki Co., Ltd." }, + { 0x0DFE, "Interactive Metronome" }, + { 0x0DFF, "Deodeo Corporation" }, + { 0x0E00, "Novar GmbH" }, + { 0x0E01, "Sheng Xiang Investment Ltd." }, + { 0x0E02, "Doowon Co., LTD" }, + { 0x0E03, "Nippon Systemware Co., Ltd." }, + { 0x0E04, "PowerCom Technology Co., Ltd." }, + { 0x0E05, "Nordic ID" }, + { 0x0E06, "Personal Telecom, Inc." }, + { 0x0E07, "Viewtek Co., Ltd" }, + { 0x0E08, "Winbest Technology Co., Ltd." }, + { 0x0E09, "Winskon Cabling Specialist Co., Ltd." }, + { 0x0E0A, "JAEIK Information & Communication Co., Ltd." }, + { 0x0E0B, "Fujitsu Denso Ltd." }, + { 0x0E0C, "Gesytec GmbH" }, + { 0x0E0D, "Picoquant GmbH" }, + { 0x0E0E, "Fuji Data System Co., Ltd." }, + { 0x0E0F, "VMWare, Inc." }, + { 0x0E10, "TERUMO Corporation (Suruga Factory)" }, + { 0x0E11, "Neurotec" }, + { 0x0E12, "Danam Communications Inc." }, + { 0x0E13, "Lugh Networks, Inc." }, + { 0x0E14, "Hunter Engineering Co." }, + { 0x0E15, "Tellert Elektronik GmbH" }, + { 0x0E16, "JMTEK, LLC" }, + { 0x0E17, "Walex Electronic Ltd." }, + { 0x0E18, "UNIWIDE Technologies" }, + { 0x0E19, "OeRSTED, Inc." }, + { 0x0E1A, "RDM Corporation" }, + { 0x0E1B, "Crewave Co., Ltd." }, + { 0x0E1C, "Beijing Hi-tech Wealth Software Technology Co." }, + { 0x0E1D, "International Parts & Information Co., Ltd." }, + { 0x0E1E, "Green Hills Software, Inc." }, + { 0x0E1F, "Cabin Industrial Co., Ltd." }, + { 0x0E20, "Pegasus Technologies Ltd." }, + { 0x0E21, "Cowon Systems, Inc." }, + { 0x0E22, "Symbian Ltd." }, + { 0x0E23, "Liou Yuane International Ltd." }, + { 0x0E24, "Samson Electric Wire Co., Ltd." }, + { 0x0E25, "VinChip Systems, Inc." }, + { 0x0E26, "J-Phone East Co., Ltd." }, + { 0x0E27, "Thunder Island Limited" }, + { 0x0E28, "Industrial Control Systems" }, + { 0x0E29, "CB Sciences, Inc." }, + { 0x0E2A, "Flight Link Inc." }, + { 0x0E2B, "Kumamoto Techno Corporation" }, + { 0x0E2C, "Intersoft Electronics N.V." }, + { 0x0E2D, "SKF Condition Monitoring" }, + { 0x0E2E, "Brady Corporation" }, + { 0x0E2F, "Daisen Electronic Industrial Co., Ltd." }, + { 0x0E30, "HeartMath LLC" }, + { 0x0E31, "Biosign" }, + { 0x0E32, "ICONAG - Intelligent Control AG" }, + { 0x0E33, "Luna Innovations, Inc." }, + { 0x0E34, "Micro Computer Control Corp." }, + { 0x0E35, "3Pea Technologies, Inc." }, + { 0x0E36, "TiePie engineering" }, + { 0x0E37, "Alpha Data Corp." }, + { 0x0E38, "Stratitec, Inc." }, + { 0x0E39, "Smart Modular Technologies, Inc." }, + { 0x0E3A, "Neostar Technology Co., Ltd." }, + { 0x0E3B, "Mansella Ltd." }, + { 0x0E3C, "Raytec Electronic Co., Ltd." }, + { 0x0E3D, "Metex Corporation" }, + { 0x0E3E, "Good Technology, Inc." }, + { 0x0E3F, "AM Group Corp." }, + { 0x0E40, "Proteq LTDA" }, + { 0x0E41, "Line 6, Inc." }, + { 0x0E42, "Puretek Industrial Co., Ltd." }, + { 0x0E43, "Holly Lin International Technology Inc." }, + { 0x0E44, "Sun-Riseful Technology Co., Ltd." }, + { 0x0E45, "SafeNet B.V." }, + { 0x0E46, "Delphi Corporation" }, + { 0x0E47, "AMANO Corporation" }, + { 0x0E48, "Julia Corporation Limited" }, + { 0x0E49, "Ingenieurbuero Chanda AG" }, + { 0x0E4A, "Shenzhen Bao Hing Electric Wire & Cable Mfr. Co." }, + { 0x0E4B, "System General Corp." }, + { 0x0E4C, "Radica Games Ltd." }, + { 0x0E4D, "Hong Shi Precision Corp." }, + { 0x0E4E, "Lih Duo Intl. Co., Ltd." }, + { 0x0E4F, "Data Ray Corp." }, + { 0x0E50, "TDi GmbH TechnoData Interware" }, + { 0x0E51, "Therapy Information & Communication System Inc." }, + { 0x0E52, "Mindready Solutions (NI) Ltd." }, + { 0x0E53, "King Tester Corporation" }, + { 0x0E54, "KDE, Inc." }, + { 0x0E55, "Speed Dragon Multimedia Ltd." }, + { 0x0E56, "Cenix Digicom Co., Ltd." }, + { 0x0E57, "Loas Co., Ltd" }, + { 0x0E58, "Technology For Energy Corp." }, + { 0x0E59, "Bourns, Inc." }, + { 0x0E5A, "ACTIVE CO., LTD." }, + { 0x0E5B, "Union Power Information Industrial Co., Ltd." }, + { 0x0E5C, "Shenzhen Bitland Information Technology Co., Ltd." }, + { 0x0E5D, "Neltron Industrial Co., Ltd." }, + { 0x0E5E, "Conwise Technology Co., Ltd." }, + { 0x0E5F, "Entone Technologies" }, + { 0x0E60, "XAVi Technologies Corp." }, + { 0x0E61, "E-Pen InMotion Inc." }, + { 0x0E62, "Shandong CVIC Software Engineering Co., Ltd." }, + { 0x0E63, "SECUREPIA Inc." }, + { 0x0E64, "Nida Corporation" }, + { 0x0E65, "Skycom Tek Co., Ltd" }, + { 0x0E66, "Hawking Technologies, Inc." }, + { 0x0E67, "Fossil" }, + { 0x0E68, "Artec" }, + { 0x0E69, "A Global Partner Corporation" }, + { 0x0E6A, "Megawin Technology Co., Ltd." }, + { 0x0E6B, "DMA Korea Co., Ltd" }, + { 0x0E6C, "E & D Co., Ltd." }, + { 0x0E6D, "Tenovis Business Communication" }, + { 0x0E6E, "Volvo Car Corporation" }, + { 0x0E6F, "Performance Designed Products, LLC" }, + { 0x0E70, "Tokyo Electronic Industry Co, LTD." }, + { 0x0E71, "Schwarzer GmbH" }, + { 0x0E72, "Hsi-Chin Electronics Co., Ltd." }, + { 0x0E73, "MCK Communications, Inc." }, + { 0x0E74, "Accu-Automation Corp." }, + { 0x0E75, "TVS Electronics Limited" }, + { 0x0E76, "Seiko S-Yard Co., Ltd" }, + { 0x0E77, "Weinzierl Engineering GmbH" }, + { 0x0E78, "Ascom Powerline Communications Ltd." }, + { 0x0E79, "ARCHOS SA" }, + { 0x0E7A, "Indocomp Systems Inc." }, + { 0x0E7B, "On-Tech Industry Co., Ltd." }, + { 0x0E7C, "Legend Holdings Limited" }, + { 0x0E7D, "Eutectics Inc." }, + { 0x0E7E, "G.Mate, Inc." }, + { 0x0E7F, "Keysight Technologies, Inc. - AFM division" }, + { 0x0E80, "GateHouse A/S" }, + { 0x0E81, "System Consultants Co., Ltd." }, + { 0x0E82, "Ching Tai Electric Wire & Cable Co., Ltd." }, + { 0x0E83, "Shin An Wire & Cable Co." }, + { 0x0E84, "Elelux International Ltd." }, + { 0x0E85, "Dynavox Systems LLC" }, + { 0x0E86, "Watthour Engineering Co., Inc." }, + { 0x0E87, "Internet Security Co., Ltd" }, + { 0x0E88, "ELBIO" }, + { 0x0E89, "PRT Manufacturing Ltd." }, + { 0x0E8A, "FinePoint Innovations, Inc." }, + { 0x0E8B, "KAO SHIN PRECISION INDUSTRY CO., LTD." }, + { 0x0E8C, "Well Force Electronic Co., Ltd" }, + { 0x0E8D, "MediaTek Inc." }, + { 0x0E8E, "Stuart Tyrrell Developments" }, + { 0x0E8F, "Pansignal Technology Inc." }, + { 0x0E90, "CRU" }, + { 0x0E91, "VTech Engineering Canada Ltd." }, + { 0x0E92, "C'S GLORY ENTERPRISE CO., LTD." }, + { 0x0E93, "eM Technics Co., Ltd." }, + { 0x0E94, "Sirona Dental Systems GmbH" }, + { 0x0E95, "Future Technology Co., Ltd" }, + { 0x0E96, "APLUX Communications Ltd." }, + { 0x0E97, "Fingerworks, Inc." }, + { 0x0E98, "Advanced Analogic Technologies, Inc." }, + { 0x0E99, "Parallel Dice Co., Ltd." }, + { 0x0E9A, "TA HSING INDUSTRIES LTD." }, + { 0x0E9B, "ADTEC CORPORATION" }, + { 0x0E9C, "StreamZap, Inc." }, + { 0x0E9D, "Hitron Technologies, Inc." }, + { 0x0E9E, "Japan System Design Co." }, + { 0x0E9F, "TAMURA CORPORATION" }, + { 0x0EA0, "Ours Technology Inc." }, + { 0x0EA1, "Infinite Communication Terminals Ltd." }, + { 0x0EA2, "Triumph Technology Corp." }, + { 0x0EA3, "Rion Co., Ltd." }, + { 0x0EA4, "Intelligent Hearing Systems" }, + { 0x0EA5, "DATA SYSTEM TECHNOLOGY CO., LTD." }, + { 0x0EA6, "Nihon Computer Co., Ltd." }, + { 0x0EA7, "MSL Enterprises Corp." }, + { 0x0EA8, "CenDyne, Inc." }, + { 0x0EA9, "J&J ENGINEERING INC." }, + { 0x0EAA, "TOKYO SOKKI KENKYUJO CO., LTD." }, + { 0x0EAB, "Yiso Telecom" }, + { 0x0EAC, "ALCATech GmbH" }, + { 0x0EAD, "HUMAX Co., Ltd." }, + { 0x0EAE, "Alcon Labs" }, + { 0x0EAF, "Grandex International Corporation" }, + { 0x0EB0, "Amigo Technology Co., Ltd." }, + { 0x0EB1, "WIS Technologies, Inc." }, + { 0x0EB2, "Y-S ELECTRONIC CO., LTD." }, + { 0x0EB3, "Saint Technology Corp." }, + { 0x0EB4, "IPLAN Inc." }, + { 0x0EB5, "@pos.com" }, + { 0x0EB6, "GAMEPARK, Inc." }, + { 0x0EB7, "Endor AG" }, + { 0x0EB8, "Mettler-Toledo (Albstadt) GmbH" }, + { 0x0EB9, "SKY Electronics" }, + { 0x0EBA, "iWOW Connections Pte Ltd" }, + { 0x0EBB, "Thermo Nicolet Corp." }, + { 0x0EBC, "CHOIS Technology" }, + { 0x0EBD, "Kyowa Electronics Co., Ltd." }, + { 0x0EBE, "VWEB Corporation" }, + { 0x0EBF, "Omega Technology Inc." }, + { 0x0EC0, "LHI Technology (China) Co., Ltd." }, + { 0x0EC1, "ABIT Computer Corporation" }, + { 0x0EC2, "Sweetray Industrial Ltd." }, + { 0x0EC3, "Axell Corporation" }, + { 0x0EC4, "Ballracing Developments Ltd." }, + { 0x0EC5, "GT Information System Co., Ltd." }, + { 0x0EC6, "InnoVISION Multimedia Limited" }, + { 0x0EC7, "Theta Link Corporation" }, + { 0x0EC8, "Mitechno Co., Ltd." }, + { 0x0EC9, "HemoCue AB" }, + { 0x0ECA, "Mit System Co., Ltd." }, + { 0x0ECB, "Harman Kardon" }, + { 0x0ECC, "Samsung SDS" }, + { 0x0ECD, "Lite-On IT Corp." }, + { 0x0ECE, "TaiSol Electronics Co., Ltd." }, + { 0x0ECF, "Phogenix Imaging, LLC" }, + { 0x0ED0, "LANergy Limited" }, + { 0x0ED1, "Tai Guen Enterprise Co., Ltd." }, + { 0x0ED2, "Kyoto Micro Computer Co., LTD." }, + { 0x0ED3, "Wing-Tech Enterprise Co., Ltd." }, + { 0x0ED4, "Ross Video" }, + { 0x0ED5, "ChronoLogic Pty. Ltd." }, + { 0x0ED6, "TECHNOS JAPAN Co., LTD." }, + { 0x0ED7, "COSMODOG, LTD." }, + { 0x0ED8, "ASAHI SPECTRA CO., LTD." }, + { 0x0ED9, "Holy Stone Enterprise Co., Ltd." }, + { 0x0EDA, "NORITAKE ITRON CORPORATION" }, + { 0x0EDB, "AboveTech, Inc." }, + { 0x0EDC, "GALTRONICS" }, + { 0x0EDD, "KOWA COMPANY, LTD." }, + { 0x0EDE, "TOD Co., Ltd." }, + { 0x0EDF, "e-MDT Co., Ltd." }, + { 0x0EE0, "SHIMA SEIKI MFG., LTD." }, + { 0x0EE1, "Sarotech Co., Ltd." }, + { 0x0EE2, "AMI Semiconductor Inc." }, + { 0x0EE3, "ComTrue Technology Corporation (Taiwan)" }, + { 0x0EE4, "Sunrich Technology (H.K.) Ltd." }, + { 0x0EE5, "Medical Graphics Corporation" }, + { 0x0EE6, "Takacom Corporation" }, + { 0x0EE7, "Furuno Electric Co., Ltd." }, + { 0x0EE8, "Triz Communications Group" }, + { 0x0EE9, "JPK Systems Limited" }, + { 0x0EEA, "William Demant Holding A/S" }, + { 0x0EEB, "Design Of Systems On Silicon, S.A. (DS2)" }, + { 0x0EEC, "Tritek Co., Ltd." }, + { 0x0EED, "CCP Co., Ltd." }, + { 0x0EEE, "Digital STREAM Technology, Inc." }, + { 0x0EEF, "eGalax Inc." }, + { 0x0EF0, "Hitachi Cable, Ltd." }, + { 0x0EF1, "Aichi Micro Intelligent Corporation" }, + { 0x0EF2, "I/OMAGIC CORPORATION" }, + { 0x0EF3, "Lynn Products, Inc." }, + { 0x0EF4, "DSI Datotech" }, + { 0x0EF5, "PointChips" }, + { 0x0EF6, "Yield Microelectronics Corp." }, + { 0x0EF7, "SM Tech Co., Ltd." }, + { 0x0EF8, "ECT Inc." }, + { 0x0EF9, "eHome TV, Inc. DBA Fuze3 Technologies" }, + { 0x0EFA, "Corepro Entertainment" }, + { 0x0EFB, "ARKRAY, Inc." }, + { 0x0EFC, "ELMEX COMPANY Ltd." }, + { 0x0EFD, "Oasis Semiconductor" }, + { 0x0EFE, "WEM TECHNOLOGY INC." }, + { 0x0EFF, "CSIRO-TIP" }, + { 0x0F00, "ndd Medizintechnik AG" }, + { 0x0F01, "EXPAN Electronics Co., Ltd." }, + { 0x0F02, "MobileAria" }, + { 0x0F03, "Jet Power Technology Co., Ltd." }, + { 0x0F04, "Softlok International Limited" }, + { 0x0F05, "Quanta Network Systems Inc." }, + { 0x0F06, "Visual Frontier Precision Corp." }, + { 0x0F07, "Pakon" }, + { 0x0F08, "CSL Wire & Plug (Shen Zhen) Company" }, + { 0x0F09, "Sandel Arionics Inc." }, + { 0x0F0B, "Great Computer Corporation" }, + { 0x0F0C, "CAS Corporation" }, + { 0x0F0D, "HORI CO., LTD." }, + { 0x0F0E, "Energyfull & Hi-Top International Ltd." }, + { 0x0F0F, "NANOPTIX INC." }, + { 0x0F10, "Personal Information Systems Co., Ltd." }, + { 0x0F11, "Leybold Didactic GMBH" }, + { 0x0F12, "MARS ENGINEERING CORPORATION" }, + { 0x0F13, "Acetek Technology Co., Ltd." }, + { 0x0F14, "XIRING" }, + { 0x0F15, "PlayMore Corporation" }, + { 0x0F16, "GLOBAL VIEW CO. LTD." }, + { 0x0F17, "Correlant Communications" }, + { 0x0F18, "Finger Lakes Instrumentation, LLC" }, + { 0x0F19, "ORACOM CO., Ltd." }, + { 0x0F1A, "General Information Systems Ltd." }, + { 0x0F1B, "Onset Computer Corporation" }, + { 0x0F1C, "Funai Electric Co., Ltd." }, + { 0x0F1D, "Iwill Corporation" }, + { 0x0F1E, "INVAIR Technologies AG" }, + { 0x0F1F, "Laxtha" }, + { 0x0F20, "GENNUM CORPORATION" }, + { 0x0F21, "IOI Technology Corporation" }, + { 0x0F22, "SENIOR INDUSTRIES, INC." }, + { 0x0F23, "Leader Tech Manufacturer Co., Ltd" }, + { 0x0F24, "FLEX-P INDUSTRIES SDN.BHD." }, + { 0x0F25, "Primera Technology Inc." }, + { 0x0F26, "B.G. Technologies, Inc." }, + { 0x0F27, "Alpes DEIS" }, + { 0x0F28, "ESEC SA" }, + { 0x0F29, "TIPTEL AG" }, + { 0x0F2A, "Marconi Data Systems" }, + { 0x0F2B, "XEMICS SA" }, + { 0x0F2D, "ViPower, Inc." }, + { 0x0F2E, "Good Man Corporation" }, + { 0x0F2F, "Priva Design Services" }, + { 0x0F30, "Jess Technology Co., Ltd." }, + { 0x0F31, "Chrysalis Development" }, + { 0x0F32, "YFC-BonEagle Electric Co., Ltd." }, + { 0x0F33, "Futek Electronics, Co., Ltd." }, + { 0x0F34, "Hokuto Denshi Co., Ltd." }, + { 0x0F35, "Kinpo Electronics, Inc." }, + { 0x0F36, "Philips Medical Systems Ultrasound" }, + { 0x0F37, "Kokuyo Co., Ltd." }, + { 0x0F38, "Nien-Yi Industrial Corp." }, + { 0x0F39, "Heng Yu Technology (HK) Ltd." }, + { 0x0F3A, "Aidensi Giken" }, + { 0x0F3B, "IR-LINK" }, + { 0x0F3C, "Numesa, Inc." }, + { 0x0F3D, "AirPrime Inc." }, + { 0x0F3E, "Aastra Broadband" }, + { 0x0F3F, "FEI Electron Optics B.V." }, + { 0x0F40, "Denver Instrument Company" }, + { 0x0F41, "RDC Semiconductor Co., Ltd." }, + { 0x0F42, "Nital Consulting Services, Inc." }, + { 0x0F43, "LiteON Semiconductor Corp." }, + { 0x0F44, "Polhemus Incorporated" }, + { 0x0F45, "International Road Dynamics" }, + { 0x0F46, "KIHOKU Electronic Co., Ltd." }, + { 0x0F47, "SN Systems Ltd." }, + { 0x0F48, "Durand Interstellar, Inc." }, + { 0x0F49, "Evolis" }, + { 0x0F4A, "Planmeca Oy" }, + { 0x0F4B, "St. John Technology Co., Ltd." }, + { 0x0F4C, "WORLDWIDE CABLE OPTO CORP." }, + { 0x0F4D, "Microtune, Inc." }, + { 0x0F4E, "Freedom Scientific" }, + { 0x0F4F, "INVENTEL" }, + { 0x0F50, "LeadingSpect Corporation" }, + { 0x0F51, "Zeta Broadband Inc." }, + { 0x0F52, "Wing Kei Electrical Production Ltd." }, + { 0x0F53, "Taiyo Cable (Dongguan) Co. Ltd." }, + { 0x0F54, "Kawai Musical Instruments Mfg. Co., Ltd." }, + { 0x0F55, "AmbiCom, Inc." }, + { 0x0F56, "SecureTech Corp." }, + { 0x0F57, "WavePlus Tech. Co., Ltd." }, + { 0x0F58, "JASCO Corporation" }, + { 0x0F59, "NCI/Newcomb Company, Inc." }, + { 0x0F5A, "Cogency Semiconductor Inc." }, + { 0x0F5B, "Ritech International Ltd." }, + { 0x0F5C, "PRAIRIECOMM, INC." }, + { 0x0F5D, "NewAge International, LLC" }, + { 0x0F5E, "LEADER ELECTRONICS CORP." }, + { 0x0F5F, "Key Technology Corporation" }, + { 0x0F60, "GuangZhou Chief Tech Electronic Technology Co. Ltd." }, + { 0x0F61, "Varian Inc." }, + { 0x0F62, "Acrox Technologies Co., Ltd." }, + { 0x0F63, "Leapfrog Enterprises" }, + { 0x0F64, "ZAE Research, Inc." }, + { 0x0F65, "Dataflex Design Communications Limited" }, + { 0x0F66, "Toshiba Global Commerce Solutions" }, + { 0x0F67, "Quantum3D, Inc." }, + { 0x0F68, "UQUEST, LTD." }, + { 0x0F69, "DIONEX CORPORATION" }, + { 0x0F6A, "Vibren Technologies Inc." }, + { 0x0F6B, "OHM ELECTRIC CO., LTD." }, + { 0x0F6C, "DnC Tech., Inc." }, + { 0x0F6D, "WillPoD Co., Ltd." }, + { 0x0F6E, "INTELLIGENT SYSTEMS CO., LTD." }, + { 0x0F6F, "Samtec GmbH" }, + { 0x0F70, "YOZAN Inc." }, + { 0x0F71, "Systems Integration Solutions Inc." }, + { 0x0F72, "Robert Bosch GmbH - Chassis Systems Control" }, + { 0x0F73, "DFI" }, + { 0x0F74, "KOSUGI GIKEN Co, Ltd." }, + { 0x0F75, "Future Internet" }, + { 0x0F76, "Vacon Plc" }, + { 0x0F77, "Fasstech" }, + { 0x0F78, "Guntermann & Drunck GmbH" }, + { 0x0F79, "Transonic Systems, Inc." }, + { 0x0F7A, "EE Tools, Inc." }, + { 0x0F7B, "Hivertec Inc." }, + { 0x0F7C, "DQ Technology, Inc." }, + { 0x0F7D, "NetBotz, Inc." }, + { 0x0F7E, "Fluke" }, + { 0x0F7F, "Lansmont Corporation" }, + { 0x0F80, "OCULUS Optikgeraete GmbH" }, + { 0x0F81, "DP Computers Pte. Ltd." }, + { 0x0F82, "IMedia Semiconductor Corporation" }, + { 0x0F83, "Ernst Reiner GmbH & Co. KG" }, + { 0x0F84, "A.E.B. S.R.L." }, + { 0x0F85, "IDX Company, Ltd." }, + { 0x0F86, "Cedar Audio Limited" }, + { 0x0F87, "HUMANDATA LTD." }, + { 0x0F88, "VTech Holdings Ltd." }, + { 0x0F89, "Leading Edge Co., Ltd." }, + { 0x0F8A, "Centro De Tecnologia de las Comunicaciones, S.A." }, + { 0x0F8B, "Yazaki Corporation" }, + { 0x0F8C, "Young Generation International Corp." }, + { 0x0F8D, "Uniwill Computer Corp." }, + { 0x0F8E, "Kingnet Technology Co., Ltd." }, + { 0x0F8F, "SOMA NETWORKS" }, + { 0x0F90, "Quad Engineering Solutions LLC" }, + { 0x0F91, "UNIPULSE Corporation" }, + { 0x0F92, "JASTEC CO., LTD." }, + { 0x0F93, "Sondex Limited" }, + { 0x0F94, "FALCOM GmbH" }, + { 0x0F95, "TOKYO SOKUSHIN CO., LTD." }, + { 0x0F96, "NEC-Mitsubishi Electric Visual Systems Corp." }, + { 0x0F97, "CviLux Corporation" }, + { 0x0F98, "CYBERBANK CORP." }, + { 0x0F99, "Biopia Co., Ltd." }, + { 0x0F9A, "Sistel S.R.L." }, + { 0x0F9B, "G-Card Technology Co., Ltd." }, + { 0x0F9C, "HYUN WON INC." }, + { 0x0F9D, "Opteon Corporation" }, + { 0x0F9E, "Lucent Technologies" }, + { 0x0F9F, "Racewood Technology Co., Ltd." }, + { 0x0FA0, "TRITTON TECHNOLOGIES" }, + { 0x0FA1, "AIJI System Co., Ltd." }, + { 0x0FA2, "TAG Systems Racing Products, Inc." }, + { 0x0FA3, "Chief Land Electronic Co., Ltd." }, + { 0x0FA4, "ATL Technology" }, + { 0x0FA5, "SOTEC CO., LTD." }, + { 0x0FA6, "CMD AG" }, + { 0x0FA7, "EPOX COMPUTER CO., LTD." }, + { 0x0FA8, "Logic Controls, Inc." }, + { 0x0FA9, "Shenzhen Motion Control Technology Co., Ltd." }, + { 0x0FAA, "Changrime Telecom Co., Ltd." }, + { 0x0FAB, "ISZ" }, + { 0x0FAC, "Current Stone Co., Ltd." }, + { 0x0FAD, "Ultravision Ltd." }, + { 0x0FAE, "Redsun Technology Corp." }, + { 0x0FAF, "Winpoint Electronic Corp." }, + { 0x0FB0, "Haurtian Wire & Cable Co., Ltd." }, + { 0x0FB1, "SuperGate Technologies" }, + { 0x0FB2, "Conteck Co., Ltd." }, + { 0x0FB3, "SYMAGERY MICROSYSTEMS INC." }, + { 0x0FB4, "Smiths Detection" }, + { 0x0FB5, "NIHON DENJI SOKKI CO., LTD." }, + { 0x0FB6, "Heber Ltd." }, + { 0x0FB7, "East Press Co., Ltd." }, + { 0x0FB8, "Wistron Corporation" }, + { 0x0FB9, "AACOM CORPORATION" }, + { 0x0FBA, "SAN SHING ELECTRONICS CO., LTD.." }, + { 0x0FBB, "Bitwise Systems, Inc." }, + { 0x0FBC, "Schick Technologies" }, + { 0x0FBD, "Siblings Investment Inc. (dba vantecusa)" }, + { 0x0FBE, "Applied Diabetes Research, Inc." }, + { 0x0FBF, "Certifiable Innovations" }, + { 0x0FC0, "NUDIAN ELECTRON CO., LTD." }, + { 0x0FC1, "MITAC INTERNATIONAL CORP." }, + { 0x0FC2, "PLUG AND JACK INDUSTRIAL INC." }, + { 0x0FC3, "BRAINTREE COMMUNICATIONS" }, + { 0x0FC4, "Yamato Electric Industry Co., Ltd." }, + { 0x0FC5, "Delcom Engineering" }, + { 0x0FC6, "Dataplus Supplies, Inc." }, + { 0x0FC7, "BES Technology Group" }, + { 0x0FC8, "Phoenix Co., Ltd." }, + { 0x0FC9, "Tecom Co., Ltd." }, + { 0x0FCA, "BlackBerry Limited" }, + { 0x0FCB, "Suzuken Co., Ltd." }, + { 0x0FCC, "Marushin-Denshi Co., Ltd." }, + { 0x0FCD, "Centurion, Inc." }, + { 0x0FCE, "Sony Mobile Communications" }, + { 0x0FCF, "Dynastream Innovations Inc." }, + { 0x0FD0, "2L international B.V." }, + { 0x0FD1, "Giant Electronics Ltd." }, + { 0x0FD2, "SEAC BANCHE S.P.A." }, + { 0x0FD3, "Marconi Applied Technologies Ltd." }, + { 0x0FD4, "Tenovis GmbH & Co., KG" }, + { 0x0FD5, "Direct Access Technology, Inc." }, + { 0x0FD6, "Mexmal Mayorista S.A. de C.V." }, + { 0x0FD7, "Jeulin S.A." }, + { 0x0FD8, "LARSEN & BRUSGAARD" }, + { 0x0FD9, "El Gato Software LLC" }, + { 0x0FDA, "Quantec Networks GmbH" }, + { 0x0FDB, "Comtech EF Data" }, + { 0x0FDC, "Micro Plus" }, + { 0x0FDD, "Yuyama Mfg. Co., Ltd." }, + { 0x0FDE, "IDT DATA SYSTEM LIMITED" }, + { 0x0FDF, "Foveon Inc." }, + { 0x0FE0, "AONEPROTECH Co., Ltd." }, + { 0x0FE1, "MADWAVES ApS" }, + { 0x0FE2, "Air Techniques, Inc." }, + { 0x0FE3, "ACCEL CORP." }, + { 0x0FE4, "IN-TECH ELECTRONICS LIMITED" }, + { 0x0FE5, "TC&C ELECTRONIC CO.,LTD (SUNTECC, INC.)" }, + { 0x0FE6, "Sospita ASA" }, + { 0x0FE7, "Mitutoyo Corporation" }, + { 0x0FE8, "TurboComm Tech. Inc." }, + { 0x0FE9, "DVICO Inc." }, + { 0x0FEA, "United Computer Accessories" }, + { 0x0FEB, "CRS ELECTRONIC CO., LTD." }, + { 0x0FEC, "UMC Electronics Co., Ltd." }, + { 0x0FED, "ACCESS CO., LTD." }, + { 0x0FEE, "Xsido Corporation" }, + { 0x0FEF, "MJ RESEARCH, INC." }, + { 0x0FF0, "Physical Electronics" }, + { 0x0FF1, "Minato Electronics, Inc." }, + { 0x0FF2, "EZMAX CO., LTD." }, + { 0x0FF3, "Dimentor" }, + { 0x0FF4, "POLYMATECH CO., LTD." }, + { 0x0FF5, "OYO-ELECTRIC CO., LTD." }, + { 0x0FF6, "Core Valley Co., Ltd." }, + { 0x0FF7, "CHI SHING COMPUTER ACCESSORIES CO., LTD." }, + { 0x0FF8, "iXs Research Corporation" }, + { 0x0FF9, "FHC., Inc. Frederick Haer & Co." }, + { 0x0FFA, "ELENTEC CO., LTD." }, + { 0x0FFB, "Avail Corporation" }, + { 0x0FFC, "Clavia Digital Musical Instruments AB" }, + { 0x0FFD, "AKATSUKI ELECTRIC MFG. CO., LTD." }, + { 0x0FFE, "ASKA Corporation" }, + { 0x0FFF, "Aopen Inc." }, + { 0x1000, "Speed Tech Corp." }, + { 0x1001, "Ritronics Components (S) Pte. Ltd." }, + { 0x1002, "Spa Design Ltd." }, + { 0x1003, "SIGMA CORPORATION" }, + { 0x1004, "LG Electronics Inc." }, + { 0x1005, "Apacer Technology Inc." }, + { 0x1006, "Reign Com Ltd." }, + { 0x1007, "Samphone Electronic Co., Ltd." }, + { 0x1008, "Futaba Corporation" }, + { 0x1009, "Lumanate, Inc." }, + { 0x100A, "AVC Technology" }, + { 0x100B, "Chou Chin Industrial Co., Ltd." }, + { 0x100C, "eMachines, inc" }, + { 0x100D, "NETOPIA, INC." }, + { 0x100E, "North American Pacific Industries, Corp." }, + { 0x100F, "Trek Inc." }, + { 0x1010, "FUKUDA DENSHI CO., LTD." }, + { 0x1011, "Mobile Media Tech." }, + { 0x1012, "SDKM Fibres, Wires & Cables Berhad" }, + { 0x1013, "TST-Touchless Sensor Technology AG" }, + { 0x1014, "Densitron Technologies PLC" }, + { 0x1015, "Softronics Pty. Ltd." }, + { 0x1016, "Xiamen Hung's Enterprise Co., Ltd." }, + { 0x1017, "SPEEDY INDUSTRIAL SUPPLIES PTE. LTD." }, + { 0x1018, "Mindtell Inc." }, + { 0x1019, "Fostex Corporation" }, + { 0x101A, "Annecy Electronique" }, + { 0x101B, "Digital Innovations" }, + { 0x101C, "Teradyne Diagnostic Solutions Ltd." }, + { 0x101D, "Aerospace Information Corporation Limited" }, + { 0x101E, "Fronius International GmbH" }, + { 0x101F, "Pocketec" }, + { 0x1020, "Paten Wireless Technology Inc." }, + { 0x1021, "Time Management, Inc." }, + { 0x1022, "Shinko Shoji Co., Ltd." }, + { 0x1023, "CHRONIX Inc." }, + { 0x1024, "ASEC CO., LTD." }, + { 0x1025, "Technology Testing Lab" }, + { 0x1026, "Newly Corporation" }, + { 0x1027, "Time Domain" }, + { 0x1028, "Inovys Corporation" }, + { 0x1029, "Atlantic Coast Telesys" }, + { 0x102A, "RAMOS Technology Co., Ltd." }, + { 0x102B, "Infotronic America, Inc." }, + { 0x102C, "Etoms Electronics Corp." }, + { 0x102D, "Winic Corporation" }, + { 0x102E, "Binstead Systems Ltd." }, + { 0x102F, "WENZHOU YIHUA CONNECTOR CO.,LTD." }, + { 0x1030, "Asoka USA Corporation" }, + { 0x1031, "Comax Technology Inc." }, + { 0x1032, "C-One Technology Corp." }, + { 0x1033, "Nucam Corporation" }, + { 0x1034, "Teramecs Co., Ltd." }, + { 0x1035, "Cyber Solid Laboratory" }, + { 0x1036, "ELLAB A/S" }, + { 0x1037, "Red Lion Controls LP" }, + { 0x1038, "SteelSeries ApS" }, + { 0x1039, "devolo AG" }, + { 0x103A, "I+ME ACTIA GmbH" }, + { 0x103B, "Quatographic AG" }, + { 0x103C, "AMX Corp." }, + { 0x103D, "Stanton Magnetics, Inc." }, + { 0x103E, "Thurlby-Thandar Instruments Ltd." }, + { 0x103F, "Tectech inc." }, + { 0x1040, "Valiant Technology Ltd." }, + { 0x1041, "Kongsberg Defence Communications AS" }, + { 0x1042, "CARDIO SISTEMAS COML. INDL. LTDA." }, + { 0x1043, "iCreate Technologies Corporation" }, + { 0x1044, "Chu Yuen Enterprise Co., Ltd." }, + { 0x1045, "Transiciel Technologies" }, + { 0x1046, "Hitachi Asahi Electronics Co., Ltd." }, + { 0x1047, "HOYA CORPORATION Vision Care Company" }, + { 0x1048, "Targus International LLC" }, + { 0x1049, "Studio Technologies, Inc." }, + { 0x104A, "WACOH Corporation" }, + { 0x104B, "CSM GmbH" }, + { 0x104C, "AMCO TEC International Inc." }, + { 0x104D, "Newport Corporation" }, + { 0x104E, "Halliburton Energy Services" }, + { 0x104F, "W B Electronics" }, + { 0x1050, "Yubico AB" }, + { 0x1051, "Nippon Printer Engineering Inc." }, + { 0x1052, "U-Medica Inc." }, + { 0x1053, "Immanuel Electronics Co., Ltd." }, + { 0x1054, "BMS International Beheer N.V." }, + { 0x1055, "Complex Micro Interconnection Co., Ltd." }, + { 0x1056, "Hsin Chen Ent Co., Ltd." }, + { 0x1057, "ON Semiconductor" }, + { 0x1058, "Western Digital, Branded" }, + { 0x1059, "Giesecke & Devrient GmbH" }, + { 0x105A, "DDS, Inc." }, + { 0x105B, "TOKIWA WEST Co., Ltd." }, + { 0x105C, "Freeway Electronic Wire & Cable (Dongguan) Co., Ltd." }, + { 0x105D, "Delkin Devices, Inc." }, + { 0x105E, "Valence Semiconductor Design Limited" }, + { 0x105F, "Chin Shong Enterprise Co., Ltd." }, + { 0x1060, "Easthome Industrial Co., Ltd." }, + { 0x1061, "Cardinal Components Inc." }, + { 0x1062, "Sumitomo Electric Industries, Ltd." }, + { 0x1063, "LPKF Laser & Electronics AG" }, + { 0x1064, "INNOPLUS Co., Ltd." }, + { 0x1065, "ImageQuest Co., Ltd." }, + { 0x1066, "Eten Information Systems Co., Ltd." }, + { 0x1067, "L-3 Communications" }, + { 0x1068, "Micropi Elettronica" }, + { 0x1069, "Easy Digital Concept" }, + { 0x106A, "Loyal Legend Limited" }, + { 0x106B, "MED Associates Inc. , sue@med-associates.com" }, + { 0x106C, "Curitel Communications, Inc." }, + { 0x106D, "San Chieh Manufacturing Ltd." }, + { 0x106E, "ConectL" }, + { 0x106F, "Money Controls" }, + { 0x1070, "TAKAMISAWA CYBERNETICS CO., LTD." }, + { 0x1071, "Paxton Access Ltd." }, + { 0x1072, "FDI Matelec" }, + { 0x1073, "Lifetron Co., Ltd." }, + { 0x1074, "TECHNO SOFT SYSTEMNICS INC." }, + { 0x1075, "TOKYO KEIKI INC." }, + { 0x1076, "GCT Semiconductor, Inc." }, + { 0x1077, "VoiceBox Technologies Inc." }, + { 0x1078, "Maycom Co., Ltd." }, + { 0x1079, "Suisei Electronics System Co., Ltd." }, + { 0x107A, "Optionexist Limited" }, + { 0x107B, "X E Systems Inc." }, + { 0x107C, "Whelen Engineering Company Inc." }, + { 0x107D, "Arlec Australia Limited" }, + { 0x107E, "MIDORIYA ELECTRIC CO., LTD." }, + { 0x107F, "KidzMouse, Inc." }, + { 0x1080, "Musetel Co., Ltd." }, + { 0x1081, "VG Electracon, Inc." }, + { 0x1082, "Shin-Etsukaken Co., Ltd." }, + { 0x1083, "CANON ELECTRONICS INC." }, + { 0x1084, "PANTECH CO., LTD." }, + { 0x1085, "Datalaster" }, + { 0x1086, "Smart System Inc." }, + { 0x1087, "Shanghai Ewaytek Co., Ltd." }, + { 0x1088, "Archtek Telecom Co." }, + { 0x1089, "On Track Innovations Ltd." }, + { 0x108A, "Chloride Power Protection" }, + { 0x108B, "Grand-tek Technology Co., Ltd." }, + { 0x108C, "Robert Bosch GmbH" }, + { 0x108D, "Mitsui Zosen Systems Research Inc." }, + { 0x108E, "Lotes Co., Ltd." }, + { 0x108F, "HIOKI E.E. CORPORATION" }, + { 0x1090, "DSP Research Inc." }, + { 0x1091, "DR. JOHANNES HEIDENHAIN GmbH" }, + { 0x1092, "TOPDEK Semiconductor Inc." }, + { 0x1093, "SongPro, Inc." }, + { 0x1094, "NextEngine, Inc." }, + { 0x1095, "Good Work Systems" }, + { 0x1096, "NIO Corporation" }, + { 0x1097, "Computational Systems Incorporated" }, + { 0x1098, "Raytek Corp." }, + { 0x1099, "Surface Optics Corporation" }, + { 0x109A, "DATASOFT Systems GmbH" }, + { 0x109B, "Qingdao Hisense Communication Co., Ltd." }, + { 0x109C, "Electronic Trade Solutions Ltd." }, + { 0x109D, "NAVIUS CO., LTD." }, + { 0x109E, "Finger System Inc." }, + { 0x109F, "eSOL Co., Ltd." }, + { 0x10A0, "HIROTECH, INC." }, + { 0x10A1, "target-systemelectronic gmbh" }, + { 0x10A2, "HYUNDAI NETWORKS, INC." }, + { 0x10A3, "MITSUBISHI MATERIALS CORPORATION" }, + { 0x10A4, "Frontier Silicon Ltd." }, + { 0x10A5, "FINGERPRINT CARDS AB" }, + { 0x10A6, "SKYUP TECHNOLOGY CORPORATION" }, + { 0x10A7, "3i techs Development Corp" }, + { 0x10A8, "Imaging Devices, Inc." }, + { 0x10A9, "SK Teletech Co., Ltd." }, + { 0x10AA, "Cables To Go" }, + { 0x10AB, "Universal Global Scientific Industrial Co., Ltd." }, + { 0x10AC, "Honeywell, Inc." }, + { 0x10AD, "Impact Instrumentation Inc." }, + { 0x10AE, "Princeton Technology Corp." }, + { 0x10AF, "Liebert Corporation" }, + { 0x10B0, "IPmental Inc." }, + { 0x10B1, "Safe Valley Inc." }, + { 0x10B2, "Data East Corporation" }, + { 0x10B3, "Roke Manor Research Limited" }, + { 0x10B4, "Guardtec, Inc." }, + { 0x10B5, "Comodo" }, + { 0x10B6, "Dynojet Research, Inc." }, + { 0x10B7, "VSM Medtech Ltd." }, + { 0x10B8, "DIBCOM" }, + { 0x10B9, "Prime Electronics & Satellitics, Inc." }, + { 0x10BA, "Dong-Guan Sintai Optical Co., Ltd." }, + { 0x10BB, "TM Technology Inc." }, + { 0x10BC, "Dinging Technology Co., Ltd." }, + { 0x10BD, "TMT TECHNOLOGY, INC." }, + { 0x10BE, "KBM Electronic System Design" }, + { 0x10BF, "Smarthome" }, + { 0x10C0, "SougaSoft Co., Ltd." }, + { 0x10C1, "Kyokuto Electric Co., Ltd." }, + { 0x10C2, "Phasespace, Inc." }, + { 0x10C3, "Universal Laser Systems" }, + { 0x10C4, "Silicon Laboratories, Inc." }, + { 0x10C5, "Sanei Electric Inc." }, + { 0x10C6, "Intec, Inc." }, + { 0x10C7, "Touchstone Technology Co., Ltd." }, + { 0x10C8, "SIGMACOM CO., LTD." }, + { 0x10C9, "ZUKEN Inc." }, + { 0x10CA, "Xrosstech, Inc." }, + { 0x10CB, "eratech" }, + { 0x10CC, "GBM Connector Co., Ltd." }, + { 0x10CD, "Kycon Inc." }, + { 0x10CE, "Shinko Electric Co., Ltd." }, + { 0x10CF, "Velleman Components" }, + { 0x10D0, "Tokai University Educational System" }, + { 0x10D1, "HBM GmbH" }, + { 0x10D2, "Adams IT Services" }, + { 0x10D3, "Trimos SA" }, + { 0x10D4, "Man Boon Manufactory Ltd." }, + { 0x10D5, "Uni Class Technology Co., Ltd." }, + { 0x10D6, "Actions Semiconductor Co., Ltd." }, + { 0x10D7, "Array Corporation" }, + { 0x10D8, "ACTIKEY S.A." }, + { 0x10D9, "Tecnova Corporation" }, + { 0x10DA, "HOWTEL CO., LTD." }, + { 0x10DB, "Prior Scientific Instruments Ltd." }, + { 0x10DC, "Evolve Communications" }, + { 0x10DD, "VerNova, Inc." }, + { 0x10DE, "Authenex, Inc." }, + { 0x10DF, "In-Win Development Inc." }, + { 0x10E0, "Bella Corporation" }, + { 0x10E1, "CABLEPLUS LTD." }, + { 0x10E2, "Nada Electronics, Ltd." }, + { 0x10E3, "tec5 AG" }, + { 0x10E4, "Trans-Lux Corporation & Subsidiaries" }, + { 0x10E5, "MACTek" }, + { 0x10E6, "Altotec Hard- und Software GmbH" }, + { 0x10E7, "dSPACE GmbH" }, + { 0x10E8, "Kumahira Co., Ltd." }, + { 0x10E9, "XIA LLC" }, + { 0x10EA, "ELITRONIC s.r.o." }, + { 0x10EB, "FREEBOX SA" }, + { 0x10EC, "Vast Technologies Inc." }, + { 0x10ED, "KDS USA, Inc." }, + { 0x10EE, "Compuprint" }, + { 0x10EF, "Integrity Instruments Inc." }, + { 0x10F0, "Etronics Corp." }, + { 0x10F1, "Inventec Multimedia & Telecom Corp." }, + { 0x10F2, "Autonics Co., Ltd." }, + { 0x10F3, "Vercel Development Inc." }, + { 0x10F4, "INcoder Technology CO., Ltd." }, + { 0x10F5, "Voyetra Turtle Beach, Inc." }, + { 0x10F6, "IMAGENICS Co., Ltd." }, + { 0x10F7, "Hando Computer Co., Ltd" }, + { 0x10F8, "CESYS GmbH" }, + { 0x10F9, "NSD Corporation" }, + { 0x10FA, "CHINO Corporation" }, + { 0x10FB, "Pictos Technologies, Inc." }, + { 0x10FC, "MICRELEC" }, + { 0x10FD, "Animation Technologies Inc." }, + { 0x10FE, "Thrane & Thrane A/S" }, + { 0x10FF, "Bellwave" }, + { 0x1100, "VirTouch Ltd." }, + { 0x1101, "EASYPASS INDUSTRIAL CO., LTD." }, + { 0x1102, "Instrument Systems GmbH" }, + { 0x1103, "Brain Products GmbH" }, + { 0x1104, "TOA Corporation" }, + { 0x1105, "MAP Medizin-Technologie GmbH" }, + { 0x1106, "OrangeHouse Co., Ltd." }, + { 0x1107, "CreamWare GmbH" }, + { 0x1108, "BRIGHTCOM TECHNOLOGIES LTD." }, + { 0x1109, "LG Industrial Systems Co., Ltd." }, + { 0x110A, "Moxa Inc." }, + { 0x110B, "NAKI INTERNATIONAL" }, + { 0x110C, "Computer Network Technology" }, + { 0x110D, "Hitachi Car Engineering Co., Ltd." }, + { 0x110E, "Innotrac Diagnostics OY" }, + { 0x110F, "OneVision Corporation" }, + { 0x1110, "Analog Devices Canada Ltd." }, + { 0x1111, "Siemens Healthcare Diagnostics Inc." }, + { 0x1112, "Golden Bright (Sichuan) Electronic Technology Co Ltd" }, + { 0x1113, "Medion AG" }, + { 0x1114, "Psion Teklogix Inc." }, + { 0x1115, "Data Link Co., Ltd." }, + { 0x1116, "Compro Technology Inc." }, + { 0x1117, "11 WAVE TECHNOLOGY, INC." }, + { 0x1118, "MotoSAT" }, + { 0x1119, "GCS General Control Systems GmbH" }, + { 0x111A, "The Nippon Signal Co., Ltd." }, + { 0x111B, "Kyusyu Ten Ltd." }, + { 0x111C, "point electronic GmbH" }, + { 0x111D, "Centon Electronics" }, + { 0x111E, "VSO ELECTRONICS CO., LTD." }, + { 0x111F, "BANCOR S.R.L." }, + { 0x1120, "Voipac, s.r.o." }, + { 0x1121, "Kore Technology Limited" }, + { 0x1122, "Klein & Melgert Developments B.V." }, + { 0x1123, "Hi-Tech Instruments, Inc." }, + { 0x1124, "REnex Technology Limited" }, + { 0x1125, "Industrial Computing Ltd." }, + { 0x1126, "Protonic - Holland" }, + { 0x1127, "BANK25 Co., Ltd." }, + { 0x1128, "STEAG ETA-Optik GmbH" }, + { 0x1129, "Jung Myung Telecom Co., Ltd." }, + { 0x112A, "RedRat Ltd." }, + { 0x112B, "Stenograph L.L.C." }, + { 0x112C, "Ethics Organization of Computer Software" }, + { 0x112D, "SYSMEX CORPORATION" }, + { 0x112E, "Master Hill Electric Wire and Cable Co., Ltd." }, + { 0x112F, "Cellon International" }, + { 0x1130, "Tenx Technology, Inc." }, + { 0x1131, "Integrated System Solution Corp." }, + { 0x1132, "Visoduck discount GmbH" }, + { 0x1133, "Sanei Electric Co., Ltd." }, + { 0x1134, "Tri-L Data Systems, Inc." }, + { 0x1135, "imo-elektronik GmbH" }, + { 0x1136, "CTS ELECTRONICS" }, + { 0x1137, "Beyond LSI, Inc." }, + { 0x1138, "Greenwood Engineering A/S" }, + { 0x1139, "Wavetrend" }, + { 0x113B, "Hana Micron, Inc." }, + { 0x113C, "Arintech Co., Ltd." }, + { 0x113D, "Mapower Electronics Co. Ltd." }, + { 0x113E, "KDK Electric Wire (H.K.) Co., Ltd." }, + { 0x113F, "Integrated Biometrics" }, + { 0x1140, "Ultra-Scan Corporation" }, + { 0x1141, "V ONE MULTIMEDIA PTE LTD" }, + { 0x1142, "CYBERSCAN TECH. INC." }, + { 0x1143, "Wako Pure Chemical Industries, Ltd.." }, + { 0x1144, "MURATA MACHINERY, LTD." }, + { 0x1145, "Japan Radio Co., Ltd." }, + { 0x1146, "Shimane SANYO Electric Co., Ltd." }, + { 0x1147, "Ever Great Electric Wire and Cable Co., Ltd." }, + { 0x1148, "KGS Corporation" }, + { 0x1149, "TAMA TECH LAB CORP." }, + { 0x114A, "TANITA Corporation (1)" }, + { 0x114B, "Sphairon Technologies GmbH" }, + { 0x114C, "Tinius Olsen Testing Machine Co., Inc." }, + { 0x114D, "Alpha Imaging Technology Corp." }, + { 0x114E, "Digital Electronics Corporation" }, + { 0x114F, "WAVECOM" }, + { 0x1150, "Don Alan Pty. Ltd." }, + { 0x1151, "World Wide Licenses Limited" }, + { 0x1152, "Codonics, Inc." }, + { 0x1153, "Tritec Co., Ltd." }, + { 0x1154, "BEB Industrie-Elektronik AG" }, + { 0x1155, "DICESVA S.L." }, + { 0x1156, "Cybertech bv" }, + { 0x1157, "EKS Oy" }, + { 0x1158, "Syn-Tech Systems Inc." }, + { 0x1159, "Micro Application Laboratory Corp." }, + { 0x115A, "Extreme Speed" }, + { 0x115B, "Salix Technology Co., Ltd." }, + { 0x115C, "CORESMA" }, + { 0x115D, "ADTEK SYSTEM SCIENCE CO., LTD." }, + { 0x115E, "Group Sense Ltd." }, + { 0x115F, "Dataring Systems" }, + { 0x1160, "Invocon, Inc." }, + { 0x1161, "Port Denshi Co., Ltd." }, + { 0x1162, "Secugen Corporation" }, + { 0x1163, "DeLorme Publishing Inc." }, + { 0x1164, "YUAN High-Tech Development Co., Ltd." }, + { 0x1165, "Telson Electronics Co., Ltd." }, + { 0x1166, "Bantam Interactive Technologies" }, + { 0x1167, "Salient Systems Corporation" }, + { 0x1168, "BizConn International Corp." }, + { 0x1169, "Adirondack Optics" }, + { 0x116A, "JJL Technologies, LLC" }, + { 0x116B, "Pigeon Point Systems" }, + { 0x116C, "SecureEye, Inc." }, + { 0x116D, "Filmetrics, Inc." }, + { 0x116E, "Gigastorage Corp." }, + { 0x116F, "Silicon 10 Technology Corp." }, + { 0x1170, "Tadiran Com. Ltd." }, + { 0x1171, "CRE Technology Co., Ltd." }, + { 0x1172, "Telegate Co., Ltd." }, + { 0x1173, "Esko-Graphics" }, + { 0x1174, "Techno-One Co., Ltd." }, + { 0x1175, "Sheng Yih Technologies Co., Ltd." }, + { 0x1176, "Japan Touchscreen Distributions, Inc." }, + { 0x1177, "Hitachi Communication Technologies, Ltd." }, + { 0x1178, "Kamaya Electric Co., Ltd." }, + { 0x1179, "Bio-logic Systems Corp." }, + { 0x117A, "Ishikawa Seisakusho, Ltd." }, + { 0x117B, "Primetech Engineering Corporation" }, + { 0x117C, "SOFTIDEA s.r.o." }, + { 0x117D, "Santa Electronic Inc." }, + { 0x117E, "JNC, Inc." }, + { 0x117F, "Princeton Technology, Ltd." }, + { 0x1180, "Spectra-Physics" }, + { 0x1181, "USB NET" }, + { 0x1182, "Venture Corporation Limited" }, + { 0x1183, "Digital Dream Co. Europe Ltd." }, + { 0x1184, "Kyocera Elco Corporation" }, + { 0x1185, "Projectiondesign AS" }, + { 0x1186, "Scientec System" }, + { 0x1187, "Techno Valley Co., Ltd." }, + { 0x1188, "Bloomberg L.P." }, + { 0x1189, "Trisat IndTry Computer Co. LTD." }, + { 0x118A, "KEBA AG" }, + { 0x118B, "AXIOMTEK Co., Ltd." }, + { 0x118C, "INFINIT GmbH" }, + { 0x118D, "Gould Instrument Systems" }, + { 0x118E, "Hermstedt AG" }, + { 0x118F, "You Yang Technology Co., Ltd." }, + { 0x1190, "Tripace" }, + { 0x1191, "Loyalty Founder Enterprise Co., Ltd." }, + { 0x1192, "Matsusada Precision Inc." }, + { 0x1193, "H2I TECHNOLOGIES" }, + { 0x1194, "GLORY AZ System Co., Ltd." }, + { 0x1195, "ELECTROLINE" }, + { 0x1196, "Yankee Robotics, LLC" }, + { 0x1197, "Technoimagia Co., Ltd." }, + { 0x1198, "StarShine Technology Corp." }, + { 0x1199, "Sierra Wireless Inc." }, + { 0x119A, "DONG GUAN JALINK ELECTRONICES CO.,LTD" }, + { 0x119B, "ruwido austria GmbH" }, + { 0x119C, "SK MEDICAL ELECTRONICS CO.,LTD" }, + { 0x119D, "Saka-Techno Science Co., Ltd." }, + { 0x119E, "Engineered Audio, LLC." }, + { 0x119F, "TECNOS CO., LTD." }, + { 0x11A0, "Chipcon" }, + { 0x11A1, "Mikrap AG" }, + { 0x11A2, "SitecSoft Co., Ltd." }, + { 0x11A3, "Technovas Co., Ltd." }, + { 0x11A4, "THE FURUKAWA ELECTRIC CO., LTD." }, + { 0x11A5, "TOKYO RIKAKIKAI CO., LTD." }, + { 0x11A6, "VRmagic GmbH" }, + { 0x11A7, "SNAPSHIELD LTD." }, + { 0x11A8, "Hoeft & Wessel AG" }, + { 0x11A9, "Parker Hannifin" }, + { 0x11AA, "GlobalMedia Group, LLC" }, + { 0x11AB, "Exito Electronics Co., Ltd." }, + { 0x11AC, "Nike, Inc." }, + { 0x11AD, "SANWA ELECTRIC INSTRUMENT CO., LTD." }, + { 0x11AE, "Stoelting Co." }, + { 0x11AF, "Valence Semiconductor" }, + { 0x11B0, "ATECH FLASH TECHNOLOGY" }, + { 0x11B1, "New Motion Tec. Corp." }, + { 0x11B2, "Bizerba GmbH & Co. KG" }, + { 0x11B3, "MONYA Corporation" }, + { 0x11B4, "SPIELO" }, + { 0x11B5, "ADVANTECH EQUIPMENT CORP." }, + { 0x11B6, "Diskware Co., Ltd." }, + { 0x11B7, "Embla" }, + { 0x11B8, "CROSS S&T Inc." }, + { 0x11B9, "IST Electronics, Inc." }, + { 0x11BA, "Sasem Co., Ltd." }, + { 0x11BB, "YaMu Solutions" }, + { 0x11BC, "Taipei EELY-ECW Co., Ltd." }, + { 0x11BD, "UBINETICS LIMITED" }, + { 0x11BE, "Martin Professional A/S" }, + { 0x11BF, "SonoSite, Inc." }, + { 0x11C0, "Sanmos Microelectronics Corp." }, + { 0x11C1, "Wako Giken Kogyo Co., Ltd." }, + { 0x11C2, "EYESPYFX" }, + { 0x11C3, "Kaizen Frogpad, LLC" }, + { 0x11C4, "DALLANTBANK, INC." }, + { 0x11C5, "INMAX TECHNOLOGY CORP." }, + { 0x11C6, "Guzik Technical Enterprises" }, + { 0x11C7, "Reliance Electric Limited" }, + { 0x11C8, "Fullcom Technology Corp." }, + { 0x11C9, "Monster Cable Products, Inc." }, + { 0x11CA, "VeriFone" }, + { 0x11CB, "Magni Systems, Inc." }, + { 0x11CC, "AIM SRL" }, + { 0x11CD, "KTEK Co., Ltd." }, + { 0x11CE, "Argolis BV" }, + { 0x11CF, "Nemoto Kyorindo Co., Ltd." }, + { 0x11D0, "TOPCON CORPORATION, Opthalmic & Medical Instrument Dept" }, + { 0x11D1, "Far Touch Inc." }, + { 0x11D2, "BW Technologies Ltd." }, + { 0x11D3, "Elias Technology, Inc." }, + { 0x11D4, "Unitac Co., Ltd." }, + { 0x11D5, "Polyvision Corporation" }, + { 0x11D6, "FUJIFILM AXIA CO., LTD." }, + { 0x11D7, "Kokusai Electric Alpha Co., Ltd." }, + { 0x11D8, "Zybertek" }, + { 0x11D9, "Itronix Corporation" }, + { 0x11DA, "Tekscan, Inc." }, + { 0x11DB, "Topfield Co., Ltd." }, + { 0x11DC, "STELECTRIC A/S" }, + { 0x11DD, "DRAGONCHIP LTD." }, + { 0x11DE, "La Generale Multimedia" }, + { 0x11DF, "ROI Computer AG" }, + { 0x11E0, "SUNX Limited" }, + { 0x11E1, "Encentuate Pte. Ltd." }, + { 0x11E2, "SPECSOFT CONSULTING INC" }, + { 0x11E3, "GfS-Hofheim" }, + { 0x11E4, "STANDARD ELECTRONICS TELECOM INC." }, + { 0x11E5, "CHUFON Technology Co., Ltd." }, + { 0x11E6, "K.I. Technology Co. Ltd." }, + { 0x11E7, "Rockford Corporation" }, + { 0x11E8, "NAAT Technology Corp." }, + { 0x11E9, "Wincan Technology Co., Ltd." }, + { 0x11EA, "Panram International Corp." }, + { 0x11EB, "VTech Innovation L.P. dba Advanced American Telephones" }, + { 0x11EC, "Hitachi Computer Peripherals Co., Ltd." }, + { 0x11ED, "Shimizu Technology Inc." }, + { 0x11EE, "ASAHI ELECTRIC CO., LTD." }, + { 0x11EF, "Cableplus Industrial Co., Ltd." }, + { 0x11F0, "Matthew Ward Solutions" }, + { 0x11F1, "Cal-Comp Electronics (Thailand) Public Co., Ltd." }, + { 0x11F2, "Chain Tay Technology Co., Ltd." }, + { 0x11F3, "ROUND Co., Ltd." }, + { 0x11F4, "Kyoritsu Electric Corporation" }, + { 0x11F5, "Siemens Mobile Phones" }, + { 0x11F6, "NetIndex Inc." }, + { 0x11F7, "ALCATEL BUSINESS SYSTEMS" }, + { 0x11F8, "BodyMedia, Inc." }, + { 0x11F9, "Cryptocard Corporation" }, + { 0x11FA, "Code Corporation" }, + { 0x11FB, "HORIBA, Ltd." }, + { 0x11FC, "ANCOT CORPORATION" }, + { 0x11FD, "EKE-Electronics Ltd." }, + { 0x11FE, "SHENZHEN CHANGXUNXING ELECTRONIC CO., LTD." }, + { 0x11FF, "LITE STAR ELECTRONICS TECHNOLOGIES, CO. LTD." }, + { 0x1200, "Spellman High Voltage Electronics Corp." }, + { 0x1201, "Practical Automation, Inc." }, + { 0x1202, "KUK JE TONG SHIN CO., LTD." }, + { 0x1203, "Taiwan Semiconductor Co., Ltd." }, + { 0x1204, "SATEC" }, + { 0x1205, "NV ADB TTV TECHNOLOGIES SA" }, + { 0x1206, "Synnix Technology Co." }, + { 0x1207, "Cardinal Health UK 232 Ltd." }, + { 0x1208, "Seiko Epson Corp.- System Device" }, + { 0x120A, "Wintest Corp." }, + { 0x120B, "Dension Audio Systems Ltd." }, + { 0x120C, "ALF, Inc." }, + { 0x120D, "(AVL) DiTEST Fahrzeugdiagnose GmbH" }, + { 0x120E, "HUDSON SOFT CO., LTD." }, + { 0x120F, "Magellan Navigation, Inc." }, + { 0x1210, "Harman" }, + { 0x1211, "COSMED S.r.l." }, + { 0x1212, "D'Crypt Pte Ltd." }, + { 0x1213, "Fukko System Co., Ltd." }, + { 0x1214, "Dr. Bott KG" }, + { 0x1215, "Towa Engineering Corporation" }, + { 0x1216, "ProMinent Dosiertechnik GmbH" }, + { 0x1217, "Goyatek Technology Inc." }, + { 0x1218, "Geutebrueck GmbH" }, + { 0x1219, "COMPAL COMMUNICATIONS, INC." }, + { 0x121A, "TimeKeeping Systems, Inc." }, + { 0x121B, "FEC Inc." }, + { 0x121C, "Raysis Co., Ltd." }, + { 0x121D, "Intelligent Computer Solutions" }, + { 0x121E, "Jungsoft Co., Ltd." }, + { 0x121F, "Panini S.P.A." }, + { 0x1220, "TC Group A/S" }, + { 0x1221, "Averatec, Inc." }, + { 0x1222, "Tipro Keyboards D.O.O." }, + { 0x1223, "SKYCABLE ENTERPRISE CO., LTD." }, + { 0x1224, "SCATT, ZAO" }, + { 0x1225, "HI-P Tech Corporation" }, + { 0x1226, "Keihin Corporation" }, + { 0x1227, "T-RAC INTERNATIONAL, INC." }, + { 0x1228, "DATAPAQ" }, + { 0x1229, "EPO Science & Technology Inc." }, + { 0x122A, "WABCO GmbH & Co., OHG" }, + { 0x122B, "Midas Lab Inc." }, + { 0x122C, "Qbtech AB" }, + { 0x122D, "Hitachi Information & Control Solutions, Ltd." }, + { 0x122E, "IOLINE" }, + { 0x122F, "Takimaging" }, + { 0x1230, "MIPSABG Chipidea, Lda." }, + { 0x1231, "CHI MEI COMMUNICATION SYSTEMS, INC." }, + { 0x1232, "SolitonWave Co., Ltd." }, + { 0x1233, "Targa Systems Div. L-3 Communications" }, + { 0x1234, "Micro Science Co., Ltd." }, + { 0x1235, "Focusrite Audio Engineering Ltd" }, + { 0x1236, "Nozaki Insatsu Shigyo Co., Ltd." }, + { 0x1237, "Technowave Ltd." }, + { 0x1238, "Bridgekey Corp." }, + { 0x1239, "Antex Electronics" }, + { 0x123A, "Spectra Technologies Holdings Co., Ltd." }, + { 0x123B, "De La Rue Systems Automatizacao" }, + { 0x123C, "K-Won C & C Co., Ltd." }, + { 0x123D, "Microplex Printware AG" }, + { 0x123E, "A.T. WORKS, Inc." }, + { 0x123F, "DURAPOWER TECHNOLOGY LTD." }, + { 0x1240, "HUMUS MOG CO., LTD." }, + { 0x1241, "OTSUKA ELECTRONICS CO., LTD." }, + { 0x1242, "MAC SYSTEM CO., LTD." }, + { 0x1243, "Fujikura Ltd., Fiber Optic System Division" }, + { 0x1244, "DResearch Digital Media Systems GmbH" }, + { 0x1245, "R/D Tech Inc." }, + { 0x1246, "CTO S.p.A." }, + { 0x1247, "JAPAN PRECISION INSTRUMENTS, INC." }, + { 0x1248, "Vector Informatik GmbH" }, + { 0x1249, "TRACESPAN Communications Ltd." }, + { 0x124A, "AirVast Technology Inc." }, + { 0x124B, "NYKO Technologies, Inc." }, + { 0x124C, "MEMORY EXPERTS International Inc." }, + { 0x124D, "Just Rams PLC" }, + { 0x124E, "YEM Inc." }, + { 0x124F, "Beijing JingHuiJiaDe Tech. Co., Ltd." }, + { 0x1250, "TECMAG" }, + { 0x1251, "Iwaya Corporation" }, + { 0x1252, "Nextway Co., Ltd." }, + { 0x1253, "Erebus Limited" }, + { 0x1254, "Empirical Systems" }, + { 0x1255, "ASCII Solutions, Inc." }, + { 0x1256, "Spectronic Denmark A/S" }, + { 0x1257, "AudioScience" }, + { 0x1258, "Continental Automotive Trading UK Ltd." }, + { 0x1259, "Deutsche Montan Technologie GmbH" }, + { 0x125A, "Shintake Sangyo Co., Ltd." }, + { 0x125B, "VIDEX" }, + { 0x125C, "Apogee Instruments, Inc." }, + { 0x125D, "Advanced Technology (UK) PLC" }, + { 0x125E, "Bosch Automotive Service Solutions" }, + { 0x125F, "ADATA Technology Co., Ltd." }, + { 0x1260, "Cores Inc." }, + { 0x1261, "All Ring Tech Co., Ltd." }, + { 0x1262, "MICRO VISION CO., LTD." }, + { 0x1263, "Opti Japan Corporation" }, + { 0x1264, "Covidien Energy-based Devices" }, + { 0x1265, "Good Mind Industries Co., Ltd." }, + { 0x1266, "Pirelli Cavi e Sistemi Telecom S.p.A." }, + { 0x1267, "SILCOR" }, + { 0x1268, "icube Corp." }, + { 0x1269, "Sequoia Voting Systems Inc." }, + { 0x126A, "CHH Electronics Ltd." }, + { 0x126B, "Veridian Systems" }, + { 0x126C, "Aristocrat Technologies" }, + { 0x126D, "Bel Stewart" }, + { 0x126E, "Strobe Data, Inc." }, + { 0x126F, "TwinMOS Technologies ME FZE" }, + { 0x1270, "Procomp Informatics Ltd." }, + { 0x1271, "Foxda Technology Industrial (Shenzhen) Co., Ltd." }, + { 0x1272, "Linear Technology Corporation" }, + { 0x1273, "HANEX Co., Ltd." }, + { 0x1274, "Matin, Inc." }, + { 0x1275, "Xaxero Marine Software Engineering Ltd." }, + { 0x1276, "QVS" }, + { 0x1277, "Silicon Media Inc." }, + { 0x1278, "Starlight Xpress Ltd." }, + { 0x1279, "Cheesecote Mountain Camac" }, + { 0x127A, "Electrophysics Corp." }, + { 0x127B, "The Technology Partnership (TTP)" }, + { 0x127C, "Comarco Wireless" }, + { 0x127D, "RAiO Technology Inc." }, + { 0x127E, "Hugelent Telecommunication (SuZhou) Co., Ltd." }, + { 0x127F, "IPACS Hans-Borchers-Gruentjens GbR (IPACS)" }, + { 0x1280, "Animeta Systems Inc." }, + { 0x1281, "Gean Sen Electronic Co., Ltd." }, + { 0x1282, "Falco Electronics Mexico" }, + { 0x1283, "zebris Medizintechnik GmbH" }, + { 0x1284, "YEC Co., Ltd." }, + { 0x1285, "Schindler Aufzuge AG" }, + { 0x1286, "MARVELL SEMICONDUCTOR, INC." }, + { 0x1287, "Infomove Co., Ltd." }, + { 0x1288, "Micro Advantage Inc." }, + { 0x1289, "Nippon Telesoft Co., Ltd." }, + { 0x128A, "Asia Vital Components Co., Ltd." }, + { 0x128B, "Medicapture, Inc." }, + { 0x128C, "ITW Food Equipment Group, LLC dba Hobart Corporation" }, + { 0x128D, "Testo AG" }, + { 0x128E, "Stormblue Co., Ltd." }, + { 0x128F, "Guidant Corporation" }, + { 0x1290, "Musicus GmbH" }, + { 0x1291, "Flarion Technologies" }, + { 0x1292, "Fire International Ltd." }, + { 0x1293, "Mitsubishi Electric Engineering Co., Ltd." }, + { 0x1294, "RISO KAGAKU CORP." }, + { 0x1295, "A & G Souzioni Digitali" }, + { 0x1296, "RadioScape" }, + { 0x1297, "DEKTEC Digital Video B.V." }, + { 0x1298, "Genlyte Controls" }, + { 0x1299, "DGStation Co., Ltd." }, + { 0x129A, "PULSTEC INDUSTRIAL CO., LTD." }, + { 0x129B, "CyberTAN Technology Inc." }, + { 0x129C, "Min Aik Technology Co., Ltd." }, + { 0x129D, "Yueqing Longhua Electronics Factory" }, + { 0x129E, "Aceeca Limited" }, + { 0x129F, "Howtek Devices Corp." }, + { 0x12A0, "CDC Point S.p.A." }, + { 0x12A1, "Tohken Co., Ltd." }, + { 0x12A2, "E28 (Shanghai) Ltd." }, + { 0x12A3, "KENT WORLD CO., LTD." }, + { 0x12A4, "Guangdong Matsunichi Communications Technology Co., Ltd" }, + { 0x12A5, "Sola/Hevi-Duty" }, + { 0x12A6, "ULVAC-PHI, Inc." }, + { 0x12A7, "Trendchip Technologies Corp." }, + { 0x12A8, "Clovertech Inc." }, + { 0x12A9, "Sunwave Technology Corp." }, + { 0x12AA, "Bustec Production Ltd." }, + { 0x12AB, "Honey Bee (Hong Kong) Limited" }, + { 0x12AC, "Compact Light System Norway A/S" }, + { 0x12AD, "Asahi Seiko Co., Ltd." }, + { 0x12AE, "Matsunichi Communication Holdings Limited" }, + { 0x12AF, "Baldor UK Ltd." }, + { 0x12B0, "Axciton Systems, Inc." }, + { 0x12B1, "HIMECS CO., LTD." }, + { 0x12B2, "DICKSON Company" }, + { 0x12B3, "Megaforce Company Ltd." }, + { 0x12B4, "Hanchang System Corporation" }, + { 0x12B5, "World Touch Gaming , Inc." }, + { 0x12B6, "Naito Densei Machida Mfg. Co., Ltd." }, + { 0x12B7, "Genesis Microchip Inc." }, + { 0x12B8, "Zhejiang Xinya Electronic Technology Co., Ltd." }, + { 0x12B9, "Freehand Systems, Inc." }, + { 0x12BA, "Sony Computer Entertainment America" }, + { 0x12BB, "Paltronics, Inc." }, + { 0x12BC, "Hakusan Corporation" }, + { 0x12BD, "Sun Light Application Co., Ltd." }, + { 0x12BE, "Dynex Technologies" }, + { 0x12BF, "Matrix Multimedia Ltd." }, + { 0x12C0, "Sencore, Inc." }, + { 0x12C1, "ARTRAY CO., LTD." }, + { 0x12C2, "HHB Communications Ltd." }, + { 0x12C3, "Fiso Technologies, Inc." }, + { 0x12C4, "Autocue Ltd." }, + { 0x12C5, "XN Technologies, Inc." }, + { 0x12C6, "Bosch Security Systems" }, + { 0x12C7, "Hismartech Co., Ltd." }, + { 0x12C8, "XiMeta Inc." }, + { 0x12C9, "Newmen Technology Corp. Ltd." }, + { 0x12CA, "Cables To Go International Manufacturing Co., Ltd." }, + { 0x12CB, "Dallmeier electronic GmbH" }, + { 0x12CC, "Printherm" }, + { 0x12CD, "Cables Unlimited" }, + { 0x12CE, "Hakko Electronics Co., Ltd." }, + { 0x12CF, "Dexin Corporation" }, + { 0x12D0, "ITG Research & Development Center" }, + { 0x12D1, "Huawei Technologies Co., Ltd." }, + { 0x12D2, "LINE TECH INDUSTRIAL CO., LTD." }, + { 0x12D3, "Linak A/S" }, + { 0x12D4, "Infonics Pty. Limited" }, + { 0x12D5, "Strategic Vista Corp." }, + { 0x12D6, "EMS Dr. Thomas Wuensche" }, + { 0x12D7, "Better Holdings (HK) Limited" }, + { 0x12D8, "Araneus Information Systems Oy" }, + { 0x12D9, "DIGITFAB INTERNATIONAL CO., LTD." }, + { 0x12DA, "Simavionics, Inc." }, + { 0x12DB, "Planar Systems, Inc." }, + { 0x12DC, "MMGEAR Co., Ltd." }, + { 0x12DD, "JFE Advantech Co., Ltd." }, + { 0x12DE, "National Display Systems" }, + { 0x12DF, "Sumitomo 3M Limited" }, + { 0x12E0, "Electronica Mecanica Y Control S.A." }, + { 0x12E1, "FDK CORPORATION" }, + { 0x12E2, "Bonso Electronic Ltd." }, + { 0x12E3, "1417188 Ontario Ltd." }, + { 0x12E4, "Bruel & Kjaer Sound & Vibration Meas. A/S" }, + { 0x12E5, "Interactive Computer Products, Inc." }, + { 0x12E6, "Waldorf-Music AG" }, + { 0x12E7, "Sugiyama Electron Co., Ltd." }, + { 0x12E8, "ZAN Messgeraete" }, + { 0x12E9, "Mindspeed Technologies" }, + { 0x12EA, "Microlink Systems" }, + { 0x12EB, "MITSUI & CO., LTD." }, + { 0x12EC, "KYORITSU ELECTRICAL INSTRUMENTS WORKS, LTD. (R&D Center" }, + { 0x12ED, "Techno Kit Corporation" }, + { 0x12EE, "Avery Dennison Deutschland GmbH" }, + { 0x12EF, "Tapwave, Inc." }, + { 0x12F0, "KROHNE" }, + { 0x12F1, "OHIRA GIKEN, IND. CO., LTD." }, + { 0x12F2, "VIEWPLUS TECHNOLOGIES, INC." }, + { 0x12F3, "FORMOSA TELETEK CORPORATION" }, + { 0x12F4, "Glovic Electronics Corp." }, + { 0x12F5, "Dynamic System Electronics Corp." }, + { 0x12F6, "Aichi Tokei Denki Co., Ltd." }, + { 0x12F7, "Memorex Products, Inc." }, + { 0x12F8, "Evolution Technologies, Inc." }, + { 0x12F9, "RF-LINK SYSTEMS, INC." }, + { 0x12FA, "RF Micro Devices" }, + { 0x12FB, "SSD JAPAN CO., Ltd" }, + { 0x12FC, "eGenium S.r.l." }, + { 0x12FD, "AIN COMM. TECHNOLOGY CO., LTD." }, + { 0x12FE, "E.U CONNECTOR(M) SDN BHD." }, + { 0x12FF, "Fascinating Electronics, Inc." }, + { 0x1300, "Muscle Corporation" }, + { 0x1301, "Woehler Messgeraete Kehrgeraete GmbH" }, + { 0x1302, "Wildseed Ltd." }, + { 0x1303, "Lloyd Research (Projects) Ltd." }, + { 0x1304, "MEDIALINK-I, Inc." }, + { 0x1305, "ELSE Ltd." }, + { 0x1306, "Torcon Instruments Inc." }, + { 0x1307, "USBest Technology Inc." }, + { 0x1308, "Precision Photonics Corp." }, + { 0x1309, "Sabine, Inc." }, + { 0x130A, "SIBATA SCIENTIFIC TECHNOLOGY, LTD." }, + { 0x130B, "MPC Products" }, + { 0x130C, "Quest Technologies" }, + { 0x130D, "Loyal Technology Corporation" }, + { 0x130E, "Microlink Communications Inc." }, + { 0x130F, "AGFA NDT, Krautkramer Ultrasonic Systems" }, + { 0x1310, "Air2U Inc." }, + { 0x1311, "EDX Epi-Scan Corp" }, + { 0x1312, "ICS Electronics" }, + { 0x1313, "THORLABS, INC" }, + { 0x1314, "Ryoko Electric Co., Ltd." }, + { 0x1315, "Prairie Systems & Equip. Ltd. O/A Massload Technologies" }, + { 0x1316, "JUNGLE Inc" }, + { 0x1317, "PC-CRAFT Co., Ltd." }, + { 0x1318, "O'RITE TECHNOLOGY Co., Ltd." }, + { 0x1319, "Peekel Instruments B.V." }, + { 0x131A, "VERYWELL CO., LTD." }, + { 0x131B, "Rowley Associates Ltd." }, + { 0x131C, "Staples, Inc." }, + { 0x131D, "Natural Point" }, + { 0x131E, "Duerr Dental GmbH & Co., KG" }, + { 0x131F, "Ayuttha Technology Corp." }, + { 0x1320, "Jaguar International Corporation" }, + { 0x1321, "Lectrosonics, Inc." }, + { 0x1322, "Z/I Imaging" }, + { 0x1323, "Zeustech Company Limited" }, + { 0x1324, "H-Mod, Inc." }, + { 0x1325, "Austriamicrosystems AG" }, + { 0x1326, "Force Control Industries Inc." }, + { 0x1327, "Avtec, Inc." }, + { 0x1328, "Iris Power Engineering" }, + { 0x1329, "Appairent Technologies, Inc." }, + { 0x132A, "Envara" }, + { 0x132B, "Konica Minolta, Inc." }, + { 0x132C, "Le Prestique International (H.K.) Ltd." }, + { 0x132D, "GE Healthcare Life Sciences" }, + { 0x132E, "Kwang Jang Corporation" }, + { 0x132F, "ViALUX GmbH" }, + { 0x1330, "ALFANUCLEAR S.A." }, + { 0x1331, "Panic Inc." }, + { 0x1332, "Moral Follow System Co., Ltd." }, + { 0x1333, "Ultra Electronics Precision Air & Land Systems" }, + { 0x1334, "ADC Corporation" }, + { 0x1335, "PLUS Corporation" }, + { 0x1336, "IMM-Gruppe" }, + { 0x1337, "Radiant Networks Plc" }, + { 0x1338, "IT CONCEPTS LLC" }, + { 0x1339, "Akashi Corporation" }, + { 0x133A, "Vyyo Inc." }, + { 0x133B, "FLASH SUPPORT GROUP, INC." }, + { 0x133C, "G-Design Technology" }, + { 0x133D, "Jasco Products Company" }, + { 0x133E, "Kemper Digital GmbH" }, + { 0x133F, "Hwayoung RF Solution Inc." }, + { 0x1340, "Escherlogic Inc." }, + { 0x1341, "Lavry Engineering" }, + { 0x1342, "Sutter Instrument Company" }, + { 0x1343, "Heiwa Tokei Mfg. Co., Ltd" }, + { 0x1344, "TCI, Inc. d/b/a TCI Medical" }, + { 0x1345, "Sino Lite Technology Corp." }, + { 0x1346, "Mediatek Corp." }, + { 0x1347, "Moravian Instruments, Inc." }, + { 0x1348, "Katsuragawa Electric Co., Ltd." }, + { 0x1349, "Esaote/Pie Medical Equipment" }, + { 0x134A, "iX Group" }, + { 0x134B, "El Pusk Co., Ltd." }, + { 0x134C, "Panjit International Inc." }, + { 0x134D, "Danfoss Drives A/S" }, + { 0x134E, "Digby's Bitpile, Inc. D.B.A. D Bit" }, + { 0x134F, "Addvalue Communications Pte Ltd." }, + { 0x1350, "UniqueICs, LLC" }, + { 0x1351, "Crossware Associates" }, + { 0x1352, "Km2Net" }, + { 0x1353, "Shenzhen Coship Software Co., Ltd." }, + { 0x1354, "FACTS Engineering LLC" }, + { 0x1355, "Ethicon Endo-Surgery, Inc." }, + { 0x1356, "Techpoint Electric Wire & Cable Co., Ltd." }, + { 0x1357, "P & E Microcomputer Systems, Inc." }, + { 0x1358, "SKYLIGHT DIGITAL INC." }, + { 0x1359, "RKC INSTRUMENT INC." }, + { 0x135A, "URMET TLC S.p.A. - Servizio Amministrativo" }, + { 0x135B, "M-System Co., Ltd." }, + { 0x135C, "Real-Time Essentials, Inc." }, + { 0x135D, "ALGOTEX SRL" }, + { 0x135E, "Insta Elektro GmbH" }, + { 0x135F, "Control Development, Inc." }, + { 0x1360, "FREETRON COM LTD." }, + { 0x1361, "Thinktel Korea Co., Ltd." }, + { 0x1362, "IMAGICA Corp." }, + { 0x1363, "Axsun Technologies, Inc." }, + { 0x1364, "SHARP TAKAYA ELECTRONICS INDUSTRY CO., LTD." }, + { 0x1365, "TOYO JIKI INDUSTRY CO., LTD." }, + { 0x1366, "SEGGER Microcontroller Systems GmbH" }, + { 0x1367, "The Soundbeam Project" }, + { 0x1368, "TelePaq Technology Inc." }, + { 0x1369, "FASL LLC." }, + { 0x136A, "Pelco" }, + { 0x136B, "STEC" }, + { 0x136C, "Datastor Technology Co., Ltd." }, + { 0x136D, "Brainchild" }, + { 0x136E, "Andor Technology" }, + { 0x136F, "Nielsen Media Research" }, + { 0x1370, "Swissbit AG" }, + { 0x1371, "Micro Technology Co., Ltd." }, + { 0x1372, "AMAC Tek Co., Ltd." }, + { 0x1373, "Radical Research, Inc." }, + { 0x1374, "American Anko Co." }, + { 0x1375, "TCL MOBILE COMMUNICATION CO., LTD." }, + { 0x1376, "Vimtron Electronics Co., Ltd." }, + { 0x1377, "Sennheiser Electronic" }, + { 0x1378, "HIRATA Corporation" }, + { 0x1379, "Inprocomm, Inc." }, + { 0x137A, "Weldon Technologies, Inc." }, + { 0x137B, "SCAPS GmbH" }, + { 0x137C, "Yaskawa Electric Corporation" }, + { 0x137D, "Diodes Incorporated" }, + { 0x137E, "XL Microwave, Inc." }, + { 0x137F, "Sata Hi Tech Services" }, + { 0x1380, "Staveley Instruments" }, + { 0x1381, "N-LINE SYSTEM CO., LTD." }, + { 0x1382, "Systemware Inc." }, + { 0x1383, "Application Corporation" }, + { 0x1384, "Device Drivers Limited" }, + { 0x1385, "Variscite Ltd." }, + { 0x1386, "SCD Tech Inc." }, + { 0x1387, "Advanced Technical Group" }, + { 0x1388, "Southern Vision Systems, Inc." }, + { 0x1389, "Coolnection Technology Co., Ltd." }, + { 0x138A, "Validity Inc." }, + { 0x138B, "AMS Limited, Integrated Systems" }, + { 0x138C, "Fortemedia, Inc." }, + { 0x138D, "CPI GmbH" }, + { 0x138E, "RAISONANCE" }, + { 0x138F, "Saia-Burgess Controls Ltd." }, + { 0x1390, "TomTom International B.V." }, + { 0x1391, "IdealTEK" }, + { 0x1392, "SAGE INSTRUMENTS" }, + { 0x1393, "ELNEC s.r.o." }, + { 0x1394, "Gemini 2000 Ltd." }, + { 0x1395, "Sennheiser Communications A/S" }, + { 0x1396, "Greenliant Systems, Inc." }, + { 0x1397, "Behringer Spezielle Studiotechnik GmbH" }, + { 0x1398, "Nintendo of America" }, + { 0x1399, "Thai Wonderful Wire Cable Co., Ltd." }, + { 0x139A, "Infinitec Co., Ltd." }, + { 0x139B, "Thomas Enterprises, Inc." }, + { 0x139C, "Deltronics" }, + { 0x139D, "Digisafe Pte. Ltd." }, + { 0x139E, "Valueplus Inc." }, + { 0x139F, "Audio Technology Switzerland SA" }, + { 0x13A0, "Essilor International" }, + { 0x13A1, "Canas Co., Ltd." }, + { 0x13A2, "Pesa Switching Systems, Inc." }, + { 0x13A3, "Dynon Instruments" }, + { 0x13A4, "Equipment Systems & Devices" }, + { 0x13A5, "Sammy Corporation" }, + { 0x13A6, "Jeppesen Sanderson Inc." }, + { 0x13A7, "Circuit Design, Inc." }, + { 0x13A8, "Grandtec Electronic Corp" }, + { 0x13A9, "YAMAMOTO-MS CO., LTD." }, + { 0x13AA, "Sinar Electronics Limited" }, + { 0x13AB, "MicroMade Galka i Drozdz sp.j" }, + { 0x13AC, "DAQ Systems" }, + { 0x13AD, "Baltech AG" }, + { 0x13AE, "CIM-USA Inc." }, + { 0x13AF, "Handheld Entertainment" }, + { 0x13B0, "PerkinElmer Optoelectronics" }, + { 0x13B1, "Cisco-Linksys, LLC" }, + { 0x13B2, "ALESIS" }, + { 0x13B3, "Nippon Dics Co., Ltd." }, + { 0x13B4, "Dolch Computer Systems" }, + { 0x13B5, "INVENTECH, INC." }, + { 0x13B6, "ISABELLENHUETTE Heusler GmbH KG" }, + { 0x13B7, "Keymark Technology Co., Ltd." }, + { 0x13B8, "PDM Electronic Co., Ltd." }, + { 0x13B9, "Cimcore" }, + { 0x13BA, "Yung Ray Technology Co., Ltd." }, + { 0x13BB, "Covidien Respiratory and Monitoring Solutions" }, + { 0x13BC, "Imaging Supersonic Laboratories Co., Ltd." }, + { 0x13BD, "Remote Technologies, Inc." }, + { 0x13BE, "Ricoh Printing Systems, Ltd." }, + { 0x13BF, "Accusys, Inc." }, + { 0x13C0, "Stream Labs" }, + { 0x13C1, "Vivitar Corporation" }, + { 0x13C2, "SATO KEIRYOKI MFG. CO., LTD." }, + { 0x13C3, "SCT Performance, LLC" }, + { 0x13C4, "StationZ Inc." }, + { 0x13C5, "MELFAS, INC." }, + { 0x13C6, "Hasointech Co., Ltd." }, + { 0x13C7, "ANDO ELECTRIC CO., LTD." }, + { 0x13C8, "Togami Electric Mfg. Co., Ltd." }, + { 0x13C9, "LinearX Systems Inc." }, + { 0x13CA, "JyeTai Precision Industrial Co., Ltd." }, + { 0x13CB, "JTEK Technology Corporation" }, + { 0x13CC, "Cellvic Corporation" }, + { 0x13CD, "ABCD Aging Biorhythms and Computer Diagnostics GmbH" }, + { 0x13CE, "Cypherix (Pty) Ltd." }, + { 0x13CF, "Wisair Ltd." }, + { 0x13D0, "Swedect AB" }, + { 0x13D1, "A-Max Technology Macao Commercial Offshore Co. Ltd." }, + { 0x13D2, "Intelligraphics, Inc." }, + { 0x13D3, "AzureWave Technologies, Inc." }, + { 0x13D4, "IWATSU TEST INSTRUMENTS CORPORATION" }, + { 0x13D5, "International Electronics Inc." }, + { 0x13D6, "Appside" }, + { 0x13D7, "Tableau, LLC" }, + { 0x13D8, "University of Stirling" }, + { 0x13D9, "Blazepoint Limited" }, + { 0x13DA, "OPTEX CO., LTD." }, + { 0x13DB, "Zastron Electronic (Shenzhen) Co. Ltd." }, + { 0x13DC, "ALEREON, INC." }, + { 0x13DD, "i.Tech Dynamic Limited" }, + { 0x13DE, "LANKOM ELECTRONICS CO., LTD." }, + { 0x13DF, "Good Fancy Enterprise Co., Ltd." }, + { 0x13E0, "Taiwan Silicon Electronics Corp." }, + { 0x13E1, "Kaibo Wire & Cable (Shenzhen) Co., Ltd." }, + { 0x13E2, "Parallax, Inc." }, + { 0x13E3, "SoniqCast, LLC" }, + { 0x13E4, "Audio Precision" }, + { 0x13E5, "Sigma Audio Research Ltd." }, + { 0x13E6, "TechnoScope Co., Ltd." }, + { 0x13E7, "Gantner Pigeon Systems GmbH" }, + { 0x13E8, "PalmSource Inc." }, + { 0x13E9, "Ununpentium, LLC" }, + { 0x13EA, "I/F - COM A/S" }, + { 0x13EB, "PILZ GMBH & CO. KG" }, + { 0x13EC, "Chyau Yuan Technology Co., Ltd." }, + { 0x13ED, "Wooju Communications Co., Ltd." }, + { 0x13EE, "ATLab Inc." }, + { 0x13EF, "Turner Technology" }, + { 0x13F0, "DIGENT CO., Ltd." }, + { 0x13F1, "AP Instruments" }, + { 0x13F2, "Tech Micro Corporation" }, + { 0x13F3, "Amulet Hotkey" }, + { 0x13F4, "Verisity Design Inc." }, + { 0x13F5, "X-TEL Communications, Inc." }, + { 0x13F6, "Aspen Touch Solutions, Inc." }, + { 0x13F7, "Corevalley Co., Ltd." }, + { 0x13F8, "EZPnP Technologies Corp." }, + { 0x13F9, "Impsys Digital Security AB" }, + { 0x13FA, "Radiantech, Inc." }, + { 0x13FB, "Noritsu Koki Co., Ltd." }, + { 0x13FC, "Compucat Research Pty Limited" }, + { 0x13FD, "Initio (HK) Corporation Limited" }, + { 0x13FE, "Phison Electronics Corp." }, + { 0x13FF, "VIEWCON ELECTRONIC LTD." }, + { 0x1400, "Axxion Group Corp." }, + { 0x1401, "Fulhua Microelectronics Corp." }, + { 0x1402, "Bowe Bell & Howell" }, + { 0x1403, "Sitronix Technology Corp." }, + { 0x1404, "Fundamental Software Incorporated" }, + { 0x1405, "Cooper Security Ltd." }, + { 0x1406, "Systemneeds, Inc." }, + { 0x1407, "Coin Mechanisms Inc." }, + { 0x1408, "Comark Ltd." }, + { 0x1409, "IDS Imaging Development Systems GmbH" }, + { 0x140A, "Koyo Electronics Industries Co., Ltd." }, + { 0x140B, "Vertex Standard Co., Ltd." }, + { 0x140C, "MITS Electronics" }, + { 0x140D, "Japan Novel Corporation" }, + { 0x140E, "Telechips, Inc." }, + { 0x140F, "i-WAVER" }, + { 0x1410, "Novatel Wireless, Inc." }, + { 0x1411, "SKIDATA AG" }, + { 0x1412, "IMADA CO., LTD." }, + { 0x1413, "Telsey S.p.A." }, + { 0x1415, "Sony Computer Entertainment Europe" }, + { 0x1416, "Axeon Limited" }, + { 0x1417, "Butterfly Media" }, + { 0x1418, "MediaPower Technology Corporation" }, + { 0x1419, "ABILITY ENTERPRISE CO., LTD." }, + { 0x141A, "Realm Systems Inc." }, + { 0x141B, "METRAWARE" }, + { 0x141C, "Leviton Manufacturing" }, + { 0x141D, "J.FIT Co., Ltd." }, + { 0x141E, "Ikegami Tsushinki Co., Ltd." }, + { 0x141F, "SHIMADZU CORPORATION" }, + { 0x1420, "Lyrtech Inc." }, + { 0x1421, "Sentech Co., Ltd." }, + { 0x1422, "Bird Electronic Corporation" }, + { 0x1423, "ANCA Pty. Ltd." }, + { 0x1424, "Posnet Polska S.A." }, + { 0x1425, "IBEX Technology Co., Ltd." }, + { 0x1426, "NADEX Co., Ltd." }, + { 0x1427, "Global Display Solutions S.P.A." }, + { 0x1428, "Improvision Ltd." }, + { 0x1429, "Vega Technologies Industrial (Austria) Co." }, + { 0x142A, "Thales-e-Transactions" }, + { 0x142B, "Arbiter Systems, Inc." }, + { 0x142C, "SOMA OPTICS, LTD." }, + { 0x142D, "Sanblaze Technology, Inc." }, + { 0x142E, "TAMS Inc." }, + { 0x142F, "IO Display Systems" }, + { 0x1430, "Activision" }, + { 0x1431, "Pertech Resources, Inc." }, + { 0x1432, "Beijing Watertek Information Technology Co., Ltd." }, + { 0x1433, "TRANWO TECHNOLOGY CORP." }, + { 0x1434, "Comart System Co., Ltd." }, + { 0x1435, "Wistron NeWeb Corp." }, + { 0x1436, "Denali Software, Inc." }, + { 0x1437, "Carl Zeiss" }, + { 0x1438, "My3ia (Beijing) Technology Ltd." }, + { 0x1439, "Wind River Systems Inc." }, + { 0x143A, "CP Technologies" }, + { 0x143B, "RHESCA Company Limited" }, + { 0x143C, "Altek Corporation" }, + { 0x143D, "FUKOKU INDUSTRY CO., LTD." }, + { 0x143E, "IAV GmbH" }, + { 0x143F, "IDEC IZUMI CORPORATION" }, + { 0x1440, "Jaalaa, Inc." }, + { 0x1441, "MARIAN GbR" }, + { 0x1442, "Canadian Bank Note Company, Limited" }, + { 0x1443, "Digilent Inc." }, + { 0x1444, "H & S Instruments Inc." }, + { 0x1445, "JUSTER CO., LTD." }, + { 0x1446, "X.J. Group Ltd." }, + { 0x1447, "Cognex Corporation" }, + { 0x1448, "Biosystems LLC" }, + { 0x1449, "SHIMADEN CO., LTD." }, + { 0x144A, "Megger" }, + { 0x144B, "MADENTEC LTD." }, + { 0x144C, "Always On UPS Systems Inc." }, + { 0x144D, "K-SUN Corporation" }, + { 0x144E, "Westar Corporation" }, + { 0x144F, "K-jump Health Co., Ltd." }, + { 0x1450, "Melec Inc." }, + { 0x1451, "Force Dimension LLC" }, + { 0x1452, "DAI NIPPON PRINTING CO., LTD." }, + { 0x1453, "Epilog Corporation" }, + { 0x1454, "China IWNCOMM Co., Ltd." }, + { 0x1455, "Georgia Technology Corp." }, + { 0x1456, "Extending Wire & Cable Co., Ltd." }, + { 0x1457, "DAE-A Mediatech Co., Ltd." }, + { 0x1458, "Rauland-Borg Corporation" }, + { 0x1459, "Shanghai Simax Micro-electronics Co., Ltd." }, + { 0x145A, "All-Systems Electronics Pty. Ltd." }, + { 0x145B, "Lead-Type Precision Electronics Co., Ltd." }, + { 0x145C, "Busch-Jaeger-Elektro GmbH" }, + { 0x145D, "Sopac Ltd." }, + { 0x145E, "Forschungszentrum Karlsruhe GmbH" }, + { 0x145F, "Trust International BV" }, + { 0x1460, "TATUNG Company" }, + { 0x1461, "Staccato Communications" }, + { 0x1462, "Bright Computech Co., Ltd." }, + { 0x1463, "BBWM Corp." }, + { 0x1464, "Asiamajor Inc." }, + { 0x1465, "Michilin Prosperity Co., Ltd." }, + { 0x1466, "H2 Developer Group" }, + { 0x1467, "Clearly Superior Technologies" }, + { 0x1468, "CSE Co., Ltd." }, + { 0x1469, "ELECTRIM CORPORATION" }, + { 0x146A, "Knobloch GmbH" }, + { 0x146B, "BigBen Interactive Limited" }, + { 0x146C, "HETEC Datensysteme GmbH" }, + { 0x146D, "Progeny Inc." }, + { 0x146E, "ClearOne Communications" }, + { 0x146F, "Unity Electrical Ind. Ltd." }, + { 0x1470, "STARRIVER TECHNOLOGY CO., LTD." }, + { 0x1471, "Open Labs, Inc." }, + { 0x1472, "Hangzhou H3C Technologies Co., Ltd." }, + { 0x1473, "Dingo Incorporated" }, + { 0x1474, "Lamp Express USA, Inc." }, + { 0x1475, "NAC Image Technology Incorporated" }, + { 0x1476, "Westech Korea Inc." }, + { 0x1477, "XIROKU INC." }, + { 0x1478, "Link World Electric Inc." }, + { 0x1479, "Datalux Corporation" }, + { 0x147A, "Formosa21 Inc." }, + { 0x147B, "ABB STOTZ-KONTAKT GmbH" }, + { 0x147C, "KeyGhost Ltd." }, + { 0x147D, "Tosoh Corporation" }, + { 0x147E, "UPEK Inc." }, + { 0x147F, "Hama GmbH & Co., KG" }, + { 0x1480, "SITEK S.p.a." }, + { 0x1481, "MHT S.p.A." }, + { 0x1482, "Vaillant GmbH" }, + { 0x1483, "Shenzhen MingWah Aohan High Technology Co., Ltd." }, + { 0x1484, "Triad Semiconductor, Inc." }, + { 0x1485, "OrangeWare Corp." }, + { 0x1486, "SCM PC-CARD GmbH" }, + { 0x1487, "DSP Group, Ltd." }, + { 0x1488, "Orion Technology Corp." }, + { 0x1489, "Sakura Finetek USA, Inc." }, + { 0x148A, "MICROVISION" }, + { 0x148B, "HandEra, Inc." }, + { 0x148C, "Colortrac Ltd." }, + { 0x148D, "DESMA Co., Ltd." }, + { 0x148E, "EVATRONIX SA" }, + { 0x148F, "Ralink Technology, Corp." }, + { 0x1490, "Digitek Spa" }, + { 0x1491, "Futronic Technology Co., Ltd." }, + { 0x1492, "Farsharp Imaging Technology Corp." }, + { 0x1493, "Suunto" }, + { 0x1495, "Elprotronic Inc." }, + { 0x1496, "Tunturi Oy Ltd." }, + { 0x1497, "Panstrong Company Ltd." }, + { 0x1498, "ULi Electronics Inc." }, + { 0x1499, "G-STAR Communications, Ltd." }, + { 0x149A, "Imagination Technologies" }, + { 0x149B, "Ivoclar Vivadent AG" }, + { 0x149C, "TonerHead.com" }, + { 0x149D, "QMotions Inc." }, + { 0x149E, "Amkor Technology" }, + { 0x149F, "Wits Technologies Pte. Ltd." }, + { 0x14A0, "WAVE Corporation" }, + { 0x14A1, "Sunhayato Corp." }, + { 0x14A2, "Big Dutchman (Skandinavien) A/S" }, + { 0x14A3, "Wipotec GmbH" }, + { 0x14A4, "Kyerim Industrial Co." }, + { 0x14A5, "I-ROCKS TECHNOLOGY CO., LTD." }, + { 0x14A6, "Interface Masters, Inc." }, + { 0x14A7, "LanReady Technologies, Inc." }, + { 0x14A8, "1C Company" }, + { 0x14A9, "Smar Research Corp." }, + { 0x14AA, "WideView Technology Inc." }, + { 0x14AB, "Technisches Buero Koenig" }, + { 0x14AC, "Coolstf.com" }, + { 0x14AD, "CTK Corporation" }, + { 0x14AE, "Printronix Inc." }, + { 0x14AF, "ATP Electronics Inc." }, + { 0x14B0, "StarTech.com Ltd." }, + { 0x14B1, "I.E. Gesellschaft fuer Industrieelektronik mbH" }, + { 0x14B2, "Alpha Networks Inc." }, + { 0x14B3, "CHUO ELECTRIC WORKS CO., LTD." }, + { 0x14B4, "Appliances Corp." }, + { 0x14B5, "NTS Telecom" }, + { 0x14B6, "Mimic Technologies Inc." }, + { 0x14B7, "In2Games Limited" }, + { 0x14B8, "UNITEK TECHNOLOGY CORPORATION" }, + { 0x14B9, "BP Microsystems" }, + { 0x14BA, "FLOVEL CO., LTD." }, + { 0x14BB, "Assembly Tech. Co., Ltd." }, + { 0x14BC, "NordNav Technologies AB" }, + { 0x14BD, "Eintech Co., Ltd." }, + { 0x14BE, "Crestron Electronics, Inc." }, + { 0x14BF, "Everbee Networks" }, + { 0x14C0, "Rockwell Automation, Inc." }, + { 0x14C1, "SOHYA TECHNOLOGY CO., LTD." }, + { 0x14C2, "Gemlight Computer Ltd." }, + { 0x14C3, "VOXELLE LTD." }, + { 0x14C4, "CLOVER Electronics Co., Ltd." }, + { 0x14C5, "AudioControl" }, + { 0x14C6, "Trigon Components, Inc." }, + { 0x14C7, "Hartmann GmbH" }, + { 0x14C8, "Zytronic Displays Limited" }, + { 0x14C9, "IXOS Ltd. Bvi" }, + { 0x14CA, "Technol Seven Co., Ltd." }, + { 0x14CB, "Dynapoint, Inc." }, + { 0x14CC, "WIN TONG ELECTRONICS CO., LTD." }, + { 0x14CD, "MOAI ELECTRONICS CORPORATION" }, + { 0x14CE, "Spectra, Inc." }, + { 0x14CF, "Measurement Systems Inc." }, + { 0x14D0, "Dentrix Dental Systems, Inc." }, + { 0x14D1, "Maximo Products LLC" }, + { 0x14D2, "BITS CO., LTD." }, + { 0x14D3, "Y2 Corporation" }, + { 0x14D4, "Telequip Corporation" }, + { 0x14D5, "Electronic Theatre Controls" }, + { 0x14D6, "Beijing Zhijiu Technology Co., Ltd." }, + { 0x14D7, "Toppan Printing Co., Ltd." }, + { 0x14D8, "JAMER INDUSTRIES CO., LTD." }, + { 0x14D9, "Advanced Flash Memory Card Technology Ltd." }, + { 0x14DA, "Horng Technical Enterprise Co., Ltd." }, + { 0x14DB, "TOA Musendenki Co., Ltd." }, + { 0x14DC, "Ftech Co., Ltd." }, + { 0x14DD, "Raritan Computer, Inc." }, + { 0x14DE, "Jetway Information Co., Ltd." }, + { 0x14DF, "COMPRION GmbH" }, + { 0x14E0, "Winradio Communications" }, + { 0x14E1, "Imagination Broadway Ltd" }, + { 0x14E2, "Avistar Communications Corporation" }, + { 0x14E3, "Medmont Pty Ltd." }, + { 0x14E4, "S.CAM Co., Ltd." }, + { 0x14E5, "Zinitix Co., Ltd" }, + { 0x14E6, "Micromed Biotecnologia Ltda." }, + { 0x14E7, "ISS Incorporated" }, + { 0x14E8, "Animated Lighting LC" }, + { 0x14E9, "Lifetouch, Inc." }, + { 0x14EA, "Kosaka Laboratory Ltd." }, + { 0x14EB, "Pendulum Instruments AB" }, + { 0x14EC, "Vansco Electronics Ltd." }, + { 0x14ED, "Shure Inc." }, + { 0x14EE, "INFORAD Ltd." }, + { 0x14EF, "AVICLink Corporation" }, + { 0x14F0, "GE" }, + { 0x14F1, "America Hears, LLC." }, + { 0x14F2, "Axess AG" }, + { 0x14F3, "BAP IMAGE SYSTEMS" }, + { 0x14F4, "Accell Corporation" }, + { 0x14F5, "SourceQuest, Inc." }, + { 0x14F6, "Symbium Corporation" }, + { 0x14F7, "TechniSat Digital GmbH" }, + { 0x14F8, "Chenrol Electric Wire & Cable Co., Ltd." }, + { 0x14F9, "Full Conductor Electric Appliance Manufacturer" }, + { 0x14FA, "The Wild Divine Project" }, + { 0x14FB, "JAI" }, + { 0x14FC, "Signami LLC" }, + { 0x14FD, "IPC Information Systems" }, + { 0x14FE, "Madrics Media GmbH Europe" }, + { 0x14FF, "Twinhead International Corp." }, + { 0x1500, "Ellisys" }, + { 0x1501, "Pine-Tum Enterprise Co., Ltd." }, + { 0x1502, "Peavey Electronics" }, + { 0x1503, "Stretch Inc." }, + { 0x1504, "Bixolon Co., Ltd." }, + { 0x1505, "Extraordinary Technologies Pty. Ltd.-Trading as Halcro" }, + { 0x1506, "T.D. Technecon Ltd." }, + { 0x1507, "APIM INFORMATIQUE" }, + { 0x1508, "MAATEL" }, + { 0x1509, "LI-COR Biosciences, Inc." }, + { 0x150A, "TiVo Inc." }, + { 0x150B, "COLLEX COMMUNICATION CORP." }, + { 0x150C, "Brightwell Dispenses Ltd." }, + { 0x150D, "PR Electronics A/S" }, + { 0x150E, "Ono Sokki Co., Ltd." }, + { 0x150F, "Nidec Nemicon Corporation" }, + { 0x1510, "RACEWOOD TELECOM CO., LTD." }, + { 0x1511, "BridgeCo, AG" }, + { 0x1512, "Software Technologies Group, Inc." }, + { 0x1513, "Hypercom" }, + { 0x1514, "Microsemi, SOC Products Group" }, + { 0x1515, "Hexon Media Pte Ltd" }, + { 0x1516, "Skymedi Corporation" }, + { 0x1517, "Precisa Instruments AG" }, + { 0x1518, "Cheshire Engineering Corporation" }, + { 0x1519, "Comneon GmbH Co., Ohg." }, + { 0x151A, "RoyalTek Company Ltd." }, + { 0x151B, "HOSTNET CO." }, + { 0x151C, "VeriSilicon Holdings Co., Ltd." }, + { 0x151D, "P W Allen & Co." }, + { 0x151E, "Circad Design Ltd." }, + { 0x151F, "Opal Kelly Incorporated" }, + { 0x1520, "Bitwire Corp." }, + { 0x1521, "S++ Simulation Services" }, + { 0x1522, "Educational Insights" }, + { 0x1523, "Hitachi High-Tech Science Corporation" }, + { 0x1524, "SCIENTEX Inc." }, + { 0x1525, "Newson Engineering NV" }, + { 0x1526, "ARDUC Co., Ltd." }, + { 0x1527, "iQue Ltd." }, + { 0x1528, "HighAndes Limited" }, + { 0x1529, "UBIQUAM CO., LTD." }, + { 0x152A, "Thesycon Systemsoftware & Consulting GmbH" }, + { 0x152B, "MIR-Medical International Research" }, + { 0x152C, "titel++" }, + { 0x152D, "JMicron Technology Corp." }, + { 0x152E, "HLDS (Hitachi-LG Data Storage, Inc.)" }, + { 0x152F, "PRO-MECH CORPORATION" }, + { 0x1530, "Martsoft Corp." }, + { 0x1531, "MICRODIA Ltd." }, + { 0x1532, "Razer (Asia-Pacific) Pte Ltd." }, + { 0x1533, "AEPTEC Microsystems, Inc." }, + { 0x1534, "Advanced Research Corporation" }, + { 0x1535, "Practical Engineering Incorporated" }, + { 0x1536, "Neonode Technologies AB" }, + { 0x1537, "Power Up Manufacturing" }, + { 0x1538, "IES Elektronikentwicklung" }, + { 0x1539, "AFG-Engineering GmbH" }, + { 0x153A, "WMS Gaming Inc." }, + { 0x153B, "ERCO Leuchten GmbH" }, + { 0x153C, "Guger Technologies OEG" }, + { 0x153D, "Adam Tech" }, + { 0x153E, "abKey ptd ltd." }, + { 0x153F, "UNIBRAIN S.A." }, + { 0x1540, "Phihong Technology Co., Ltd." }, + { 0x1541, "Better Light, Inc." }, + { 0x1542, "Gemini Industries, Inc." }, + { 0x1543, "Buxco Research Systems" }, + { 0x1544, "Alphamosaic Ltd." }, + { 0x1545, "Kistler Instrumente AG" }, + { 0x1546, "u-blox AG" }, + { 0x1547, "S. Goers IT-Solutions" }, + { 0x1548, "Centrepoint Technologies" }, + { 0x1549, "Beamex Oy Ab" }, + { 0x154A, "ID Innovations Incorporated" }, + { 0x154B, "PNY Technologies Inc." }, + { 0x154C, "AutoXray Inc." }, + { 0x154D, "Rapid Conn, Connect County Holdings Bhd" }, + { 0x154E, "D & M Holdings, Inc." }, + { 0x154F, "Shandong New Beiyang Information Technology Co., Ltd." }, + { 0x1550, "Cardinal Health, Inc." }, + { 0x1551, "SAIC/IISBU" }, + { 0x1552, "DALLAB (M) SDN BHD (587734-A)" }, + { 0x1553, "Raytheon Commercial Infrared" }, + { 0x1554, "Prolink Microsystems Corporation" }, + { 0x1555, "OWEN Ltd." }, + { 0x1556, "CERN" }, + { 0x1557, "OQO" }, + { 0x1558, "Microbus Designs Ltd." }, + { 0x1559, "The Toro Company" }, + { 0x155A, "ELDAT GmbH" }, + { 0x155B, "Shanghai Huahong Integrated Circuit Co., Ltd." }, + { 0x155C, "Meyers Technology" }, + { 0x155D, "National Rejectors, Inc. GmbH" }, + { 0x155E, "DUPLO SEIKO CORPORATION" }, + { 0x155F, "Cobra Electronics Corporation" }, + { 0x1560, "Supra, A UTC Fire & Security Company" }, + { 0x1561, "LaunchPadOffice Inc." }, + { 0x1562, "Infowize Technologies Corporation" }, + { 0x1563, "Micronet Corporation" }, + { 0x1564, "Gizmondo Europe Ltd." }, + { 0x1565, "Advance Modules" }, + { 0x1566, "WIN ACCORD LTD." }, + { 0x1567, "MUTOH Industries Ltd." }, + { 0x1568, "Sunf Pu Technology (Dong-Guan) Co., Ltd." }, + { 0x1569, "Mad City Labs, Inc." }, + { 0x156A, "Logical Solutions, Inc." }, + { 0x156B, "Cairn Research Ltd." }, + { 0x156C, "Meade Instruments Corp." }, + { 0x156D, "OMICRON electronics GmbH" }, + { 0x156E, "MVox Electronics" }, + { 0x156F, "Quantum Corporation" }, + { 0x1570, "ALLTOP TECHNOLOGY CO., LTD." }, + { 0x1571, "NIKON-TRIMBLE CO., LTD." }, + { 0x1572, "Ricreations, Inc." }, + { 0x1573, "Gradiente Eletronica S.A." }, + { 0x1574, "HKW-Elektronik GmbH" }, + { 0x1575, "Video Associates Labs, Inc." }, + { 0x1576, "Maretron" }, + { 0x1577, "MIYUKI ELEX CO., LTD." }, + { 0x1578, "Beijing Huaqi Information Digital Technology Co., Ltd." }, + { 0x1579, "Reputed Industrial Company Limited" }, + { 0x157A, "Lowrance Electronics, Inc." }, + { 0x157B, "Ketron SRL" }, + { 0x157C, "Eurosoft (UK) Ltd." }, + { 0x157D, "Tokyo Sokuteikizai Co., Ltd." }, + { 0x157E, "U-MEDIA Communications, Inc." }, + { 0x157F, "Levon Limited" }, + { 0x1580, "Real Time Logic, Inc." }, + { 0x1581, "IGB Communication Co., Ltd." }, + { 0x1582, "Asia Pacifc Microsystems, Inc." }, + { 0x1583, "EUCHNER GmbH & Co. KG" }, + { 0x1584, "Prueftechnik AG" }, + { 0x1585, "IKeyInfinity Inc." }, + { 0x1586, "Palconn Technology Co., Ltd." }, + { 0x1587, "SMA Solar Technology AG" }, + { 0x1588, "Fine Instruments Corporation" }, + { 0x1589, "Arcus Technology Inc." }, + { 0x158A, "BOBE Industrie-Elektronik" }, + { 0x158B, "Righttag Inc." }, + { 0x158C, "LINFOS CO., LTD." }, + { 0x158D, "Oakley Inc." }, + { 0x158E, "Acterna Germany GmbH" }, + { 0x158F, "Tai Yip Electrical Co., Ltd." }, + { 0x1590, "Onsu Data Telecommunication Technology (Shenzhen) Fty." }, + { 0x1591, "Advanced Product Design & Mfg. Inc." }, + { 0x1592, "Tokyo Drawing Ltd." }, + { 0x1593, "Vector International bvba" }, + { 0x1594, "Lockheed Martin Missiles & Fire Control" }, + { 0x1595, "Flexiworld Technologies, Inc." }, + { 0x1596, "Kilodyne LLC" }, + { 0x1597, "KCodes Corporation" }, + { 0x1598, "Kunshan Guoji Electronics Co., Ltd." }, + { 0x1599, "ANRITSU METER CO., LTD." }, + { 0x159A, "SkuTek Instrumentation" }, + { 0x159B, "Zitte Corporation" }, + { 0x159C, "Binary Acoustic Technology" }, + { 0x159D, "Boone Cable Works & Electronics" }, + { 0x159E, "SmartSwing, Inc." }, + { 0x159F, "Beijer Electronics AB" }, + { 0x15A0, "Zarlink Semiconductor" }, + { 0x15A1, "Nicety Technologies Inc." }, + { 0x15A2, "Freescale Semiconductor, Inc." }, + { 0x15A3, "Larson Davis, Inc." }, + { 0x15A4, "Afa Technologies, Inc." }, + { 0x15A5, "CIT Engineering NV" }, + { 0x15A6, "Unicos Corporation" }, + { 0x15A7, "APPSware Wireless LLC dba Apriva" }, + { 0x15A8, "Shen Zhen Teamspower Electronics Co., Ltd." }, + { 0x15A9, "Gemtek Technology Co., Ltd." }, + { 0x15AA, "GuangDong Ya Lian Technology Co., Ltd" }, + { 0x15AB, "Virgin HealthMiles, Inc." }, + { 0x15AC, "Smartware" }, + { 0x15AD, "Bleile Datentechnik GmbH" }, + { 0x15AE, "KAYSER-THREDE GMBH" }, + { 0x15AF, "Jenaer Antriebstechnik GmbH" }, + { 0x15B0, "Pacific Instruments, Inc." }, + { 0x15B1, "MiTAC Technology Corporation" }, + { 0x15B2, "Audio Dev AB" }, + { 0x15B3, "GL Sciences Inc." }, + { 0x15B4, "Orient Power Multimedia Ltd." }, + { 0x15B5, "ANUBIS ELECTRONIC GmbH" }, + { 0x15B6, "Dialog Semiconductor GmbH" }, + { 0x15B7, "Hyper Stimulator International Pty Ltd." }, + { 0x15B8, "Serome Electronics, Inc." }, + { 0x15B9, "USD Corporation" }, + { 0x15BA, "Olimex Ltd." }, + { 0x15BB, "CopyPro , Inc." }, + { 0x15BC, "Daktronics Inc." }, + { 0x15BD, "Sigmaelectronics Co., Ltd." }, + { 0x15BE, "EssNet Interactive AB" }, + { 0x15BF, "ESA, Inc." }, + { 0x15C0, "CJM" }, + { 0x15C1, "Amirix Systems Inc." }, + { 0x15C2, "SoundGraph, Inc." }, + { 0x15C3, "m.u.t - GmbH" }, + { 0x15C4, "Global Marketing Alliance, Inc." }, + { 0x15C5, "Pressure Profile Systems, Inc." }, + { 0x15C6, "Laboratoires MXM" }, + { 0x15C7, "IRI-Ubiteq, Inc." }, + { 0x15C8, "KTF Technologies" }, + { 0x15C9, "D-Box Technologies" }, + { 0x15CA, "TEXTECH INTERNATIONAL LTD." }, + { 0x15CB, "Activis Polska" }, + { 0x15CC, "GL Communications Inc." }, + { 0x15CD, "DeFelsko Corporation" }, + { 0x15CE, "Oriental R&D Co., Ltd." }, + { 0x15CF, "AVTOR Ltd.." }, + { 0x15D0, "AIRSTAR Inc." }, + { 0x15D1, "Hokuyo Automatic Co., Ltd." }, + { 0x15D2, "REA Elektronik GmbH" }, + { 0x15D3, "Symmetric Research" }, + { 0x15D4, "Opinionmeter International, Ltd." }, + { 0x15D5, "Coulomb Electronics Ltd." }, + { 0x15D6, "Fitness Expert" }, + { 0x15D7, "amaxa GmbH" }, + { 0x15D8, "Grundig Business Systems GmbH" }, + { 0x15D9, "Apexone Microelectronics Inc." }, + { 0x15DA, "Cooper - Atkins Corporation" }, + { 0x15DB, "Philip Harris Education" }, + { 0x15DC, "Hynix Semiconductor Inc." }, + { 0x15DD, "Axona Limited" }, + { 0x15DE, "Spatial Freedom, Inc." }, + { 0x15DF, "Helmut Fischer GmbH + Co. KG" }, + { 0x15E0, "Seong Ji Industrial Co., Ltd." }, + { 0x15E1, "RSA Security Inc." }, + { 0x15E2, "Bionopoly LLC" }, + { 0x15E3, "NEURICAM SPA" }, + { 0x15E4, "Numark Industries" }, + { 0x15E5, "Micro Systems Inc." }, + { 0x15E6, "Turnkey Ltd." }, + { 0x15E7, "Media Systems Ltd." }, + { 0x15E8, "Micro Tools Inc." }, + { 0x15E9, "Pacific Digital Corp." }, + { 0x15EA, "C-guys Inc." }, + { 0x15EB, "VIA Telecom" }, + { 0x15EC, "Belcarra Technologies Corp." }, + { 0x15ED, "UCA Technology Inc." }, + { 0x15EE, "Quorum Communications, Inc." }, + { 0x15EF, "MSilicon Electronics, Inc." }, + { 0x15F0, "Technex Lab Co., Ltd." }, + { 0x15F1, "Mortara Instrument, Inc." }, + { 0x15F2, "Chyron Corp." }, + { 0x15F3, "AquaCube Inc." }, + { 0x15F4, "Computer & Entertainment, Inc." }, + { 0x15F5, "Mobitek Communication Corp." }, + { 0x15F6, "ASICS World Services Ltd." }, + { 0x15F7, "HANTEL CO., LTD." }, + { 0x15F8, "Vianet, Inc." }, + { 0x15F9, "SunCorp Industrial Limited" }, + { 0x15FA, "Department of Defense" }, + { 0x15FB, "R-Quest Technologies , LLC" }, + { 0x15FC, "Humen Xintai Electrical Wires Factory" }, + { 0x15FD, "XEMAX Co., Ltd." }, + { 0x15FE, "Bio-Rad Laboratories Deeside" }, + { 0x15FF, "Heartsine Technologies Ltd." }, + { 0x1600, "Monisys Limited" }, + { 0x1601, "Avenues in Leather" }, + { 0x1602, "CompUSA Inc." }, + { 0x1603, "ERGODEX Corp." }, + { 0x1604, "Kyokko Seiko Co., Ltd." }, + { 0x1605, "Acces I/O Products, Inc." }, + { 0x1606, "UMAX Data Systems Inc." }, + { 0x1607, "ESE Corporate" }, + { 0x1608, "Inside Out Networks, a division of Digi International" }, + { 0x1609, "K-byte (ACI Group)" }, + { 0x160A, "VIA Networking Technologies, Inc." }, + { 0x160B, "CSI Wireless Inc." }, + { 0x160C, "Shanghai Tiananxin Information & Tech., Co., Ltd." }, + { 0x160D, "Samtec" }, + { 0x160E, "INRO Consultants Inc." }, + { 0x160F, "Strand Lighting Limited" }, + { 0x1610, "Q-Sense AB" }, + { 0x1611, "Vita-Mix Corporation" }, + { 0x1612, "Soft DB Inc." }, + { 0x1613, "Airconnect Solutions (Asia) Ltd." }, + { 0x1614, "Amoi Electronics Co., Ltd." }, + { 0x1615, "Rock Data Services Ltd." }, + { 0x1616, "Cute Mobile Corp." }, + { 0x1617, "Navman" }, + { 0x1618, "Redpine Signals, Inc." }, + { 0x1619, "L & K Precision Technology Co., Ltd." }, + { 0x161A, "Celeraise Investments Ltd." }, + { 0x161B, "MYCOM, INC." }, + { 0x161C, "DigiTech Systems Co., Ltd." }, + { 0x161D, "Delfin Technologies Ltd." }, + { 0x161E, "Aerotech Inc." }, + { 0x161F, "Prosisa International LLC" }, + { 0x1620, "Accesstek Inc." }, + { 0x1621, "Wionics Research" }, + { 0x1622, "California Instruments" }, + { 0x1623, "Mindtech Limited" }, + { 0x1624, "AIOI Systems, USA Corp." }, + { 0x1625, "ViaSat UK" }, + { 0x1626, "Advance Data Technology Corporation" }, + { 0x1627, "IPextreme, Inc." }, + { 0x1628, "Stonestreet One, Inc." }, + { 0x1629, "Erae Electronics" }, + { 0x162A, "Airgo Networks Inc." }, + { 0x162B, "Acksys" }, + { 0x162C, "Ecler Laboratorio de Electroacustica S.A." }, + { 0x162D, "Control Instruments Development (Pty) Ltd." }, + { 0x162E, "Joytech Europe Ltd." }, + { 0x162F, "WiQuest Communications, Inc." }, + { 0x1630, "QformX" }, + { 0x1631, "Focus Enhancements" }, + { 0x1632, "Data Ray Inc." }, + { 0x1633, "AIM GmbH" }, + { 0x1634, "ABB Switzerland Ltd." }, + { 0x1635, "Doble Engineering Co." }, + { 0x1636, "Kobe-Addtech Co., Ltd." }, + { 0x1637, "LZAE LUMEL SA" }, + { 0x1638, "Skyworks Solutions" }, + { 0x1639, "BeRiver Electronics Co., Ltd." }, + { 0x163A, "Traficon N.V." }, + { 0x163B, "Controlled Speed Engineering Ltd." }, + { 0x163C, "Watchdata System Co., Ltd." }, + { 0x163D, "Million Tech Dev. Ltd." }, + { 0x163E, "Dezhou HongJu Communication Technology Co., Ltd." }, + { 0x163F, "AVEX Technologies, Inc." }, + { 0x1640, "M3 Electronics, Inc." }, + { 0x1641, "eMagin Corporation" }, + { 0x1642, "AquaSensors LLC" }, + { 0x1643, "Sanwa Newtec Co., Ltd." }, + { 0x1644, "Active Technologies SRL" }, + { 0x1645, "Smiths Heimann Biometrics GmbH" }, + { 0x1646, "Altronic, Inc." }, + { 0x1647, "Horizon Navigation, Inc." }, + { 0x1648, "Wood Head Software & Electronics" }, + { 0x1649, "Softec Microsystems" }, + { 0x164A, "ChipX" }, + { 0x164B, "Lytech Technology Inc." }, + { 0x164C, "Matrix Vision GmbH" }, + { 0x164D, "DASAN Networks, Inc." }, + { 0x164E, "Picotest Corp." }, + { 0x164F, "Kinkei System Co., Ltd." }, + { 0x1650, "Remopro Technology Inc." }, + { 0x1651, "PACOMP" }, + { 0x1652, "EFull Tech. Corp. Ltd." }, + { 0x1653, "Nissho Electronics Co., Ltd." }, + { 0x1654, "Stamer Musikanlagen GmbH" }, + { 0x1655, "Dtron Co., Ltd." }, + { 0x1656, "QSC Audio Products, Inc." }, + { 0x1657, "Struck Innovative Systeme GmbH" }, + { 0x1658, "Grayhill Inc." }, + { 0x1659, "Lathem Time Corp." }, + { 0x165A, "E.D.P. SRL" }, + { 0x165B, "Frontier Design Group" }, + { 0x165C, "Kondo Kagaku Co., Ltd." }, + { 0x165D, "Orange Tree Technologies Ltd." }, + { 0x165E, "Pangolin" }, + { 0x165F, "Ansync Inc." }, + { 0x1660, "Creatix Polymedia GmbH" }, + { 0x1661, "DVS Korea Co., Ltd." }, + { 0x1662, "Positivo Informatica LTDA" }, + { 0x1663, "Sercel, Inc." }, + { 0x1664, "ARGOX INFORMATION CO., LTD." }, + { 0x1665, "General Dynamics Canada" }, + { 0x1666, "Vanguard Instruments Co., Inc." }, + { 0x1667, "GIGA-TMS, INC." }, + { 0x1668, "Actiontec Electronics, Inc." }, + { 0x1669, "PiKRON s.r.o." }, + { 0x166A, "Clipsal Integrated Systems" }, + { 0x166B, "PedalPax Corporation" }, + { 0x166C, "Technology Driven Solutions Ltd" }, + { 0x166D, "MCS Logic Inc." }, + { 0x166E, "SerComm Corporation" }, + { 0x166F, "Idetech Europe S.A." }, + { 0x1670, "Hach Company" }, + { 0x1671, "Telular Corporation" }, + { 0x1672, "MBS GmbH" }, + { 0x1673, "ROBOTIKER" }, + { 0x1674, "Pantone, Inc." }, + { 0x1675, "SE-IR Corporation" }, + { 0x1676, "I-Ware Laboratory Co., Ltd." }, + { 0x1677, "China Integrated Circuit Design Corp., Ltd." }, + { 0x1678, "Matsunichi Information Technology (Shenzhen) Co., Ltd." }, + { 0x1679, "Total Phase" }, + { 0x167A, "USBWARE" }, + { 0x167B, "Pure Digital Technologies" }, + { 0x167C, "Vionics" }, + { 0x167D, "SIM Security & Electronic System GmbH" }, + { 0x167E, "Videa Technology Inc." }, + { 0x167F, "Actigraph, LLC" }, + { 0x1680, "KaVo Dental GmbH" }, + { 0x1681, "Prevo Technologies, Inc." }, + { 0x1682, "Maxwise Production Enterprise Ltd." }, + { 0x1683, "DualCor Technologies, Inc." }, + { 0x1684, "Godspeed Computer Corp." }, + { 0x1685, "Tanic Electroics Ltd." }, + { 0x1686, "ZOOM Corporation" }, + { 0x1687, "Kingmax Digital Inc." }, + { 0x1688, "AerotechTelub AB" }, + { 0x1689, "Griffin International Companies, Inc." }, + { 0x168A, "Veeco Instruments" }, + { 0x168B, "BTC Secu Co., Ltd." }, + { 0x168C, "Tabor Electroics Ltd." }, + { 0x168D, "YSI, Inc." }, + { 0x168E, "iMetrikus Inc." }, + { 0x168F, "ETA S.A. Manufacture Horlogere Suisse" }, + { 0x1690, "Simple Solutions" }, + { 0x1691, "Landers Instruments" }, + { 0x1692, "Weatherford" }, + { 0x1693, "Zultys Technologies" }, + { 0x1694, "Cassidian Communications" }, + { 0x1695, "FATAR, S.r.l." }, + { 0x1696, "Hitachi Advanced Digital, Inc." }, + { 0x1697, "VTEC TEST, INC." }, + { 0x1698, "Eurosmart" }, + { 0x1699, "United RadioTek Inc." }, + { 0x169A, "Ten X Technology Inc." }, + { 0x169B, "aitronic GmbH" }, + { 0x169C, "DMS" }, + { 0x169E, "Groupics.com, Inc." }, + { 0x169F, "Monolith Inc." }, + { 0x16A0, "Real Thoughts GmbH" }, + { 0x16A1, "Trilithic, Inc." }, + { 0x16A2, "Sypris Test and Measurement (FW Bell)" }, + { 0x16A3, "B & W Tek Inc." }, + { 0x16A4, "Sagutech Microsystems" }, + { 0x16A5, "Shenzhen Zhengerya Technology Co., Ltd." }, + { 0x16A6, "UNIGRAF OY" }, + { 0x16A7, "Sauer-Danfoss" }, + { 0x16A8, "Nice Systems" }, + { 0x16A9, "Worth-Pfaff Innovations, Inc." }, + { 0x16AA, "Symtx Inc." }, + { 0x16AB, "InnoWireless Co. Ltd." }, + { 0x16AC, "Dongguan ChingLung Wire & Cable Co., Ltd." }, + { 0x16AD, "Siemens VDO Trading GmbH" }, + { 0x16AE, "ELSA Japan Inc." }, + { 0x16AF, "Intelligent Mechatronic Systems" }, + { 0x16B0, "Infosight Corp." }, + { 0x16B1, "Cami Research Inc." }, + { 0x16B2, "Bruxton Corporation" }, + { 0x16B3, "Eizoken Inc." }, + { 0x16B4, "Digital Cube" }, + { 0x16B5, "PerSen Technologies, Inc." }, + { 0x16B6, "Nexus Technology Inc." }, + { 0x16B7, "Pulsafeeder Inc." }, + { 0x16B8, "Honeywell Life Safety" }, + { 0x16B9, "Origin Technologies Limited" }, + { 0x16BA, "SmarTec" }, + { 0x16BB, "Tomra Systems ASA" }, + { 0x16BC, "JOBO AG" }, + { 0x16BD, "Leica Geosystems AG" }, + { 0x16BE, "RyuSyo Industrial Co., Ltd." }, + { 0x16BF, "CAST, INC." }, + { 0x16C0, "Van Ooijen Technische Informatica" }, + { 0x16C1, "Lucas-Nuelle GmbH" }, + { 0x16C2, "Amphenol-Data Telecom" }, + { 0x16C3, "Nihon Kaiheiki Ind. Co., Ltd." }, + { 0x16C4, "SavaJe Technologies, Inc." }, + { 0x16C5, "Cryptek Inc." }, + { 0x16C6, "NDS Surgical Imaging, LLC" }, + { 0x16C7, "Crystal Technology, Inc." }, + { 0x16C8, "Technische Universiteit Eindhoven" }, + { 0x16C9, "OCT Co., Ltd." }, + { 0x16CA, "Wireless Cables Inc." }, + { 0x16CB, "Highwater Designs Limited" }, + { 0x16CC, "silex technology, Inc." }, + { 0x16CD, "Brian Moore Guitars, Inc." }, + { 0x16CE, "IPFlex Inc." }, + { 0x16CF, "YAZAKI PARTS CO., LTD." }, + { 0x16D1, "SUPREMA, INC." }, + { 0x16D2, "TOMEY" }, + { 0x16D3, "Frontline Test Equipment, Inc." }, + { 0x16D4, "SRTechnologies" }, + { 0x16D5, "AnyDATA Corporation" }, + { 0x16D6, "Jablotron" }, + { 0x16D7, "Aprilis, Inc." }, + { 0x16D8, "CMOTECH CO., LTD." }, + { 0x16D9, "A7 Engineering, Inc." }, + { 0x16DA, "Linkam Scientific Instruments Ltd." }, + { 0x16DB, "Eridon Corporation" }, + { 0x16DC, "W-IE-NE-R, Plein & Baus GmbH" }, + { 0x16DD, "YOSHIDA SEIKI CO., LTD." }, + { 0x16DE, "Schneider Electric" }, + { 0x16DF, "King Billion Electronics Co., Ltd." }, + { 0x16E0, "Lumex Ltd." }, + { 0x16E1, "Bed Check Corporation" }, + { 0x16E2, "Hitachi I E Systems Co., Ltd." }, + { 0x16E3, "ITM Inc." }, + { 0x16E4, "Franklin Electric Co., Inc." }, + { 0x16E5, "TOKYO KEIKI RAIL TECHNO INC." }, + { 0x16E6, "Diginfo Technology Corporation" }, + { 0x16E7, "United Keys, Inc." }, + { 0x16E8, "Frontier Information Enterprise, Inc." }, + { 0x16E9, "Dr. Gal Ben-David" }, + { 0x16EA, "Avionica, Inc." }, + { 0x16EB, "Helvar" }, + { 0x16EC, "ASAHI GLASS CO., LTD." }, + { 0x16ED, "Parker Vision Inc." }, + { 0x16EE, "Ryvor Corp." }, + { 0x16EF, "Global Safety & Security Solutions OY" }, + { 0x16F0, "GN ReSound" }, + { 0x16F1, "Versus Technology, Inc." }, + { 0x16F2, "St. Jude Medical AB" }, + { 0x16F3, "Hammer Storage/Bell Microproducts" }, + { 0x16F4, "Lineeye Co., Ltd." }, + { 0x16F5, "Futurelogic Inc." }, + { 0x16F6, "Shin Tek Inc." }, + { 0x16F7, "Japan Gals Co., Ltd." }, + { 0x16F8, "Ever Bright Wire Factory" }, + { 0x16F9, "Astrosys International Limited" }, + { 0x16FA, "Shachihata Inc." }, + { 0x16FB, "MICRONIX CORPORATION" }, + { 0x16FC, "TRICOM TECHNOLOGIES, INC." }, + { 0x16FD, "Reakin Technology Corporation" }, + { 0x16FE, "Su Zhou Song Qing Electronical Co., Ltd." }, + { 0x16FF, "Ultimate Technology Corp." }, + { 0x1700, "Hunt Engineering (UK) Ltd." }, + { 0x1701, "Peyroutet Telecom" }, + { 0x1702, "Softcare Ltd." }, + { 0x1703, "NormSoft, Inc." }, + { 0x1704, "ANIMATICS CORP." }, + { 0x1705, "Aerosonic Corporation" }, + { 0x1706, "BlueView Technologies, Inc." }, + { 0x1707, "ARTIMI" }, + { 0x1708, "Mibudenki Industrial Co., Ltd." }, + { 0x1709, "Sanmina-SCI" }, + { 0x170A, "MAXTEK, INC." }, + { 0x170B, "Phonic Corp." }, + { 0x170C, "BlueTree Wireless Data" }, + { 0x170D, "Avnera" }, + { 0x170E, "Iris Corporation Berhad" }, + { 0x170F, "UbiBro Technolgies Inc." }, + { 0x1710, "AZIO Corporation" }, + { 0x1711, "Leica Microsystems CMS GmbH" }, + { 0x1712, "Fujitsu LSI Technology Ltd." }, + { 0x1713, "Enter Tech Co., Ltd" }, + { 0x1714, "iCRco" }, + { 0x1715, "NL Technology" }, + { 0x1716, "LHR Technologies" }, + { 0x1717, "Formats Unlimited, Inc." }, + { 0x1718, "Mobile Doctor Co., Ltd." }, + { 0x1719, "American Technology Corp." }, + { 0x171A, "PSi Printer Systems international GmbH" }, + { 0x171B, "NT Ware Systemprogrammierung GmbH" }, + { 0x171C, "IER" }, + { 0x171E, "PACIFIC CORPORATION" }, + { 0x171F, "CHIPNUTS TECHNOLOGY INC." }, + { 0x1720, "Innova Electronics Corp." }, + { 0x1721, "ELAD SRL" }, + { 0x1722, "Axicon Auto ID LTD" }, + { 0x1723, "Datatronics Technology, Inc" }, + { 0x1724, "Lumenera Corporation" }, + { 0x1725, "HI-TECH Software" }, + { 0x1726, "Axesstel, Inc." }, + { 0x1727, "RiCHIP Incorporated" }, + { 0x1728, "BYTE TOOLS INC." }, + { 0x1729, "CONSULTRONICS EUROPE LTD." }, + { 0x172A, "wenglor sensoric gmbh" }, + { 0x172B, "CompuSoft A/S" }, + { 0x172C, "Silicon Optix" }, + { 0x172D, "AccFast Technology Corp." }, + { 0x172E, "ELECTION SYSTEMS & Software" }, + { 0x172F, "WALTOP International Corporation" }, + { 0x1730, "MERCURY" }, + { 0x1731, "DATA DISPLAY AG" }, + { 0x1732, "NETENRICH INC." }, + { 0x1733, "NUBYTECH INC." }, + { 0x1734, "IPdrum AB" }, + { 0x1735, "Satloc LLC (CSI Wireless)" }, + { 0x1736, "CANON IMAGING SYSTEMS INC." }, + { 0x1737, "Hong Kong Applied Science and Technology Research Inst." }, + { 0x1738, "Asicen Technology Corp." }, + { 0x1739, "Radiant Technologies Inc." }, + { 0x173A, "F. Hoffmann-La Roche AG" }, + { 0x173B, "Cadillac Jack Inc." }, + { 0x173C, "Signalcraft Technologies Inc." }, + { 0x173D, "Great Pleasure Electronics Co. LTD." }, + { 0x173E, "Devlin Electronics Ltd." }, + { 0x173F, "Peyer Engineering" }, + { 0x1740, "Senao International Co., Ltd." }, + { 0x1741, "Techino Science Co., Ltd." }, + { 0x1742, "Nippon Chemi-Con Corp." }, + { 0x1743, "General Atomics" }, + { 0x1744, "Sanwa Electronic Instrument Co. Ltd." }, + { 0x1745, "Video Simplex, Inc." }, + { 0x1746, "Edge Products" }, + { 0x1747, "CML MICROCIRCUITS (UK) LTD" }, + { 0x1748, "MQP Electronics Ltd." }, + { 0x1749, "MAGO MOBILE LTD" }, + { 0x174A, "Endress + Hauser" }, + { 0x174B, "BARACODA" }, + { 0x174C, "ASMedia Technology Inc." }, + { 0x174D, "Broadcast System & Design ApS" }, + { 0x174E, "Xi'an Tongshi Data Co., Ltd." }, + { 0x174F, "D-MAX Technology Co., Ltd." }, + { 0x1750, "Hirschmann Automation and Control GmbH" }, + { 0x1751, "EMPIRISOFT CORPORATION" }, + { 0x1752, "Liyitec Incorporated" }, + { 0x1753, "Tecvan Informatica LTDA" }, + { 0x1754, "GERSTEL GmbH & Co. KG" }, + { 0x1755, "Electronics and Telecommunication Research Institute" }, + { 0x1756, "ENENSYS Technologies" }, + { 0x1757, "ST-MICHAEL STRATEGIES" }, + { 0x1758, "FUTURECOM SYSTEMS GROUP INC." }, + { 0x1759, "LucidPort Technology, Inc." }, + { 0x175A, "Lantronix" }, + { 0x175B, "Dongguan Init Technology Co., Ltd." }, + { 0x175C, "Isolcell Italia SpA" }, + { 0x175D, "Caterpillar Inc." }, + { 0x175E, "AT KidSystems Inc." }, + { 0x175F, "I-BIT Corporation" }, + { 0x1760, "RAYLASE AG" }, + { 0x1761, "RC GROUP (Holdings) Limited" }, + { 0x1763, "USAF" }, + { 0x1764, "KANOMAX JAPAN INC." }, + { 0x1765, "VK Corporation" }, + { 0x1766, "Hip Interactive Inc." }, + { 0x1767, "KIS Photo Mc Group" }, + { 0x1769, "ARTEK Inc." }, + { 0x176A, "GLOBALSAT TECHNOLOGY CORPORATION" }, + { 0x176B, "ATOP ELECTRONICS CO., LTD." }, + { 0x176C, "Advanced Electronic Designs" }, + { 0x176D, "Mbridge Systems, Inc." }, + { 0x176E, "UD electronic corp." }, + { 0x176F, "Astralink Technology Pte Ltd" }, + { 0x1770, "precisionWave Corporation" }, + { 0x1771, "Shenzhen Alex Connector Co., Ltd." }, + { 0x1772, "System Level Solutions, Inc." }, + { 0x1773, "InSync Speech Technologies, Inc." }, + { 0x1774, "Strawberry Linux Co., Ltd." }, + { 0x1775, "RADAR-TRONIC KFT." }, + { 0x1776, "HYPERLABS, Inc." }, + { 0x1777, "Microscan Systems, Inc." }, + { 0x1778, "PChome Online Inc." }, + { 0x1779, "Optek Electronics Co., Ltd." }, + { 0x177A, "Explore Semiconductor, Inc." }, + { 0x177B, "Cetus Engineering" }, + { 0x177C, "AD Information & Communications Co., Ltd" }, + { 0x177D, "Delta Industrie Service" }, + { 0x177E, "mils electronic GmbH & Co Kg" }, + { 0x177F, "Sweex Europe B.V." }, + { 0x1780, "TENDYRON CORPORATION" }, + { 0x1781, "MECANIQUE" }, + { 0x1782, "Spreadtrum Hong Kong Limited" }, + { 0x1783, "Foster Flight, Inc." }, + { 0x1784, "TopSeed Technology Corp." }, + { 0x1785, "CARALLON LIMITED" }, + { 0x1786, "Xeltek Inc." }, + { 0x1787, "TRIDENT SYSTEMS, INC." }, + { 0x1788, "ShenZhen Litkconn Technology Co., Ltd." }, + { 0x1789, "Ascom (Schweiz) AG" }, + { 0x178A, "Prentke Romich Company" }, + { 0x178B, "Panduit Corp." }, + { 0x178C, "URTEK TECHNOLOGIES INC." }, + { 0x178D, "CEIVA Logic, Inc." }, + { 0x178E, "Movimento Group AB" }, + { 0x1790, "Ueda Japan Radio Co., Ltd." }, + { 0x1791, "SYNTHETIC PLANNING INDUSTRY CO., LTD." }, + { 0x1792, "LINK GmbH" }, + { 0x1793, "Heim Systems GmbH" }, + { 0x1794, "MA'AGALIM COMPUTER SYSTEMS Ltd." }, + { 0x1795, "INTEGRATION ASSOCIATES INCORPORATED" }, + { 0x1796, "Printrex, Inc." }, + { 0x1797, "JALCO CO., LTD." }, + { 0x1798, "TYPE TECHNOLOGY INC." }, + { 0x1799, "Thales Norway AS" }, + { 0x179A, "Conrad Electronic GmbH" }, + { 0x179B, "HANDSFULL TECHNOLOGY CORP." }, + { 0x179C, "Net-2Com Corporation" }, + { 0x179D, "Ricavision International Inc." }, + { 0x179E, "Silicon Engines" }, + { 0x179F, "CLIQ LIMITED" }, + { 0x17A0, "Samson Technologies Corp." }, + { 0x17A1, "Taiwan Advanced Sensors Corporation" }, + { 0x17A2, "Vantage Controls, Inc." }, + { 0x17A3, "OnTime tek Inc." }, + { 0x17A4, "Concept 2" }, + { 0x17A5, "Advanced Connection Technology Inc." }, + { 0x17A6, "Astron Clinica Ltd." }, + { 0x17A7, "MICOMSOFT CO., LTD." }, + { 0x17A8, "Kamstrup A/S" }, + { 0x17A9, "MULTIMEDIA GAMES, INC." }, + { 0x17AA, "SETEK Elektronik AB" }, + { 0x17AB, "i-Bulldog Co., Ltd." }, + { 0x17AC, "Dengen Automation Co., Ltd." }, + { 0x17AD, "TRIOC AB" }, + { 0x17AE, "NAD Electronics International/A Div. of Lenbrook Ind." }, + { 0x17AF, "GIGABYTE Communications Inc." }, + { 0x17B0, "Weinmann Geraete fuer Medizen GmbH+Co. KG" }, + { 0x17B1, "ViaSat, Inc." }, + { 0x17B2, "Metec GmbH" }, + { 0x17B3, "Grey Innovation Pty., Ltd." }, + { 0x17B4, "Apres Health & Fitness" }, + { 0x17B5, "Lunatone Industrielle Elektronik GmbH" }, + { 0x17B6, "Hydronix Limited" }, + { 0x17B7, "Sinter Information Corp." }, + { 0x17B8, "Trojan Technologies Private Limited" }, + { 0x17B9, "Green Bit S.p.A." }, + { 0x17BA, "Sauris GmbH" }, + { 0x17BB, "Weihai Dongxing Electronics Co., Ltd." }, + { 0x17BC, "Advanced Peripherals Technologies, Inc." }, + { 0x17BD, "Citron Electronic Co., Ltd." }, + { 0x17BE, "Dongguan Yangming Precision of Plastic Metal Elec Co Lt" }, + { 0x17BF, "Ampere Inc." }, + { 0x17C0, "ED Co., Ltd." }, + { 0x17C1, "Sirius XM Radio" }, + { 0x17C2, "Ingenient Technologies" }, + { 0x17C3, "SGB Group Ltd." }, + { 0x17C4, "VISIOWAVE SA" }, + { 0x17C5, "Hantle System Co., Ltd." }, + { 0x17C6, "Magnetox" }, + { 0x17C7, "AIM Infrarot-Module GmbH" }, + { 0x17C8, "Ringway Tech (JiangSu) Co., Ltd." }, + { 0x17C9, "Andros Incorporated" }, + { 0x17CA, "CyberPak Co." }, + { 0x17CB, "CHINA HUAXU GOLDEN CARD CO., LTD." }, + { 0x17CC, "Native Instruments Software Synthesis GmbH" }, + { 0x17CD, "Basler Electric" }, + { 0x17CE, "Keymile AG" }, + { 0x17CF, "Hip Hing Cable & Plug Mfy. Ltd." }, + { 0x17D0, "Sanford L.P." }, + { 0x17D1, "ViDisys GmbH" }, + { 0x17D2, "Radiometer Medical ApS" }, + { 0x17D3, "Korea Techtron Co., Ltd." }, + { 0x17D4, "Kenetics Innovations Pte. Ltd., Singapore" }, + { 0x17D5, "ImageMap Inc." }, + { 0x17D6, "Samsung Electronics Research Institute" }, + { 0x17D7, "Copley Controls Corp." }, + { 0x17D8, "Rapattoni Corporation" }, + { 0x17D9, "Rasteme Systems Co., Ltd." }, + { 0x17DA, "GEMIT GmbH" }, + { 0x17DB, "CYNOVE" }, + { 0x17DC, "Thermoteknix Systems Ltd." }, + { 0x17DD, "Simply Automated, Incorporated" }, + { 0x17DE, "Grant Instruments" }, + { 0x17DF, "SOUTHWING" }, + { 0x17E0, "Big Sky Laser" }, + { 0x17E1, "ORTHOFIX" }, + { 0x17E2, "PIKAONE" }, + { 0x17E3, "Beck IPC GmbH" }, + { 0x17E4, "OKB SAPR" }, + { 0x17E5, "Memcorp Inc." }, + { 0x17E6, "Quantel Medical" }, + { 0x17E7, "Sirah Laser-und Plasmatechnik GmbH" }, + { 0x17E8, "Visionee S.R.L." }, + { 0x17E9, "DisplayLink (UK) Ltd." }, + { 0x17EA, "Web Technology Corp" }, + { 0x17EB, "Cornice, Inc." }, + { 0x17EC, "Telsource" }, + { 0x17ED, "Sumita Optical Glass, Inc." }, + { 0x17EE, "Personal Media Corporation" }, + { 0x17EF, "Lenovo" }, + { 0x17F0, "Bestronic Industry Co., Ltd." }, + { 0x17F1, "Microjet Technology Co., Ltd." }, + { 0x17F2, "Xmultiple Technologies Inc." }, + { 0x17F3, "Terascala, Inc." }, + { 0x17F4, "AgaMatrix, Inc." }, + { 0x17F5, "K.K. Rocky" }, + { 0x17F6, "Unicomp, Inc" }, + { 0x17F7, "Metroptic Technologies Ltd." }, + { 0x17F8, "Enustech, Inc." }, + { 0x17F9, "GIE Sesam-Vitale" }, + { 0x17FA, "DOSHISHA CORPORATION" }, + { 0x17FB, "Emutec Inc." }, + { 0x17FC, "Vitesse Semiconductor Corp." }, + { 0x17FD, "Formac GmbH" }, + { 0x17FE, "NIPPON PULSE MOTOR CO., LTD." }, + { 0x17FF, "Unication Co., Ltd" }, + { 0x1800, "Shandong Yuanda Net & Multimedia Co., Ltd." }, + { 0x1801, "Southern Data Comm, Inc." }, + { 0x1802, "SYN-TEK Technologies Inc." }, + { 0x1803, "Secutronix" }, + { 0x1804, "Clemens GmbH" }, + { 0x1805, "Digital Peripheral Solutions Inc." }, + { 0x1806, "New Index AS" }, + { 0x1807, "Par-Tech Inc." }, + { 0x1808, "Multiplex Engineering Inc." }, + { 0x1809, "Advantech Co., Ltd." }, + { 0x180A, "Technosystem Co., Ltd." }, + { 0x180B, "Photo Research, Inc." }, + { 0x180C, "Power Digital Card Co., Ltd." }, + { 0x180D, "U3, LLC" }, + { 0x180E, "Audisoft Technologies" }, + { 0x180F, "Phonak Communications AG" }, + { 0x1810, "Wanshih Electronic Co., Ltd." }, + { 0x1811, "Blackspot Interactive Ltd." }, + { 0x1812, "GEWI GmbH" }, + { 0x1813, "HAGIWARA ELECTRIC Co., Ltd." }, + { 0x1814, "Fashionow Co. Ltd." }, + { 0x1815, "Horizon Semiconductors Ltd." }, + { 0x1816, "Directed Electronics" }, + { 0x1817, "Digital Authentication Technologies, Inc." }, + { 0x1818, "Osteosys Co., Ltd." }, + { 0x1819, "Quality Vision International, Inc." }, + { 0x181A, "Fotonation" }, + { 0x181B, "Current Designs, Inc." }, + { 0x181C, "Rensselaer Polytechnic Institute" }, + { 0x181D, "Axon Systems Inc." }, + { 0x181E, "Advanced Tracking Technologies, Inc." }, + { 0x181F, "NAKAJIMA ALL Co., Ltd." }, + { 0x1820, "DSM - Messtechnik GmbH" }, + { 0x1821, "INwireless Co., Ltd" }, + { 0x1822, "DIGIBIO TECHNOLOGY CORP." }, + { 0x1823, "CelleBrite Mobile Synchronization" }, + { 0x1824, "Aval Nagasaki Corp." }, + { 0x1825, "Star-Dundee Ltd." }, + { 0x1826, "Xitron Inc." }, + { 0x1827, "Sanko Electronics Co., Ltd." }, + { 0x1828, "TSR Silicon Resources, Inc." }, + { 0x1829, "Dongguan YuQiu Electronics Co., Ltd." }, + { 0x182A, "Signalion GmbH" }, + { 0x182B, "Chest M.I., Incorporated" }, + { 0x182C, "Caliper LifeSciences" }, + { 0x182D, "Accutron Limited" }, + { 0x182E, "System Instruments Co., Ltd." }, + { 0x182F, "Worldwide Productions Inc." }, + { 0x1830, "I CAP Technologies, Inc." }, + { 0x1831, "Gwo Jinn Industries Co., Ltd." }, + { 0x1832, "Huizhou Shenghua Industrial Co., Ltd." }, + { 0x1833, "Genuine Technologies Co., Ltd." }, + { 0x1834, "SONEL S.A." }, + { 0x1835, "Lust Drivetronics GmbH" }, + { 0x1836, "ePoint Technology" }, + { 0x1837, "Hokuto Denko Corporation" }, + { 0x1838, "Real Networks, Inc." }, + { 0x1839, "AnexTEK Global Inc." }, + { 0x183A, "Mediafour Corporation" }, + { 0x183B, "SIDACON Systemtechnik GmbH" }, + { 0x183C, "Saab AB" }, + { 0x183D, "F3 Inc." }, + { 0x183E, "Robonik India Pvt. Ltd." }, + { 0x183F, "i-BEAD Co., Ltd." }, + { 0x1840, "Cognitive Solutions, Inc." }, + { 0x1841, "SEIKO TIME SYSTEM INC." }, + { 0x1842, "Keen High Technologies (HK) Ltd." }, + { 0x1843, "Vaisala" }, + { 0x1844, "Radiotechnika Marketing Sp.zo.o" }, + { 0x1845, "Cion Technology Corporation" }, + { 0x1846, "microEngineering Labs, Inc." }, + { 0x1847, "Global Payment Technologies, Inc." }, + { 0x1848, "Eurochannels Holding B.V." }, + { 0x1849, "Centurion Systems (Pty) Ltd." }, + { 0x184A, "EB Neuro SPA" }, + { 0x184B, "ARION Technology Inc." }, + { 0x184C, "Centice" }, + { 0x184D, "Dansk Automat Expert A/S" }, + { 0x184E, "SyGade Solutions (Pty) Ltd." }, + { 0x184F, "K2L GmbH" }, + { 0x1850, "Andigilog, Inc." }, + { 0x1851, "ULTRASONIC ENGINEERING CO., LTD." }, + { 0x1852, "Galaxy Far East Corp" }, + { 0x1853, "MITSUBISHI PRECISION CO., LTD." }, + { 0x1854, "Memory Devices Ltd." }, + { 0x1855, "Redpay Secure Payments" }, + { 0x1856, "Imaginova" }, + { 0x1857, "Picosecond Pulse Labs" }, + { 0x1858, "CELLSYSTEM CO., LTD" }, + { 0x1859, "Speech Technology Center, Ltd." }, + { 0x185A, "WinProbe Corporation" }, + { 0x185B, "IG-Development" }, + { 0x185C, "Omnisec AG" }, + { 0x185D, "Origgio Limited" }, + { 0x185E, "Meritech Co., Ltd." }, + { 0x185F, "Stinger Systems Inc." }, + { 0x1860, "HYUPJIN I & C CO, LTD." }, + { 0x1861, "Tech Technology Industrial Company" }, + { 0x1862, "Teridian Semiconductor Corp." }, + { 0x1863, "Wave Technology Co., Ltd." }, + { 0x1864, "Digital Art System" }, + { 0x1865, "Europlex Technologies" }, + { 0x1866, "Union Community Co., Ltd." }, + { 0x1867, "Control Microsystems" }, + { 0x1868, "Index Braille AB" }, + { 0x1869, "RTS Automation GmbH" }, + { 0x186A, "Pivot International, Inc." }, + { 0x186B, "Holophase Incorporated" }, + { 0x186C, "Miyachi Corporation" }, + { 0x186D, "Evermore Innovations" }, + { 0x186E, "Reel Stream LLC" }, + { 0x186F, "Motion Lingo, LLC" }, + { 0x1870, "Nexio Co., Ltd." }, + { 0x1871, "Aveo Technology Corp." }, + { 0x1872, "Cobalt Technologies Co., Ltd." }, + { 0x1873, "Etrovision Technology" }, + { 0x1874, "Nexilion Inc." }, + { 0x1875, "Humo Laboratory, Ltd." }, + { 0x1876, "MG Industrieelektronik GmbH" }, + { 0x1877, "SANEI HYTECHS Co., Ltd." }, + { 0x1878, "Sumitomo Heavy Industries, Ltd." }, + { 0x1879, "Spin Semiconductor Inc." }, + { 0x187A, "Mediachorus Inc." }, + { 0x187B, "Dent Instruments, Inc." }, + { 0x187C, "Alienware Corporation" }, + { 0x187D, "Ardware Ltd." }, + { 0x187E, "Sentelic Corporation" }, + { 0x187F, "Siano Mobile Silicon Ltd." }, + { 0x1880, "Vericon Co., Ltd./Jinn Shyang Precision Industrial Co.," }, + { 0x1881, "Interactive Learning Technologies" }, + { 0x1882, "TransChip Israel Ltd." }, + { 0x1883, "Tanaka S/S Ltd." }, + { 0x1884, "Liyuh Technology Ltd." }, + { 0x1885, "Ascalade Communications Inc." }, + { 0x1886, "Metalink Ltd." }, + { 0x1887, "Fishcamp Engineering" }, + { 0x1888, "Livingston Products, Inc." }, + { 0x1889, "DME Corporation" }, + { 0x188A, "Moeller" }, + { 0x188B, "Showa Electric Laboratory Co., Ltd." }, + { 0x188C, "Epos Development Ltd." }, + { 0x188D, "Across Techno, Inc." }, + { 0x188E, "Neopost Technologies" }, + { 0x188F, "Zefatek Co., Ltd." }, + { 0x1890, "MEDIAN Inc." }, + { 0x1891, "XSENSOR Technology Corp." }, + { 0x1892, "Accuri Instruments, Inc." }, + { 0x1893, "Ginga Software, Inc." }, + { 0x1894, "SyntheSys Research, Inc." }, + { 0x1895, "tesa scribos GmbH" }, + { 0x1896, "Legacy Electronics, Inc." }, + { 0x1897, "Evertop Wire Cable Co." }, + { 0x1898, "Summit Microelectronics" }, + { 0x1899, "Linkiss Co., Ltd." }, + { 0x189A, "Earth Computer Technologies, Inc." }, + { 0x189B, "Trimax Electronics Co., Ltd." }, + { 0x189C, "Walletex Microelectronics Ltd." }, + { 0x189D, "Navionics Inc." }, + { 0x189E, "Net Insight AB" }, + { 0x189F, "3Shape A/S" }, + { 0x18A0, "Kongsberg Maritime AS" }, + { 0x18A1, "Ionwerks, Inc." }, + { 0x18A2, "PSIA Corp." }, + { 0x18A3, "DIGIFRIENDS CO., LTD." }, + { 0x18A4, "CSSN, Inc. dba Card Scanning Solutions" }, + { 0x18A5, "Verbatim Americas LLC" }, + { 0x18A6, "Peripheral Dynamics Inc." }, + { 0x18A7, "Omniprint Inc." }, + { 0x18A8, "Smiths Medical MD" }, + { 0x18A9, "Veri-Tek International" }, + { 0x18AA, "MedRx Inc." }, + { 0x18AB, "Applied Data Systems, Inc." }, + { 0x18AC, "STRATEC Biomedical Systems AG" }, + { 0x18AD, "Invisible Technologies, Inc." }, + { 0x18AE, "MTT Corporation" }, + { 0x18AF, "LN Systems Limited" }, + { 0x18B0, "Mikrodidakt AB" }, + { 0x18B1, "Elmak Ltd." }, + { 0x18B2, "CINTEL FRANCE" }, + { 0x18B3, "RAYDON Corporation" }, + { 0x18B4, "e3C Inc." }, + { 0x18B5, "Klipsch Audio" }, + { 0x18B6, "Mikkon Technology Limited" }, + { 0x18B7, "Zotek Electronic Co., Ltd." }, + { 0x18B8, "Securewave SA" }, + { 0x18B9, "Clixxun GmbH" }, + { 0x18BA, "Bell Fruit Games" }, + { 0x18BB, "G7 Productivity Systems" }, + { 0x18BC, "Muro Co., Ltd" }, + { 0x18BD, "MNBT Co., Ltd." }, + { 0x18BE, "Kingfisher International" }, + { 0x18BF, "Ensyc Technologies" }, + { 0x18C0, "Gatekeeper Systems Inc." }, + { 0x18C1, "Shenzhen SDMC Microelectronics Co., Ltd." }, + { 0x18C2, "AccuSport International, Inc." }, + { 0x18C3, "Elite Semiconductor Memory Technology Inc. (ESMT)" }, + { 0x18C4, "ServerEngines LLC" }, + { 0x18C5, "Corega Taiwan, Inc." }, + { 0x18C6, "Aurora Photonics" }, + { 0x18C7, "Nagano Tectron Co., Ltd" }, + { 0x18C8, "Computerprox Corp." }, + { 0x18C9, "Exfo Electro-Optical Engineering Inc." }, + { 0x18CA, "Canon Korea Business Solutions Inc." }, + { 0x18CB, "Fr. Sauter AG" }, + { 0x18CC, "Osaki Electric Co., Ltd." }, + { 0x18CD, "Pico Instruments LLC" }, + { 0x18CE, "DTC Communications, Inc" }, + { 0x18CF, "Tung Shu Mei Industrial Co., Ltd." }, + { 0x18D0, "Uniform Industrial Corp." }, + { 0x18D1, "Google Inc." }, + { 0x18D2, "Raptor Gaming Technology GmbH" }, + { 0x18D3, "L&V Design" }, + { 0x18D4, "ABI Electronics Ltd." }, + { 0x18D5, "Starline International Group Limited" }, + { 0x18D6, "Ruetz Technologies" }, + { 0x18D7, "New Scale Technologies" }, + { 0x18D8, "Individual Computers" }, + { 0x18D9, "Kaba" }, + { 0x18DA, "Phonol Inc." }, + { 0x18DB, "Compix Incorporated" }, + { 0x18DC, "LKC Technologies, Inc." }, + { 0x18DD, "Docuport WC" }, + { 0x18DE, "Cyto Pulse Sciences, Inc" }, + { 0x18DF, "Cinea Inc." }, + { 0x18E0, "Source Technologies, LLC" }, + { 0x18E1, "Drew Technologies Inc." }, + { 0x18E2, "S.J. Electronics Co., Ltd" }, + { 0x18E3, "Fitilink Integrated Technology, Inc." }, + { 0x18E4, "SB Solutions, Inc" }, + { 0x18E5, "Ablaze Systems LLC" }, + { 0x18E6, "Gobex AS" }, + { 0x18E7, "Truscott Designs" }, + { 0x18E8, "Mondo Systems" }, + { 0x18E9, "Numsite Corporation" }, + { 0x18EA, "Matrox Electronic Systems" }, + { 0x18EB, "nDezign, Inc." }, + { 0x18EC, "Arkmicro Technologies Inc." }, + { 0x18ED, "Tyco Safety Products" }, + { 0x18EE, "Holm Acoustics" }, + { 0x18EF, "ELV Elektronik AG" }, + { 0x18F0, "AVAL DATA CORPORATION" }, + { 0x18F1, "AL Tech, Inc." }, + { 0x18F2, "Rasotto S.N.C." }, + { 0x18F3, "Miglia Technology Ltd." }, + { 0x18F4, "Vtech Engineering Corporation" }, + { 0x18F5, "Esterline Mason" }, + { 0x18F6, "Zermatt Systems Inc" }, + { 0x18F7, "ImageStream Internet Solutions Inc.." }, + { 0x18F8, "Teitsu Denshi Kenkyusho Co., Ltd." }, + { 0x18F9, "EX COMPANY LIMITED" }, + { 0x18FA, "Kuang Ying Computer Equipment Co., Ltd." }, + { 0x18FB, "Scriptel Corporation" }, + { 0x18FC, "Kinyo Co., Ltd." }, + { 0x18FD, "FineArch Inc." }, + { 0x18FE, "SecuriMetrics, Inc." }, + { 0x18FF, "HYUNDAI Digital Technology Co., Ltd." }, + { 0x1900, "Future Wave, Inc." }, + { 0x1901, "GE Healthcare" }, + { 0x1902, "CSIRO Marine & Atmospheric Research" }, + { 0x1903, "ANEX SYSTEM LTD." }, + { 0x1904, "LVI Low Vision International AB" }, + { 0x1905, "EGEMEN Bilgisayar Muh ve San LTD STI" }, + { 0x1906, "Seoro Tech Co., Ltd." }, + { 0x1907, "Elcoteq Design Center Oy" }, + { 0x1908, "APPOTECH LIMITED" }, + { 0x1909, "ABB Inc. Totalflow Division" }, + { 0x190A, "Freewide Inc." }, + { 0x190B, "Metasoft S.C." }, + { 0x190C, "ierise Inc." }, + { 0x190D, "Motorola GSG" }, + { 0x190E, "YAMASA Tokei-Keiki Co, Ltd" }, + { 0x190F, "YA HORNG ELECTRONIC CO., LTD." }, + { 0x1910, "Seriprint-Ziprip UK Limited" }, + { 0x1911, "Nihon Dengyo Kosaku Co., Ltd." }, + { 0x1912, "Yukyung Technologies Co, Ltd" }, + { 0x1913, "Atomynet, Inc." }, + { 0x1914, "Alco Digital Devices Limited" }, + { 0x1915, "Nordic Semiconductor ASA" }, + { 0x1916, "Juniper Systems, Inc." }, + { 0x1917, "Imagetech Corporation" }, + { 0x1918, "NanoSystem Solutions, Inc." }, + { 0x1919, "Pixelworks" }, + { 0x191A, "PATLITE Corporation" }, + { 0x191B, "PICOCEL Co., Ltd." }, + { 0x191C, "Innovative Technology Limited" }, + { 0x191D, "Midtronics, Inc." }, + { 0x191E, "Monsoon Multimedia Inc." }, + { 0x191F, "Venetex Co., Ltd." }, + { 0x1920, "U.S. Digital Television, LLC" }, + { 0x1921, "Interson Corporation" }, + { 0x1922, "Power 7 Technologies Corp." }, + { 0x1923, "FitSense Technology, Inc." }, + { 0x1924, "QnAp iT" }, + { 0x1925, "InnoFaith beauty sciences B.V." }, + { 0x1926, "NextWindow Limited" }, + { 0x1927, "Vulcan Portals Inc." }, + { 0x1928, "PROCEQ SA" }, + { 0x1929, "Wagner Owen Corporation" }, + { 0x192A, "Intek" }, + { 0x192B, "KVH Industries, Inc." }, + { 0x192C, "Twig Com Oy" }, + { 0x192D, "AgileTV" }, + { 0x192E, "Bioanalytical Systems" }, + { 0x192F, "Avago Technologies, Pte." }, + { 0x1930, "Shenzhen Xianhe Technology Co., Ltd." }, + { 0x1931, "Ningbo Broad Telecommunication Co., Ltd." }, + { 0x1932, "Daniels Electronics Ltd." }, + { 0x1933, "TASER INTERNATIONAL INC." }, + { 0x1934, "SAKAI Medical Co., Ltd." }, + { 0x1935, "Elektron Music Machines AB" }, + { 0x1936, "Asaka Riken Co., Ltd" }, + { 0x1937, "Dynjab Technologies Pty. Ltd." }, + { 0x1938, "Meinberg Funkuhren GmbH & Co. KG" }, + { 0x1939, "Hilscher GmbH" }, + { 0x193A, "Lipman Electronic Engineering Ltd." }, + { 0x193B, "Power Monitors, Inc." }, + { 0x193C, "COGELEC" }, + { 0x193D, "MAXIAN Co., Ltd." }, + { 0x193E, "Chestnut Hill Sound Inc." }, + { 0x193F, "OPDICOM PTY LTD" }, + { 0x1940, "U.S. Music Corporation" }, + { 0x1941, "Top Eight Industrial Corp." }, + { 0x1942, "GAMING PARTNERS INTERNATIONAL" }, + { 0x1943, "Sensoray" }, + { 0x1944, "Wegener Communications" }, + { 0x1945, "O-Pen" }, + { 0x1946, "Irisguard UK Ltd" }, + { 0x1947, "Harris Corporation" }, + { 0x1948, "Darlitech International Co., Ltd." }, + { 0x1949, "Lab126" }, + { 0x194A, "Secure Design Institute Co., Ltd." }, + { 0x194B, "Yanago Design Inc." }, + { 0x194C, "Scanivalve Corp." }, + { 0x194D, "Kern AG" }, + { 0x194E, "acam-messelectronic GmbH" }, + { 0x194F, "PreSonus Audio Electronics" }, + { 0x1950, "FUJINON CORPORATION" }, + { 0x1951, "Hyperstone GmbH" }, + { 0x1952, "X-TEMPO DESIGNS LLC" }, + { 0x1953, "Ironkey Inc." }, + { 0x1954, "Radiient Technologies" }, + { 0x1955, "4G Systems GmbH" }, + { 0x1956, "The SmartPill Corporation" }, + { 0x1957, "BIOS Corporation" }, + { 0x1958, "Office Depot, Inc." }, + { 0x1959, "DRS Signal Solutions Inc." }, + { 0x195A, "Technology Link Corporation" }, + { 0x195B, "Huge China Industrial Ltd." }, + { 0x195C, "NewSight" }, + { 0x195D, "Itron Technology Inc." }, + { 0x195E, "Datakey Electronics" }, + { 0x195F, "GODEX INTERNATIONAL CO., LTD." }, + { 0x1960, "Brains Corporation" }, + { 0x1961, "Grupo CD World S.L." }, + { 0x1962, "Vstone Corp." }, + { 0x1963, "IK MULTIMEDIA PRODUCTION srl" }, + { 0x1964, "ID Technica Sales Co., Ltd." }, + { 0x1965, "Uniden Corporation" }, + { 0x1966, "ELESTA GmbH" }, + { 0x1967, "CASIO HITACHI Mobile Communications Co., Ltd." }, + { 0x1968, "Global Silicon Ltd." }, + { 0x1969, "TM-Research, Inc." }, + { 0x196A, "SmartCom" }, + { 0x196B, "Wispro Technology Inc." }, + { 0x196C, "EMKA Technologies" }, + { 0x196D, "InnoDisk Corporation" }, + { 0x196E, "SEI" }, + { 0x196F, "Otoichi Corporation" }, + { 0x1970, "Dane-Elec Corp. USA" }, + { 0x1971, "Real ID Technology Co., Ltd." }, + { 0x1972, "Diagnostic Instruments, Inc." }, + { 0x1973, "SpectraLink Corporation" }, + { 0x1974, "LOSTEAKA, Inc." }, + { 0x1975, "Dongguan Guneetal Wire & Cable Co., Ltd." }, + { 0x1976, "Chipsbrand Microelectronics (HK) Co., Ltd." }, + { 0x1977, "Thales" }, + { 0x1978, "Lismore Instruments Limited" }, + { 0x1979, "Suga Digital Technology Limited" }, + { 0x197A, "Kellendonk Elektronik GmbH" }, + { 0x197B, "Way Systems Inc." }, + { 0x197C, "JSC Videofon MV" }, + { 0x197D, "Leuze electronic GmbH & Co. KG" }, + { 0x197E, "scemtec Transponder Technology GmbH" }, + { 0x197F, "Triton" }, + { 0x1980, "Storage Appliance Corp." }, + { 0x1981, "Matrix Audio Designs Inc." }, + { 0x1982, "Hitel Italia S.P.A." }, + { 0x1983, "Icera Inc." }, + { 0x1984, "Targetti Sankey S.P.A." }, + { 0x1985, "Elmos Co., Ltd." }, + { 0x1986, "Excelitas Technologies Corporation" }, + { 0x1987, "Camille Bauer AG" }, + { 0x1988, "Novar Controls" }, + { 0x1989, "Nuconn Technology Corp." }, + { 0x198A, "MODMEN Co., Ltd." }, + { 0x198B, "Fluid Imaging Technologies, Inc" }, + { 0x198C, "c-scape" }, + { 0x198D, "Fairchild Imaging" }, + { 0x198E, "Ingrid, Inc." }, + { 0x198F, "Beceem Communications Inc." }, + { 0x1990, "Acron Precision Industrial Co., Ltd." }, + { 0x1991, "AAI Corporation" }, + { 0x1992, "Avantes B.V." }, + { 0x1993, "Bluetop Technology Co., Ltd." }, + { 0x1994, "ZMM Ltd." }, + { 0x1995, "Trillium Technology PTY LTD." }, + { 0x1996, "PixeLINK" }, + { 0x1997, "CEFLA S.C.R.L." }, + { 0x1998, "JENOPTIK Laser, Optik, Systeme GmbH" }, + { 0x1999, "iba AG" }, + { 0x199A, "DNA-Technology" }, + { 0x199B, "MicroStrain, Inc." }, + { 0x199C, "Richnex Microelectronics Corporation" }, + { 0x199D, "Dexxon Groupe" }, + { 0x199E, "The Imaging Source Europe GmbH" }, + { 0x199F, "Benica Corporation" }, + { 0x19A0, "Krautkramer Japan Co., Ltd." }, + { 0x19A1, "Zeecraft Tech." }, + { 0x19A2, "SICK AG" }, + { 0x19A3, "ASmobile Communication Inc." }, + { 0x19A4, "Unique Medical Co., Ltd." }, + { 0x19A5, "Harris RF Communication" }, + { 0x19A6, "UBISYS TECHNOLOGIES" }, + { 0x19A7, "SuperTop International Corp." }, + { 0x19A8, "Biforst Technology Inc." }, + { 0x19A9, "Musashi Co., Ltd." }, + { 0x19AA, "musicobo" }, + { 0x19AB, "Bodelin Technologies" }, + { 0x19AC, "Hardworks, Inc." }, + { 0x19AD, "RiTTO GmbH & Co. KG" }, + { 0x19AE, "KeeLog" }, + { 0x19AF, "Innomax Technology Ltd." }, + { 0x19B0, "Sobal Corporation" }, + { 0x19B1, "Kyoritsu Radio Co., Ltd." }, + { 0x19B2, "Batronix Elektronik" }, + { 0x19B3, "SPOTWAVE WIRELESS" }, + { 0x19B4, "CELESTRON" }, + { 0x19B5, "B & W Group" }, + { 0x19B6, "Infotech Logistic, LLC" }, + { 0x19B7, "SK-Electronics Co. Ltd." }, + { 0x19B8, "Control Technology Inc." }, + { 0x19B9, "Drobo, Inc." }, + { 0x19BA, "ebro Electronic GmbH & Co. KG" }, + { 0x19BB, "Informtest" }, + { 0x19BC, "ioLab Systems Inc." }, + { 0x19BD, "Celluon, Inc." }, + { 0x19BE, "Guidance Software, Inc." }, + { 0x19BF, "HASHIMOTO Electronic Industry Co., Ltd." }, + { 0x19C0, "TeraTron GmbH" }, + { 0x19C1, "Digital Info Technology Pte. Ltd." }, + { 0x19C2, "TARGA GmbH" }, + { 0x19C3, "Riskema Informatica e Automacao Ltda." }, + { 0x19C4, "Control Gaging, Inc." }, + { 0x19C5, "Danaher Sensors and Controls" }, + { 0x19C6, "Harmony Microelectronic Inc." }, + { 0x19C7, "WEG Equipamentos Elétricos S.A. - Automação" }, + { 0x19C8, "Secure Key LLC" }, + { 0x19C9, "Electronic Sports" }, + { 0x19CA, "Sandio Technology Corp." }, + { 0x19CB, "EMS (European) LTD." }, + { 0x19CC, "SCIEN Co." }, + { 0x19CD, "D. O. Tel Co., Ltd." }, + { 0x19CE, "SINUS Messtechnik GmbH" }, + { 0x19CF, "Parrot SA" }, + { 0x19D0, "Pan Pacific Enterprise Co., Inc." }, + { 0x19D1, "Channaa" }, + { 0x19D2, "ZTE Corporation" }, + { 0x19D3, "Zucchetti Centro Sistemi SPA" }, + { 0x19D4, "I Bee, K.K." }, + { 0x19D5, "CNB Technology Inc." }, + { 0x19D6, "WIDE Corporation" }, + { 0x19D7, "Unitop New Technology Co., Ltd." }, + { 0x19D8, "Smart Point SA" }, + { 0x19D9, "Fujitsu Ten Limited" }, + { 0x19DA, "MUSE Inc." }, + { 0x19DB, "GeBE Elektronik und Feinwerktechnik GmbH" }, + { 0x19DC, "Communications & Power Industries" }, + { 0x19DD, "NEXVU TECHNOLOGIES, Inc." }, + { 0x19DE, "MITEQ Inc." }, + { 0x19DF, "AlpnaCom" }, + { 0x19E0, "Micro-Nits Co., Ltd." }, + { 0x19E1, "WeiDuan Electronic Accessory (S.Z.) Co., Ltd." }, + { 0x19E2, "Solomon Systech Limited" }, + { 0x19E3, "Bae Systems IEWS" }, + { 0x19E4, "In-Situ Inc." }, + { 0x19E5, "Jetmobile" }, + { 0x19E6, "Apex Digital Inc." }, + { 0x19E7, "Charismathics GmbH" }, + { 0x19E8, "Industrial Technology Research Institute" }, + { 0x19E9, "Bartec Auto ID Ltd." }, + { 0x19EA, "Lung Hwa Electronics Co., Ltd." }, + { 0x19EB, "ACE Antenna, Advanced Technology R&D Team." }, + { 0x19EC, "Forth Dimension Displays Ltd." }, + { 0x19ED, "Plastic Logic Ltd." }, + { 0x19EE, "Modern Marketing Concepts Inc." }, + { 0x19EF, "Pak Heng Technology (Shenzhen) Co., Ltd." }, + { 0x19F0, "Jyh Woei Industrial Co., Ltd." }, + { 0x19F1, "SindoRicoh Co., LTD." }, + { 0x19F2, "INFOMARK Co., Ltd." }, + { 0x19F3, "JAPAN Kyastem Co., Ltd." }, + { 0x19F4, "Malvern Instruments Ltd" }, + { 0x19F5, "Nationz Technologies Inc." }, + { 0x19F6, "J. A. Woollam Co. Inc." }, + { 0x19F7, "Rode Microphones" }, + { 0x19F8, "RoboTech srl" }, + { 0x19F9, "Megadata (Europe) PLC" }, + { 0x19FA, "SHENZHEN GAMEWARE ELECTRONIC CO., LTD." }, + { 0x19FB, "VLSI Solution Oy" }, + { 0x19FC, "BioControl A/S" }, + { 0x19FD, "MTI Instruments" }, + { 0x19FE, "Micromap Corporation" }, + { 0x19FF, "Best Buy China Ltd." }, + { 0x1A00, "Polymax Precision Industry Co., Ltd." }, + { 0x1A01, "Siemens Power Transmission & Dist. Energy Automation" }, + { 0x1A02, "DLoG GmbH" }, + { 0x1A03, "HORIBA ITECH Co., Ltd." }, + { 0x1A04, "ASTRO MACHINE CORP." }, + { 0x1A05, "Media Lab., Inc" }, + { 0x1A06, "Beijing Deng Hong Technology Co., Ltd." }, + { 0x1A07, "HID" }, + { 0x1A08, "Bellwood International, Inc." }, + { 0x1A09, "DILANO GmbH" }, + { 0x1A0B, "Teleste OYJ" }, + { 0x1A0C, "Sunkorea Electronics Co., Ltd." }, + { 0x1A0D, "Ladybug Technologies LLC" }, + { 0x1A0E, "Sasse Elektronik GmbH" }, + { 0x1A0F, "HT-ITALIA" }, + { 0x1A10, "KWANG SUNG ELECTRONICS H.K. Co., Ltd." }, + { 0x1A11, "eMDee Technology, Inc." }, + { 0x1A12, "KES Co., Ltd." }, + { 0x1A13, "Plasmon" }, + { 0x1A14, "Brainvision Inc." }, + { 0x1A15, "Amphenol-Tuchel Electronics GmbH" }, + { 0x1A16, "General Dynamics" }, + { 0x1A17, "Oticon A/S" }, + { 0x1A18, "Quadzilla Performance Technologies, Inc." }, + { 0x1A19, "DDTIC Corporation Ltd." }, + { 0x1A1A, "ASIACORP INTERNATIONAL LTD." }, + { 0x1A1B, "Fischer-Zoth GmbH" }, + { 0x1A1C, "Mercury Computer Systems AG" }, + { 0x1A1D, "Syncomm Technology Corp." }, + { 0x1A1E, "Dekart s.r.l." }, + { 0x1A1F, "Ikanos Communications Inc." }, + { 0x1A20, "Mind Logic Co., Ltd." }, + { 0x1A21, "ASITEQ Co., Ltd." }, + { 0x1A22, "Kenwin Industrial (HK) Ltd." }, + { 0x1A23, "Hangzhou YiHeng Technologies Co., Ltd." }, + { 0x1A24, "Beyondwiz Co., Ltd." }, + { 0x1A25, "Amphenol East Asia Ltd." }, + { 0x1A26, "APSI (Asia Pacific Satellite Industry)" }, + { 0x1A27, "Senior Technologies" }, + { 0x1A28, "NOVITUS SA" }, + { 0x1A29, "ABOV Semiconductor Co., Ltd." }, + { 0x1A2A, "Seagate Branded Solutions" }, + { 0x1A2B, "NTI Corporation" }, + { 0x1A2C, "Wuxi China Resources Semico Co., Ltd." }, + { 0x1A2D, "WEBSYNC Co., Ltd." }, + { 0x1A2E, "Lanner Electronics Inc." }, + { 0x1A2F, "Tetradyne Software Inc." }, + { 0x1A30, "New Media Life" }, + { 0x1A31, "SPEX SamplePrep, LLC" }, + { 0x1A32, "Verint Video Technology GmbH" }, + { 0x1A33, "Schmid & Partner Engineering AG" }, + { 0x1A34, "King Chuang Tech & Electronic Co., Ltd." }, + { 0x1A35, "Artesyn Technologies Inc." }, + { 0x1A36, "Topdisk Technology Limited" }, + { 0x1A37, "Stayhealthy Inc." }, + { 0x1A38, "Nemo-Q International AB" }, + { 0x1A39, "GBC Scientific Equipment" }, + { 0x1A3A, "Laerdal Medical AS" }, + { 0x1A3B, "South Mountain Technologies, Ltd." }, + { 0x1A3C, "New Image Co., Ltd." }, + { 0x1A3D, "ELGA LabWater (VWS UK LTD)" }, + { 0x1A3E, "INTEVAC" }, + { 0x1A3F, "Hokkei Industries Co., Ltd." }, + { 0x1A40, "TERMINUS TECHNOLOGY INC." }, + { 0x1A41, "Action Electronics Co., Ltd." }, + { 0x1A42, "CROSSLINK GmbH" }, + { 0x1A43, "JTEKT CORPORATION" }, + { 0x1A44, "VASCO Data Security NV" }, + { 0x1A45, "Wavelength Electronics Inc." }, + { 0x1A46, "JAVAD GNSS, Inc." }, + { 0x1A47, "iQBio, Inc." }, + { 0x1A48, "KYOHRITSU ELECTRONIC INDUSTRY Co., Ltd." }, + { 0x1A49, "TOKYO SEIMITSU CO., LTD." }, + { 0x1A4A, "Silicon Image" }, + { 0x1A4B, "SafeBoot International B.V." }, + { 0x1A4C, "PMC" }, + { 0x1A4D, "N-CRYPT, Inc." }, + { 0x1A4E, "SIMS Corp." }, + { 0x1A4F, "Haliplex PTY Ltd." }, + { 0x1A50, "Mechatro Inc." }, + { 0x1A51, "FRWD Technologies Ltd." }, + { 0x1A52, "MediaPhy Corporation" }, + { 0x1A53, "SANDBOX Co., Ltd" }, + { 0x1A54, "Oestling Markiersysteme GmbH" }, + { 0x1A55, "Raytheon Systems Limited" }, + { 0x1A56, "East Port Technology Co., Ltd." }, + { 0x1A57, "ARESIS d.o.o." }, + { 0x1A58, "Miranda Technologies Inc." }, + { 0x1A59, "HAAG-STREIT AG" }, + { 0x1A5A, "Tandberg Data" }, + { 0x1A5B, "Entner Electronics KEG" }, + { 0x1A5C, "Arkino Corporation Limited" }, + { 0x1A5D, "Daikin Denshi Kogyo Co., Ltd." }, + { 0x1A5E, "Edixia" }, + { 0x1A5F, "Sonatest Limited" }, + { 0x1A60, "Joytoto Co., Ltd." }, + { 0x1A61, "Abbott Diabetes Care" }, + { 0x1A62, "DAT H.K. LIMITED" }, + { 0x1A63, "Canfield Scientific, Inc." }, + { 0x1A64, "MASTERVOLT INTERNATIONAL" }, + { 0x1A65, "ELEKTRINA d.o.o., podjetje za razvoj elektronike" }, + { 0x1A66, "Andatek Technology, Ltd." }, + { 0x1A67, "Privaris" }, + { 0x1A68, "Double Top Technology Ltd." }, + { 0x1A69, "Kalon Semiconductor, Inc." }, + { 0x1A6A, "Cypress Semiconductor GmbH" }, + { 0x1A6B, "Taiwin Electronics Co., Ltd." }, + { 0x1A6C, "Hivion Co., Ltd." }, + { 0x1A6D, "SamYoung Electronics Co., Ltd" }, + { 0x1A6E, "Global Unichip Corp." }, + { 0x1A6F, "Sagem Orga GmbH" }, + { 0x1A70, "Items Technology Co., Ltd." }, + { 0x1A71, "SEIDEL Elektronik GmbH Nfg. KG" }, + { 0x1A72, "Physik Instrumente (PI) GmbH & Co. KG" }, + { 0x1A73, "Huntron Inc." }, + { 0x1A74, "Oberthur Technologies" }, + { 0x1A75, "Nautilus Hyosung" }, + { 0x1A76, "JADAK Technologies, Inc." }, + { 0x1A77, "American Master Import 26, Inc." }, + { 0x1A78, "AirLink Communications, Inc." }, + { 0x1A79, "Ascensia Diabetes Care" }, + { 0x1A7A, "Softron Co., Ltd." }, + { 0x1A7B, "Lumberg Connect GmbH" }, + { 0x1A7C, "Evoluent LLC" }, + { 0x1A7D, "Systex Corporation" }, + { 0x1A7E, "MELTEC Systementwicklung" }, + { 0x1A7F, "SSD COMPANY LIMITED" }, + { 0x1A80, "Zhong Ming Wire Cable Technology (Xiamen) Co., Ltd." }, + { 0x1A81, "G.Tech Technology Ltd." }, + { 0x1A82, "Proconn Technology Co., Ltd." }, + { 0x1A83, "Socle Technology Corp." }, + { 0x1A84, "COBB Tuning, Inc." }, + { 0x1A85, "Southwest Research Institute" }, + { 0x1A86, "Nanjing Qinherg Electronics Co., Ltd." }, + { 0x1A87, "TechLab 2000 Ltd. Co., Sp Zo.o." }, + { 0x1A88, "WowWee Limited" }, + { 0x1A89, "Dynalith Systems Co., Ltd." }, + { 0x1A8A, "Simula Technology Inc." }, + { 0x1A8B, "SGS Taiwan Ltd." }, + { 0x1A8C, "MagicEyes Digital Co., Ltd" }, + { 0x1A8D, "BandRich Inc." }, + { 0x1A8E, "XiTRON Technologies" }, + { 0x1A8F, "Harman Becker Automotive Systems, GmbH" }, + { 0x1A90, "Resource Data Management" }, + { 0x1A91, "GEOMC Co., Ltd." }, + { 0x1A92, "Berkash Enterprise" }, + { 0x1A93, "Promotional Technologies International Corp." }, + { 0x1A94, "STWTECH Co., Ltd." }, + { 0x1A95, "Sextant Labs, Inc." }, + { 0x1A96, "Harman Becker Automotive Systems, Inc." }, + { 0x1A97, "XM Satellite Radio Inc." }, + { 0x1A98, "Leica Camera AG" }, + { 0x1A99, "Asia Tai Technology (Dongguan) Co., Ltd." }, + { 0x1A9A, "Verari Systems, Inc." }, + { 0x1A9B, "Balboa Instruments" }, + { 0x1A9C, "Inomed Medizintechnik GmbH" }, + { 0x1A9D, "TrafficSim Co., Ltd." }, + { 0x1A9E, "Epicenter, Inc." }, + { 0x1A9F, "Hysitron Incorporated" }, + { 0x1AA0, "Auto Enginuity, L.L.C." }, + { 0x1AA1, "Vestax Corporation" }, + { 0x1AA2, "ORIENTAL MOTOR CO., LTD." }, + { 0x1AA3, "ZOLL Medical Corporation" }, + { 0x1AA4, "Data Drive Thru, Inc." }, + { 0x1AA5, "UBeacon Technologies, Inc." }, + { 0x1AA6, "eFortune Technology Corp." }, + { 0x1AA7, "SiliconSystems, Inc." }, + { 0x1AA8, "Waves Audio Ltd." }, + { 0x1AA9, "Home Phone Tunes Inc." }, + { 0x1AAA, "Taylor Associates/Communications, Inc." }, + { 0x1AAB, "SilverCreations Software AG" }, + { 0x1AAC, "Witschi Electronic AG" }, + { 0x1AAD, "KeeTouch Electronic Co., Ltd." }, + { 0x1AAE, "Johnson Component & Equipments Co., Ltd." }, + { 0x1AAF, "Intellectual Property Library Company" }, + { 0x1AB0, "DAEWOO ELECTRONIC COMPONENTS CO., LTD." }, + { 0x1AB1, "Rigol Technologies, Inc." }, + { 0x1AB2, "Allied Vision Technologies GmbH" }, + { 0x1AB3, "M and C System" }, + { 0x1AB4, "Japan Remote Control Co., Ltd." }, + { 0x1AB5, "Hamamatsu TOA Electronics, Inc." }, + { 0x1AB6, "Integrated Technology Corp." }, + { 0x1AB7, "GLOBAL VR, Inc." }, + { 0x1AB8, "Pen Laboratory Inc." }, + { 0x1AB9, "Nomadio Inc." }, + { 0x1ABA, "Kenton Electronics Limited" }, + { 0x1ABB, "Airo Wireless Media Inc." }, + { 0x1ABC, "Fuji Photo Film USA" }, + { 0x1ABD, "PERTO S.A." }, + { 0x1ABE, "MP3Car.com Inc" }, + { 0x1ABF, "ANIMA Corporation" }, + { 0x1AC0, "SOKKIA Co., Ltd." }, + { 0x1AC1, "LIANHE TECHNOLOGIES, INC." }, + { 0x1AC2, "DESKO GmbH" }, + { 0x1AC3, "DISK KING Technology Co., Ltd." }, + { 0x1AC4, "CAO Group, Inc." }, + { 0x1AC5, "Electronic Engineering Solutions S.L." }, + { 0x1AC6, "JAPAN ADE LTD." }, + { 0x1AC7, "Modular Communication Systems, Inc." }, + { 0x1AC8, "Toyota Industries Corporation" }, + { 0x1AC9, "Broadxent Pte. Ltd." }, + { 0x1ACA, "Bluebird Soft Inc." }, + { 0x1ACB, "Salcomp Plc" }, + { 0x1ACC, "Ta Horng Musical Instrument Co., Ltd." }, + { 0x1ACD, "MKS Instruments" }, + { 0x1ACE, "Temento Systems" }, + { 0x1ACF, "International Manufacturing & Engineering Services Co." }, + { 0x1AD0, "Cygnetron, Inc." }, + { 0x1AD1, "Desan Wire Co., Ltd." }, + { 0x1AD2, "Mesa Imaging AG" }, + { 0x1AD3, "Advanced Technetix, Inc." }, + { 0x1AD4, "Advanced Printing Systems" }, + { 0x1AD5, "Gentec-EO" }, + { 0x1AD6, "General Dynamics SATCOM Technologies, State College Fac" }, + { 0x1AD7, "A.B.O. Co., Ltd." }, + { 0x1AD8, "Motion Control i Västerås AB" }, + { 0x1AD9, "Rocket Gaming Systems" }, + { 0x1ADA, "VEGA Grieshaber KG" }, + { 0x1ADB, "Schweitzer Engineering Laboratories" }, + { 0x1ADC, "Turbolinux, Inc." }, + { 0x1ADD, "Marshall Electronics, Inc." }, + { 0x1ADE, "SpinMaster Ltd." }, + { 0x1ADF, "digital design GmbH" }, + { 0x1AE0, "Axiomatic Technologies Corp." }, + { 0x1AE1, "Hoffman Engineering" }, + { 0x1AE2, "A-JET Technology Co., LTD." }, + { 0x1AE3, "Chung Young Digital Corp., Ltd." }, + { 0x1AE4, "ic-design Reinhard Gottinger GmbH" }, + { 0x1AE5, "Jianduan Technology (Shenzhen) Co., Ltd" }, + { 0x1AE6, "JOA Telecom Co., Ltd." }, + { 0x1AE7, "Joellenbeck GmbH" }, + { 0x1AE8, "Myway Labs Co., Ltd." }, + { 0x1AE9, "arnotec GmbH" }, + { 0x1AEA, "Mobilygen Corporation" }, + { 0x1AEB, "NIHON UNICA CORPORATION" }, + { 0x1AEC, "PORTEK TECHNOLOGY CORPORATION" }, + { 0x1AED, "High Top Precision Electronic Co., Ltd." }, + { 0x1AEE, "SHEN ZHEN REX TECHNOLOGY CO., LTD." }, + { 0x1AEF, "Octekconn Incorporation" }, + { 0x1AF0, "SuperPix Micro Technology Limited" }, + { 0x1AF1, "Connect One, Ltd." }, + { 0x1AF2, "AXSionics AG" }, + { 0x1AF3, "Smarthome Technology Limited" }, + { 0x1AF4, "NCS Pearson, Inc." }, + { 0x1AF5, "Arima Communications Corp." }, + { 0x1AF6, "SL International Ltd." }, + { 0x1AF7, "GRAPHIN CO., LTD." }, + { 0x1AF8, "JS-ROBOTICS" }, + { 0x1AF9, "Alvarion Ltd." }, + { 0x1AFA, "Mobinnova Corp." }, + { 0x1AFB, "Kirche Jesu Christi der Heiligen der Letzten Tage" }, + { 0x1AFC, "Blue Orb" }, + { 0x1AFD, "FarSite Communications Limited" }, + { 0x1AFE, "A. Eberle GmbH & Co. KG" }, + { 0x1AFF, "Defibtech, LLC" }, + { 0x1B00, "Uster Technologies, Inc." }, + { 0x1B01, "ETA Chips, Co." }, + { 0x1B02, "MEN Mikro Elektronik GmbH" }, + { 0x1B03, "Moog Japan Ltd." }, + { 0x1B04, "MEILHAUS Electronic GmbH" }, + { 0x1B05, "Cracol Developments Ltd." }, + { 0x1B06, "OPGAL" }, + { 0x1B07, "WEY Technology AG" }, + { 0x1B08, "Actimo Inc." }, + { 0x1B09, "MISUZU INDUSTRIES CORPORATION" }, + { 0x1B0A, "Sense Technology Inc." }, + { 0x1B0B, "Lambda Systems Inc." }, + { 0x1B0C, "MYTECS Co., Ltd." }, + { 0x1B0D, "SmarDTV" }, + { 0x1B0E, "BLUTRONICS S.R.L." }, + { 0x1B0F, "EKS-ELEKTRONIKSERVICE GmbH" }, + { 0x1B10, "KAGA COMPONENTS CO., LTD." }, + { 0x1B11, "OneClick Technologies Ltd." }, + { 0x1B12, "Eventide, Inc." }, + { 0x1B13, "Neuf Cegetel" }, + { 0x1B14, "Ergotron, Inc." }, + { 0x1B15, "i3micro technology ab" }, + { 0x1B16, "LinTech GmbH Berlin" }, + { 0x1B17, "SHENZHEN e-loam Technology Co., Ltd." }, + { 0x1B18, "Mikrolab Entwicklungsgesellschaft fur Elektroniksysteme" }, + { 0x1B19, "RADA Electronic Industries Ltd." }, + { 0x1B1A, "Tianjin China-Silicon Microelectronics Co., Ltd." }, + { 0x1B1B, "Shenzhen MD Electric Co., Ltd." }, + { 0x1B1C, "CORSAIR MEMORY INC." }, + { 0x1B1D, "Torian Wireless Ltd." }, + { 0x1B1E, "General Imaging Company" }, + { 0x1B1F, "eQ-3 Entwicklung GmbH" }, + { 0x1B20, "MStar Semiconductor, Inc." }, + { 0x1B21, "XenICs nv" }, + { 0x1B22, "WiLinx Corp." }, + { 0x1B23, "Skyray Instrument Co., Ltd." }, + { 0x1B24, "Telegent Systems Inc." }, + { 0x1B25, "ALE" }, + { 0x1B26, "Plug Power" }, + { 0x1B27, "Current Electronics Inc." }, + { 0x1B28, "NAVIsis Inc." }, + { 0x1B29, "Industrie Dial Face S.p.A." }, + { 0x1B2A, "MICRO EMISSION CO., LTD." }, + { 0x1B2B, "Neural Image Co., Ltd." }, + { 0x1B2C, "Advanced Thermal Solutions, Inc." }, + { 0x1B2D, "Photon Inc." }, + { 0x1B2E, "ETANI ELECTRONICS CO., LTD." }, + { 0x1B2F, "Ihara Electronic Industries Co.,Ltd." }, + { 0x1B30, "STZ QSBV Ilmenau" }, + { 0x1B31, "Renu Electronics Pvt. Ltd." }, + { 0x1B32, "Ugobe, Inc." }, + { 0x1B33, "3DV Systems Ltd." }, + { 0x1B34, "EyeTalk Systems, Inc." }, + { 0x1B35, "Paradigm Electronics Inc." }, + { 0x1B36, "ViXS Systems, Inc." }, + { 0x1B37, "Savant Systems, LLC" }, + { 0x1B38, "ALBAHITH TECHNOLOGIES" }, + { 0x1B39, "ViaMichelin SAS" }, + { 0x1B3A, "JUMO GmbH & Co. KG" }, + { 0x1B3B, "iPassion Technology Inc." }, + { 0x1B3C, "DEVI A/S" }, + { 0x1B3D, "Matrix Orbital" }, + { 0x1B3E, "STIL SA" }, + { 0x1B3F, "Generalplus Technology Inc." }, + { 0x1B40, "AISIN SEIKI CO., LTD." }, + { 0x1B41, "Fujitsu Australia Limited" }, + { 0x1B42, "Cardinal Scale Manufacturing Company" }, + { 0x1B43, "Extron Design Services" }, + { 0x1B44, "Elite Co., Ltd." }, + { 0x1B45, "Cyan Technology Ltd." }, + { 0x1B46, "Holylite Microelectronics Corp." }, + { 0x1B47, "Energizer Holdings, Inc." }, + { 0x1B48, "Plastron Precision Co., Ltd." }, + { 0x1B49, "Applied Printed Electronics Research, LLC" }, + { 0x1B4A, "Gem-Med, S.L." }, + { 0x1B4B, "Watson Marlow Ltd." }, + { 0x1B4C, "Unitron Group" }, + { 0x1B4D, "Objet Geometries Ltd." }, + { 0x1B4E, "ELPRO-BUCHS AG" }, + { 0x1B4F, "Spark Fun Electronics" }, + { 0x1B50, "DictaNet Software AG" }, + { 0x1B51, "Kundisch GmbH & Co. KG" }, + { 0x1B52, "A.R. Hungary, Inc." }, + { 0x1B53, "DANI Instruments S.p.A." }, + { 0x1B54, "COMMIT Incorporated" }, + { 0x1B55, "ZKSoftware Inc." }, + { 0x1B56, "V.I.O., Inc." }, + { 0x1B57, "ATREE Inc." }, + { 0x1B58, "Sumitomo Elec Ind Ltd. Lightwave Network Products Div." }, + { 0x1B59, "K.S. Terminals Inc." }, + { 0x1B5A, "Chao Zhou Kai Yuan Electric Co., Ltd." }, + { 0x1B5B, "Homoth Medizinelektronik" }, + { 0x1B5C, "ICP DAS Co., Ltd." }, + { 0x1B5D, "MV Circuit Design, Inc." }, + { 0x1B5E, "General Engine Management Systems Ltd." }, + { 0x1B5F, "Wayne Dalton Corp." }, + { 0x1B60, "NanoDrop Technologies, Inc." }, + { 0x1B61, "n-Trance Security Ltd." }, + { 0x1B62, "Shenzhen Aoni Electronic Industry Co., Ltd." }, + { 0x1B63, "Seedsware Corporation" }, + { 0x1B64, "C.G. Development Ltd." }, + { 0x1B65, "The Hong Kong Standards and Testing Centre Ltd." }, + { 0x1B66, "Bontempi-Farfisa Sigma S.p.A." }, + { 0x1B67, "Toradex AG" }, + { 0x1B68, "ZAFENA AB" }, + { 0x1B69, "KLA-Tencor" }, + { 0x1B6A, "HIKARI Co., Ltd." }, + { 0x1B6B, "Modiotek Co., Ltd." }, + { 0x1B6C, "Techno Veins Co., Ltd." }, + { 0x1B6D, "IDpendant GmbH" }, + { 0x1B6E, "HS Automatic ApS" }, + { 0x1B6F, "Federal Signal Vama S.A." }, + { 0x1B70, "Minicom Advanced Systems" }, + { 0x1B71, "Huizhou 10Moons Technology Development Co., Ltd." }, + { 0x1B72, "ATERGI TECHNOLOGY CO., LTD." }, + { 0x1B73, "Vehicle Camera Systems Ltd" }, + { 0x1B74, "MODAFUN, Inc." }, + { 0x1B75, "OvisLink Corp." }, + { 0x1B76, "Legend Silicon Corp." }, + { 0x1B77, "Protec, Inc." }, + { 0x1B78, "LOGICPACK CO., LTD." }, + { 0x1B79, "WingsTek, Inc." }, + { 0x1B7A, "Electrox" }, + { 0x1B7B, "Ingersoll Rand Co." }, + { 0x1B7C, "io Corporation" }, + { 0x1B7D, "SUNGIL TELECOM" }, + { 0x1B7E, "Lutron Electronics Inc." }, + { 0x1B7F, "EMC Corporation" }, + { 0x1B80, "KWorld Computer Co., Ltd." }, + { 0x1B81, "Kratos Analytical Ltd." }, + { 0x1B82, "Mcube Technology Co., Ltd." }, + { 0x1B83, "Megatone systems and Technologies LTD." }, + { 0x1B84, "WALTHER Data GmbH Scan-Solutions" }, + { 0x1B85, "INNOVA S.A." }, + { 0x1B86, "Dongguan Guanshang Electronics Co., Ltd." }, + { 0x1B87, "Davis Instruments" }, + { 0x1B88, "ShenMing Electron (Dong Guan) Co., Ltd." }, + { 0x1B89, "iCache, Incorporated" }, + { 0x1B8A, "Quellan, Inc." }, + { 0x1B8B, "PROCES-DATA A/S" }, + { 0x1B8C, "Altium Limited" }, + { 0x1B8D, "e-MOVE Technology Co., Ltd." }, + { 0x1B8E, "Amlogic, Inc." }, + { 0x1B8F, "Super Talent Technology, Inc." }, + { 0x1B90, "Deep Sea Electronics Plc" }, + { 0x1B91, "Zicplay SA" }, + { 0x1B92, "Trysys Co., Ltd." }, + { 0x1B93, "Phoenix Contact GmbH & Co. KG" }, + { 0x1B94, "Yoggie Security Systems" }, + { 0x1B95, "EVC electronic GmbH" }, + { 0x1B96, "N-Trig" }, + { 0x1B97, "Metronix GmbH" }, + { 0x1B98, "YMax Communications Corp." }, + { 0x1B99, "Shenzhen Yuanchuan Electronic" }, + { 0x1B9A, "Applied Vision Systems Corporation" }, + { 0x1B9B, "Microtrac, Inc." }, + { 0x1B9C, "Maki Manufacturing Co., Ltd." }, + { 0x1B9D, "Sigma Instruments, Inc." }, + { 0x1B9E, "ARCoptix S.A" }, + { 0x1B9F, "GHI Electronics, LLC" }, + { 0x1BA0, "Jiangmen Kong Yue Jolimark Information Technology Ltd." }, + { 0x1BA1, "JINQ CHERN ENTERPRISE CO., LTD." }, + { 0x1BA2, "Lite Metals & Plastic (Shenzhen) Co., Ltd." }, + { 0x1BA3, "EmbeddedFusion Ltd." }, + { 0x1BA4, "Ember Corporation" }, + { 0x1BA5, "Futiro" }, + { 0x1BA6, "Abilis Systems" }, + { 0x1BA7, "Xantech Corporation" }, + { 0x1BA8, "China Telecommunication Technology Labs" }, + { 0x1BA9, "Renau Electronic Laboratories" }, + { 0x1BAA, "Transcell Technology, Inc." }, + { 0x1BAB, "MATT R.P.Traczynscy Sp.J." }, + { 0x1BAC, "Bernecker + Rainer Industrie-Elektronik Ges.m.b.H." }, + { 0x1BAD, "Harmonix Music Systems, Inc." }, + { 0x1BAE, "Vuzix Corporation" }, + { 0x1BAF, "NIIGATA SEIMITSU CO., LTD." }, + { 0x1BB0, "LBS PLUS Co., Ltd." }, + { 0x1BB1, "Commodore International Corporation" }, + { 0x1BB2, "G.T. trading Srl" }, + { 0x1BB3, "Holzworth Instrumentation LLC" }, + { 0x1BB4, "Satmap Systems Ltd." }, + { 0x1BB5, "SEF Roboter GmbH" }, + { 0x1BB6, "PdMA Corporation" }, + { 0x1BB7, "DGT Sp. z o.o." }, + { 0x1BB8, "MIZOUE PROJECT JAPAN Corporation" }, + { 0x1BB9, "Qpixel Technology, Inc." }, + { 0x1BBA, "Medicomp, Inc." }, + { 0x1BBB, "TCL Communication Ltd" }, + { 0x1BBC, "KATHREIN-Werke KG" }, + { 0x1BBD, "Videology Imaging Solutions, Inc." }, + { 0x1BBE, "CE+T s.a." }, + { 0x1BBF, "Littfinski DatenTechnik (LDT)" }, + { 0x1BC0, "Senselock Software Technology Co.,Ltd" }, + { 0x1BC1, "ACE ELECTRONIQUE" }, + { 0x1BC2, "SEW-EURODRIVE GmbH & Co. KG" }, + { 0x1BC3, "Fujian START Computer Equipment Co., Ltd." }, + { 0x1BC4, "Ford Motor Co." }, + { 0x1BC5, "AVIXE Technology (China) Ltd." }, + { 0x1BC6, "Yurex, Inc." }, + { 0x1BC7, "Telit Wireless Solutions" }, + { 0x1BC8, "MDS Technology Co., Ltd." }, + { 0x1BC9, "Alti-2 Inc." }, + { 0x1BCA, "Ishii Hyoki Co., Ltd." }, + { 0x1BCB, "Cubic Defence NZ Limited" }, + { 0x1BCC, "TopScan Ltd." }, + { 0x1BCD, "AZKOYEN" }, + { 0x1BCE, "Contac Cable Industrial Limited" }, + { 0x1BCF, "Sunplus Innovation Technology Inc." }, + { 0x1BD0, "Hangzhou Riyue Electronics Co., Ltd." }, + { 0x1BD1, "Companion Worlds, Inc." }, + { 0x1BD2, "Beijing G & D Card Systems Co., Ltd." }, + { 0x1BD3, "3layer Engineering" }, + { 0x1BD4, "FastVDO Inc." }, + { 0x1BD5, "BG Systems, Inc." }, + { 0x1BD6, "Lodam electronics" }, + { 0x1BD7, "TouchNetworks, Inc." }, + { 0x1BD8, "Image Computer Systems Limited" }, + { 0x1BD9, "Emerson" }, + { 0x1BDA, "University of Southampton" }, + { 0x1BDB, "Spectral Applied Research" }, + { 0x1BDC, "Slacker" }, + { 0x1BDD, "QiGO Inc" }, + { 0x1BDE, "P-TWO INDUSTRIES, INC." }, + { 0x1BDF, "Electrone Americas Ltd., Co." }, + { 0x1BE0, "Analog Devices, Inc. - Test Technology Group" }, + { 0x1BE1, "LG-Ericsson Co., Ltd" }, + { 0x1BE2, "Shenzhen Fametech Electronic Co., Ltd." }, + { 0x1BE3, "WAGO Kontakttechnik GmbH & Co. KG" }, + { 0x1BE4, "Integrated Digital Technologies, Inc. (IDTI)" }, + { 0x1BE5, "NetLogic Microsystems" }, + { 0x1BE6, "NAVENTO TECHNOLOGIES" }, + { 0x1BE7, "CPR Tools, Inc." }, + { 0x1BE8, "MEDAV GmbH" }, + { 0x1BE9, "CONCH ELECTRONIC CO., LTD." }, + { 0x1BEA, "ATTO Corporation" }, + { 0x1BEB, "HOYA CANDEO OPTRONICS CORPORATION" }, + { 0x1BEC, "isMedia Co., Ltd." }, + { 0x1BED, "OPT Corporation" }, + { 0x1BEE, "KCI Medical Products (UK) Ltd." }, + { 0x1BEF, "Shenzhen Tongyuan Network-Communication Cables Co., Ltd" }, + { 0x1BF0, "RealVision Inc." }, + { 0x1BF1, "HENGSTLER" }, + { 0x1BF2, "Newport Media, Inc." }, + { 0x1BF3, "WAVES SYSTEM / SONAMIX" }, + { 0x1BF4, "ABB / Drives" }, + { 0x1BF5, "Extranet Systems Inc." }, + { 0x1BF6, "Orient Semiconductor Electronics, Ltd." }, + { 0x1BF7, "Axiotron, Inc." }, + { 0x1BF8, "Game Mechanisms LLC" }, + { 0x1BF9, "TRACTEL SAS" }, + { 0x1BFA, "METROLAB TECHNOLOGY SA" }, + { 0x1BFB, "ALLIED PANELS" }, + { 0x1BFC, "Guidance Interactive Healthcare" }, + { 0x1BFD, "RISINTECH INC." }, + { 0x1BFE, "SEOHWA TELECOM Co., LTD." }, + { 0x1BFF, "IonOptix Corp." }, + { 0x1C00, "prodaSafe GmbH" }, + { 0x1C01, "No Climb Products Ltd." }, + { 0x1C02, "Kreton Corporation" }, + { 0x1C03, "DDL CO., LTD." }, + { 0x1C04, "QNAP System Inc." }, + { 0x1C05, "Rockwell Collins" }, + { 0x1C06, "SeekTech, Inc." }, + { 0x1C07, "CEntrance, Inc." }, + { 0x1C08, "Arcus-EDS GmbH" }, + { 0x1C09, "RAMTEX Engineering ApS" }, + { 0x1C0A, "MaxRise Inc." }, + { 0x1C0B, "Kato Tech Co., Ltd." }, + { 0x1C0C, "Ionics EMS Inc." }, + { 0x1C0D, "Relm Wireless" }, + { 0x1C0E, "Qstik plc" }, + { 0x1C0F, "NEOTECHKNO" }, + { 0x1C10, "Lanterra Industrial Co., Ltd." }, + { 0x1C11, "UNIMTEC Co., Ltd." }, + { 0x1C12, "CONITEC DATENSYSTEME GmbH" }, + { 0x1C13, "ALECTRONIC LIMITED" }, + { 0x1C14, "SENSITIVE OBJECT" }, + { 0x1C15, "TeleWell Oy" }, + { 0x1C16, "Afit Corporation" }, + { 0x1C17, "LAB REHAB PTE LTD." }, + { 0x1C18, "Apria Technology" }, + { 0x1C19, "Charder Electronic Co., Ltd." }, + { 0x1C1A, "Datel Electronics Ltd." }, + { 0x1C1B, "Volkswagen of America, Inc." }, + { 0x1C1C, "Schmartz Inc." }, + { 0x1C1D, "GASTEC CORPORATION" }, + { 0x1C1E, "Focused Test, Inc." }, + { 0x1C1F, "Goldvish S.A." }, + { 0x1C20, "Fuji Electric Device Technology Co., Ltd." }, + { 0x1C21, "ADDMM LLC" }, + { 0x1C22, "ZHONGSHAN CHIANG YU ELECTRIC CO., LTD." }, + { 0x1C23, "Enzytek Technology Inc." }, + { 0x1C24, "DIGITAL IMAGING SYSTEMS GmbH" }, + { 0x1C25, "Sunwell Electronics Ltd." }, + { 0x1C26, "Shanghai Haiying Electronics Co., Ltd." }, + { 0x1C27, "SHENZHEN DNS INDUSTRIES CO., LTD." }, + { 0x1C28, "PMDTechnologies" }, + { 0x1C29, "Elster Group" }, + { 0x1C2A, "NAVIGON AG" }, + { 0x1C2B, "SIEB & MEYER AG" }, + { 0x1C2C, "QUANTEL LTD." }, + { 0x1C2D, "Barloworld Scientific Limited" }, + { 0x1C2E, "LiveWire Test Labs, Inc." }, + { 0x1C2F, "Wessex Advanced Switching Products Ltd." }, + { 0x1C30, "Li Creative Technologies, Inc." }, + { 0x1C31, "LS Mtron Ltd." }, + { 0x1C32, "INTELBANQ" }, + { 0x1C33, "EK-TEAM GmbH" }, + { 0x1C34, "Pro-Active" }, + { 0x1C35, "Superna Inc." }, + { 0x1C36, "Axiom Manufacturing" }, + { 0x1C37, "Sonavation, Inc." }, + { 0x1C38, "Kirin Techno-System Company, Limited" }, + { 0x1C39, "Quantronix, Inc." }, + { 0x1C3A, "CCV Deutschland GmbH" }, + { 0x1C3B, "Nivis, LLC" }, + { 0x1C3C, "INFOTURE, INC." }, + { 0x1C3D, "NONIN MEDICAL INC." }, + { 0x1C3E, "Wep Peripherals" }, + { 0x1C3F, "Amfit, Inc." }, + { 0x1C40, "EZ PROTOTYPES" }, + { 0x1C41, "CompX Fort" }, + { 0x1C42, "VERCET LLC" }, + { 0x1C43, "PeCon GmbH" }, + { 0x1C44, "Fukasawa Co." }, + { 0x1C45, "NavCom Technology Inc." }, + { 0x1C46, "Hitachi Zosen Corporation" }, + { 0x1C47, "Andrew Telecommunication Product SRL" }, + { 0x1C48, "International Truck and Engine Corporation" }, + { 0x1C49, "Cherng Weei Technology Corp." }, + { 0x1C4A, "Cathay Tri-Tech., Inc." }, + { 0x1C4B, "Geratherm Respiratory GmbH" }, + { 0x1C4C, "SYSTECH" }, + { 0x1C4D, "Everest Display Inc." }, + { 0x1C4E, "Koninklijke Gazelle N.V." }, + { 0x1C4F, "Beijing Sigmachip Co., Ltd." }, + { 0x1C50, "Chatsworth Data Corporation" }, + { 0x1C51, "Wisecube Co., Ltd." }, + { 0x1C52, "FLEETWOOD ELECTRONICS LTD." }, + { 0x1C53, "Heartland Data Co." }, + { 0x1C54, "NU-LEC INDUSTRIES" }, + { 0x1C55, "LGS" }, + { 0x1C56, "RED DIGITAL CINEMA" }, + { 0x1C57, "Zalman Tech Co., Ltd." }, + { 0x1C58, "IVA Corporation" }, + { 0x1C59, "SIXNET, LLC" }, + { 0x1C5A, "Fisher and Paykel Healthcare Limited" }, + { 0x1C5B, "FUTURE WAVES PTE Ltd." }, + { 0x1C5C, "CELLMETRIC LTD." }, + { 0x1C5D, "KB Kommutatcionnoy apparatury LTD." }, + { 0x1C5E, "Fueltech Ind. & Com. Prod. Elet. Ltda." }, + { 0x1C5F, "Watec Co., Ltd." }, + { 0x1C60, "Vision & Control GmbH" }, + { 0x1C61, "ASI DataMyte, Inc." }, + { 0x1C62, "LITEPOINT CORP." }, + { 0x1C63, "DLP Design, Inc." }, + { 0x1C64, "QSI Corporation" }, + { 0x1C65, "PROCENTEC" }, + { 0x1C66, "The Trane Company" }, + { 0x1C67, "Sugar Creek Solutions LLC" }, + { 0x1C68, "Trace Systems, Inc." }, + { 0x1C69, "MPB Communications" }, + { 0x1C6A, "Regula Ltd." }, + { 0x1C6B, "Philips & Lite-ON Digital Solutions Corporation" }, + { 0x1C6C, "Skydigital Inc." }, + { 0x1C6D, "Bioptigen Inc." }, + { 0x1C6E, "MINELAB ELECTRONICS PTY LTD." }, + { 0x1C6F, "SUN-A CORPORATION" }, + { 0x1C70, "Wessa Engineering" }, + { 0x1C71, "HUMANWARE LTD." }, + { 0x1C72, "EMTEC Elektronische Messtechnik GmbH" }, + { 0x1C73, "AMT Co., Ltd." }, + { 0x1C74, "PHOTOVOX srl" }, + { 0x1C75, "ARTURIA" }, + { 0x1C76, "Sun-Light Electronic Technologies Inc." }, + { 0x1C77, "Kaetat Industrial Co., Ltd." }, + { 0x1C78, "Mindray DS USA, Inc." }, + { 0x1C79, "Unigen Corporation" }, + { 0x1C7A, "Egis Technology, Inc." }, + { 0x1C7B, "Shenzhen Luxshare Precision Industry Co., Ltd." }, + { 0x1C7C, "DELCOP LLC" }, + { 0x1C7D, "STARKEY LABORATORIES INC." }, + { 0x1C7E, "Hydrometer GmbH" }, + { 0x1C7F, "FILTRONIC DEFENCE LIMITED" }, + { 0x1C80, "Hoffmann + Krippner GmbH" }, + { 0x1C81, "MOTOSOFT b.v." }, + { 0x1C82, "Atracsys LLC" }, + { 0x1C83, "BEKA Elektronik" }, + { 0x1C84, "DRS Tactical Systems" }, + { 0x1C85, "Audyssey Laboratories, Inc." }, + { 0x1C86, "Tallahassee Technologies, Inc." }, + { 0x1C87, "2N TELEKOMUNIKACE a.s." }, + { 0x1C88, "Somagic, Inc." }, + { 0x1C89, "HONGKONG WEIDIDA ELECTRON LIMITED" }, + { 0x1C8A, "SHIN HEUNG PRECISION CO., LTD." }, + { 0x1C8B, "Bridgestone Cycle Co., Ltd." }, + { 0x1C8C, "noax Technologies AG" }, + { 0x1C8D, "Payter BV" }, + { 0x1C8E, "ASTRON INTERNATIONAL CORP." }, + { 0x1C8F, "Scolis Technologies (India) Pvt. Ltd." }, + { 0x1C90, "Pixela (Shanghai) Co., Ltd." }, + { 0x1C91, "Hutchinson Technology Incorporated" }, + { 0x1C92, "JDD Enterprises" }, + { 0x1C93, "Airspan Networks" }, + { 0x1C94, "Maerzhaeuser Wetzlar GmbH & Co. KG." }, + { 0x1C95, "OVATION SYSTEMS LIMITED" }, + { 0x1C96, "Tesselon, LLC" }, + { 0x1C97, "PEBBLE ENTERTAINMENT GmbH" }, + { 0x1C98, "ALPINE ELECTRONICS, INC." }, + { 0x1C99, "KETEREX, Inc." }, + { 0x1C9A, "Simple Step LLC" }, + { 0x1C9B, "Ohden Co., Ltd." }, + { 0x1C9C, "Technological Solutions Laboratory" }, + { 0x1C9D, "Descuentos y Electronicos AVA" }, + { 0x1C9E, "Shanghai Longcheer 3G Technology Co., Ltd." }, + { 0x1C9F, "SISS Technology Inc." }, + { 0x1CA0, "ACCARIO Inc." }, + { 0x1CA1, "Symwave, Inc." }, + { 0x1CA2, "G-coder Systems AB" }, + { 0x1CA3, "CAPAZ GmbH" }, + { 0x1CA4, "METRICO WIRELESS INC." }, + { 0x1CA5, "HASLER RAIL AG" }, + { 0x1CA6, "TECHNO-AP Limited Company" }, + { 0x1CA7, "BAE SYSTEMS AUSTRALIA LIMITED" }, + { 0x1CA8, "ROCCAT STUDIO GmbH" }, + { 0x1CA9, "THE TINTOMETER LTD." }, + { 0x1CAA, "Accel Semiconductor Corp." }, + { 0x1CAB, "SCS Engineering, Inc." }, + { 0x1CAC, "SHENZHEN KINSTONE D&T DEVELOP CO., LTD." }, + { 0x1CAD, "ONE-TOO" }, + { 0x1CAE, "MPMAN" }, + { 0x1CAF, "2WCOM GmbH" }, + { 0x1CB0, "LEGRAND FRANCE" }, + { 0x1CB1, "Enforce Device Inc." }, + { 0x1CB2, "PCO AG" }, + { 0x1CB3, "Aces Electronics Co., Ltd." }, + { 0x1CB4, "OPEX CORPORATION" }, + { 0x1CB5, "Boonton Electronics" }, + { 0x1CB6, "IDEACOM TECHNOLOGY INC." }, + { 0x1CB7, "EASTERN TIMES TECHNOLOGY CO., LTD." }, + { 0x1CB8, "Ferguson Beauregard" }, + { 0x1CB9, "DIVERSIFIED TECHNICAL SYSTEMS, INC." }, + { 0x1CBA, "MERIDIAN AUDIO LTD." }, + { 0x1CBB, "DATATEC CO., LTD." }, + { 0x1CBC, "Zizzle, LLC" }, + { 0x1CBD, "Wha Shin Co., Ltd." }, + { 0x1CBE, "Texas Instruments - Stellaris" }, + { 0x1CBF, "FORTAT SKYMARK INDUSTRIAL COMPANY" }, + { 0x1CC0, "PlantSense" }, + { 0x1CC1, "EXAKTIME INC." }, + { 0x1CC2, "CC Systems AB" }, + { 0x1CC3, "Biocomfort Diagnostics GmbH & Co. KG" }, + { 0x1CC4, "Byte Paradigm sprl" }, + { 0x1CC5, "Rane Corporation" }, + { 0x1CC6, "Digital Force Technologies" }, + { 0x1CC7, "GELOGIC" }, + { 0x1CC8, "Iofy Corporation" }, + { 0x1CC9, "COMAP, spol. s r. o." }, + { 0x1CCA, "NextWave Broadband Inc." }, + { 0x1CCB, "Lattebox Co., Ltd." }, + { 0x1CCC, "DA-DESIGN OY" }, + { 0x1CCD, "Bodatong Technology (Shenzhen) Co., Ltd." }, + { 0x1CCE, "DATA MODUL" }, + { 0x1CCF, "Konami Digital Entertainment Co., Ltd." }, + { 0x1CD0, "VEGATECH CO., LTD." }, + { 0x1CD1, "ARTAFLEX" }, + { 0x1CD2, "Christ Elektronik GmbH" }, + { 0x1CD3, "ATSUMI ELECTRIC CO., LTD." }, + { 0x1CD4, "adp corporation" }, + { 0x1CD5, "Firecomms Ltd." }, + { 0x1CD6, "Antonio Precise Products Manufactory Ltd." }, + { 0x1CD7, "GMC-I Gossen-Metrawatt GmbH" }, + { 0x1CD8, "Dash Navigation, Inc." }, + { 0x1CD9, "TL Industries" }, + { 0x1CDA, "NAVICO" }, + { 0x1CDB, "Cat Technologies Ltd." }, + { 0x1CDC, "Advanced Medical Electronics Corp." }, + { 0x1CDD, "YOOSAMFLUTE CO., LTD." }, + { 0x1CDE, "Telecommunications Technology Association (TTA)" }, + { 0x1CDF, "WonTen Technology Co., Ltd." }, + { 0x1CE0, "EDIMAX TECHNOLOGY CO., LTD." }, + { 0x1CE1, "Amphenol KAE" }, + { 0x1CE2, "Extron Electronics" }, + { 0x1CE3, "Australian Simulation Control Systems Pty., Ltd." }, + { 0x1CE4, "High Leah Electronics, Inc." }, + { 0x1CE5, "SimPhonics, Inc." }, + { 0x1CE6, "SOPRO" }, + { 0x1CE7, "FASY SPA" }, + { 0x1CE8, "Alcorn McBride, Inc." }, + { 0x1CE9, "Cadmus Payment Solutions Ltd." }, + { 0x1CEA, "MESTEK, INC." }, + { 0x1CEB, "SMARTWI" }, + { 0x1CEC, "Siemens AG I & S Postal Automation" }, + { 0x1CED, "DEWESOFT d.o.o." }, + { 0x1CEE, "Production Technology Center Kyushuu" }, + { 0x1CEF, "Siemens LD-A" }, + { 0x1CF0, "SA VALIDY" }, + { 0x1CF1, "dresden elektronik ingenieurtechnik gmbh" }, + { 0x1CF2, "TrellisWare Technologies, Inc." }, + { 0x1CF3, "Lion Power Co., Ltd." }, + { 0x1CF4, "SK INTERFACES LTD." }, + { 0x1CF5, "Swirlnet A/S" }, + { 0x1CF6, "Atlantic Zeiser GmbH" }, + { 0x1CF7, "Electric-Spin" }, + { 0x1CF8, "Biometric Associates" }, + { 0x1CF9, "Aipermon GmbH & Co. KG" }, + { 0x1CFA, "Daco Scientific Limited" }, + { 0x1CFB, "Livescribe Inc." }, + { 0x1CFC, "ANDES TECHNOLOGY CORPORATION" }, + { 0x1CFD, "Flextronics Digital Design Japan, LTD." }, + { 0x1CFE, "Cryptsoft Pty. Ltd." }, + { 0x1CFF, "Tad Radio of Canada Inc." }, + { 0x1D00, "MicroStone Corporation" }, + { 0x1D01, "SNIF Labs" }, + { 0x1D02, "DevGuru" }, + { 0x1D03, "ICON INTERNATIONAL DIGITAL LIMITED" }, + { 0x1D04, "Itronics" }, + { 0x1D05, "DESTURA S.R.L." }, + { 0x1D06, "BBK ELECTRONICS CORPORATION LIMITED" }, + { 0x1D07, "Solid-Motion" }, + { 0x1D08, "NINGBO HENTEK DRAGON ELECTRONICS CO., LTD." }, + { 0x1D09, "TechFaith Wireless Technology Limited" }, + { 0x1D0A, "Visteon Corporation" }, + { 0x1D0B, "HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD." }, + { 0x1D0C, "LAKS GmbH" }, + { 0x1D0D, "TDK Marketing Europe GmbH" }, + { 0x1D0E, "deister electronic GmbH" }, + { 0x1D0F, "NEO ELECTRONICS (HK) CO., LIMITED" }, + { 0x1D10, "Jiangsu Shinco Digital Technology Co., Ltd." }, + { 0x1D11, "Xtend Technologies Pvt. Ltd." }, + { 0x1D12, "UAB TELTONIKA" }, + { 0x1D13, "L3 Communications - Telemetry West" }, + { 0x1D14, "ALPHA-SAT TECHNOLOGY LIMITED" }, + { 0x1D15, "FUJIFILM RECORDING MEDIA GmbH" }, + { 0x1D16, "KABA MAS CORPORATION" }, + { 0x1D17, "C-THRU MUSIC Ltd." }, + { 0x1D18, "APICAL INSTRUMENTS, INC." }, + { 0x1D19, "Dexatek Technology Ltd." }, + { 0x1D1A, "Boeckeler Instruments, Inc." }, + { 0x1D1B, "HumanBeams Inc." }, + { 0x1D1C, "Novatron Oy" }, + { 0x1D1D, "SYNESTHESIA CORPORATION" }, + { 0x1D1E, "OFFCODE" }, + { 0x1D1F, "Diostech Co., Ltd." }, + { 0x1D20, "SAMTACK INC." }, + { 0x1D21, "COMPUSULT LIMITED" }, + { 0x1D22, "ELCOM s.r.o." }, + { 0x1D23, "Netsushin Co., Ltd." }, + { 0x1D24, "PHOTON KINETICS" }, + { 0x1D25, "Trinity Security Systems, Inc." }, + { 0x1D26, "ADVANCED ELECTRONICS LTD." }, + { 0x1D27, "Prime Sense Ltd." }, + { 0x1D28, "JORDAN VALLEY SEMICONDUCTORS LTD." }, + { 0x1D29, "Horng Tong Enterprise Co., Ltd." }, + { 0x1D2A, "LyconSys GmbH & Co. KG" }, + { 0x1D2B, "BEN-RI ELECTRONICA S.A." }, + { 0x1D2C, "equinux AG" }, + { 0x1D2D, "Fraunhofer IBMT" }, + { 0x1D2E, "I.S.V. Co., Ltd." }, + { 0x1D2F, "JACO, INC." }, + { 0x1D30, "Sinosun Technology Ltd." }, + { 0x1D31, "XINTRONIX LIMITED" }, + { 0x1D32, "ELECTRONICA MECHATRONIC SYSTEMS (I) PVT. LTD." }, + { 0x1D33, "Lockheed Martin - Maritime Systems & Sensors" }, + { 0x1D34, "DREAM LINK LTD." }, + { 0x1D35, "ISS Manufacturing Limited" }, + { 0x1D36, "Volucris, Inc." }, + { 0x1D37, "Phoenix Microelectronics (China) Co., Ltd." }, + { 0x1D38, "Ergowerx Int'l LLC/Smartfish Technologies" }, + { 0x1D39, "XECURENEXUS Co., LTD." }, + { 0x1D3A, "P. R. Glassel & Associates, Inc." }, + { 0x1D3B, "J & C Technology Co., Ltd." }, + { 0x1D3C, "Tomei Tsushin Kogyo Co., Ltd." }, + { 0x1D3D, "R&D Center of Biometric Technology-BMSTU" }, + { 0x1D3E, "EMCON Emanation Control Limited" }, + { 0x1D3F, "Photon Control Inc." }, + { 0x1D40, "EDANIS Elektronik AG" }, + { 0x1D41, "Teletronic Rossendorf GmbH" }, + { 0x1D42, "DRAGON JOY LIMITED" }, + { 0x1D43, "Montage Technology, Inc." }, + { 0x1D44, "Adirondack Digital Imaging Systems, Inc." }, + { 0x1D45, "Qisda Corporation" }, + { 0x1D46, "nSys Design Systems" }, + { 0x1D47, "ATAUCE" }, + { 0x1D48, "Shenzhen XinYonghui Precise Technology Co., Ltd." }, + { 0x1D49, "SHENZHEN LINKCONN ELECTRONICS CO., LTD." }, + { 0x1D4A, "HKS Co., Ltd." }, + { 0x1D4B, "DARIM VISION CO." }, + { 0x1D4C, "ARK-DESIGN Co., Ltd." }, + { 0x1D4D, "Pegatron Corporation" }, + { 0x1D4E, "INPHI CORPORATION" }, + { 0x1D4F, "ADVANCED CHIP EXPRESS INC." }, + { 0x1D50, "OPENMOKO, Inc." }, + { 0x1D51, "Sengital Limited" }, + { 0x1D52, "ELECTROBYTE di GARAVAGLIA MATTIA" }, + { 0x1D53, "Innofidei Inc." }, + { 0x1D54, "ZARAM TECHNOLOGY, Inc." }, + { 0x1D55, "XRONet Corporation" }, + { 0x1D56, "Verico International Co., Ltd." }, + { 0x1D57, "Feeling Technology Corp." }, + { 0x1D58, "SUZUKI Engineering" }, + { 0x1D59, "3DSP" }, + { 0x1D5A, "Hillcrest Laboratories, Inc." }, + { 0x1D5B, "Smartronix, Inc." }, + { 0x1D5C, "Fresco Logic Inc." }, + { 0x1D5D, "QIXING INDUSTRIAL (HK) CO." }, + { 0x1D5E, "Tonium AB" }, + { 0x1D5F, "ViVOtech, Inc." }, + { 0x1D60, "ASAP International Co., Ltd." }, + { 0x1D61, "ACCEMIC GmbH & CO. KG" }, + { 0x1D62, "KYORITSU ELECTRIC CO., LTD." }, + { 0x1D63, "Nippon Seiki Co., Ltd." }, + { 0x1D64, "MobilMAX Technology Inc." }, + { 0x1D65, "Moteurs LEROY SOMER" }, + { 0x1D66, "StreamBuster" }, + { 0x1D67, "DYNAMIC INNOVATIONS LIMITED" }, + { 0x1D68, "SEMA ELECTRONICS (H.K.) CO., Ltd." }, + { 0x1D69, "Walta Electronic Co., Ltd." }, + { 0x1D6A, "ARICENT TECHNOLOGIES (HOLDINGS) LTD." }, + { 0x1D6B, "The Linux Foundation" }, + { 0x1D6C, "Man & Machine, Inc." }, + { 0x1D6D, "VARISYS LIMITED" }, + { 0x1D6E, "EUROTECH" }, + { 0x1D6F, "Seluxit" }, + { 0x1D70, "MULTIPLE ACCESS COMMUNICATIONS LTD." }, + { 0x1D71, "Finisar Corporation" }, + { 0x1D72, "Mobiltex Data Ltd." }, + { 0x1D73, "Signal Processing Devices Sweden AB" }, + { 0x1D74, "LG Innotek Co., Ltd." }, + { 0x1D75, "DICOM, spol. s r.o." }, + { 0x1D76, "LongCheng Electronic & Communication CO., LTD." }, + { 0x1D77, "Yueqing Changling Electronic Instrument Corp., Ltd." }, + { 0x1D78, "CAMBRIDGE SEMICONDUCTOR LTD." }, + { 0x1D79, "Shenzhen Innosystem Technology Ltd." }, + { 0x1D7A, "SHINWA INTERNATIONAL HOLDINGS LTD." }, + { 0x1D7B, "Single Strand Co., Ltd." }, + { 0x1D7C, "KarmelSonix" }, + { 0x1D7D, "Seoul Commtech Co., Ltd." }, + { 0x1D7E, "WAVESAT" }, + { 0x1D7F, "MoBeam, Inc." }, + { 0x1D80, "PLDA" }, + { 0x1D81, "YongXin Plastic & Hardware Co., Ltd." }, + { 0x1D82, "HERTZ SYSTEMTECHNIK GmbH" }, + { 0x1D83, "Mantech International" }, + { 0x1D84, "Kechenda Plastic Electronic Factory" }, + { 0x1D85, "NINGBO SHUNSHENG COMMUNICATION APPARATUS CO., LTD." }, + { 0x1D86, "C.D.N. CORPORATION" }, + { 0x1D87, "RHK TECHNOLOGY, INC." }, + { 0x1D88, "Mahr GmbH" }, + { 0x1D89, "Hunter Associates" }, + { 0x1D8A, "OSASI Technos Inc. (Tokyo Headquarters)" }, + { 0x1D8B, "MEDTRONIC" }, + { 0x1D8C, "Wuxi AlphaScale IC Systems, Inc." }, + { 0x1D8D, "EXEO SYSTEMS" }, + { 0x1D8E, "Capistrano Labs, Inc." }, + { 0x1D8F, "Viprinet GmbH" }, + { 0x1D90, "CITIZEN SYSTEMS JAPAN CO., LTD." }, + { 0x1D91, "BYD COMPANY LIMITED" }, + { 0x1D92, "SPECTRONIC DEVICES LTD." }, + { 0x1D93, "Tokyo System Development Co., Ltd." }, + { 0x1D94, "ENCIRIS TECHNOLOGIES" }, + { 0x1D95, "SYSTRONIK Elektronik und Systemtechnik GmbH" }, + { 0x1D96, "CHIRSON LTD." }, + { 0x1D97, "Telonics" }, + { 0x1D98, "OUTLINE ELECTRONICS LTD." }, + { 0x1D99, "Shanghai HSIC Application System Co., Ltd." }, + { 0x1D9A, "Vubiq, Inc." }, + { 0x1D9B, "Techno Source" }, + { 0x1D9C, "SONIM TECHNOLOGIES, INC." }, + { 0x1D9D, "Sigma Elektro GmbH" }, + { 0x1D9E, "CSR, Inc." }, + { 0x1D9F, "KUNMING ELECTRONICS CO., LTD." }, + { 0x1DA0, "Parade Technologies, Inc." }, + { 0x1DA1, "COVIDENCE A/S" }, + { 0x1DA2, "LAMBDA, INC." }, + { 0x1DA3, "bebro electronic GmbH" }, + { 0x1DA4, "BTICINO" }, + { 0x1DA5, "CATHEXIS INNOVATIONS INC." }, + { 0x1DA6, "Inepro BV" }, + { 0x1DA7, "ENDRA Inc." }, + { 0x1DA8, "VIOLET" }, + { 0x1DA9, "In-Circuit GmbH" }, + { 0x1DAA, "Alcatel-Lucent" }, + { 0x1DAB, "MAGELLAN GPS" }, + { 0x1DAC, "MOBOTIX AG" }, + { 0x1DAD, "DATNET KFT" }, + { 0x1DAE, "ellipsis INC." }, + { 0x1DAF, "Breas Medical AB" }, + { 0x1DB0, "GreenPeak Technologies NV" }, + { 0x1DB1, "Reliable Controls Corporation" }, + { 0x1DB2, "Duali Inc." }, + { 0x1DB3, "Arcelik A.S." }, + { 0x1DB4, "Montalvo Systems" }, + { 0x1DB5, "BRYSTON LTD." }, + { 0x1DB6, "eDimensional, Inc." }, + { 0x1DB7, "SMedia Technology Corporation" }, + { 0x1DB8, "HD MEDICAL INC." }, + { 0x1DB9, "LITEN UP TECHNOLOGIES INC." }, + { 0x1DBA, "BancTec, Inc." }, + { 0x1DBB, "Condalo GmbH" }, + { 0x1DBC, "Shenzhen HOJY Technology Co., Ltd." }, + { 0x1DBD, "Terawins" }, + { 0x1DBE, "S.R.N. Corporation" }, + { 0x1DBF, "Signostics Pty. Ltd." }, + { 0x1DC0, "DATAFIELD INDIA PVT.LTD." }, + { 0x1DC1, "Laser Drive" }, + { 0x1DC2, "Datalogic Mobile Inc." }, + { 0x1DC3, "PoLabs" }, + { 0x1DC4, "TRANSICS" }, + { 0x1DC5, "Pixim Inc." }, + { 0x1DC6, "Miyama, Inc." }, + { 0x1DC7, "Leroy Automatique Industrielle" }, + { 0x1DC8, "GC Corporation" }, + { 0x1DC9, "Hitachi Koki Co., Ltd." }, + { 0x1DCA, "The IVOXX Corp." }, + { 0x1DCB, "IFTEST AG" }, + { 0x1DCC, "Document Capture Technologies, Inc." }, + { 0x1DCD, "HIN KUI MACHINE & METAL INDUSTRIAL CO., LTD." }, + { 0x1DCE, "SIMTEC Elektronik GmbH" }, + { 0x1DCF, "INVIX Co., Ltd." }, + { 0x1DD0, "ABB AS, Division Automation Products" }, + { 0x1DD1, "EFJohnson" }, + { 0x1DD2, "LEO BODNAR" }, + { 0x1DD3, "Dajac, Inc." }, + { 0x1DD4, "ARMELIN WIDGET CORPORATION" }, + { 0x1DD5, "MetaGeek, LLC" }, + { 0x1DD6, "Solomon Technology Corp." }, + { 0x1DD7, "REDMERE TECHNOLOGY" }, + { 0x1DD8, "BUFFALO KOKUYO SUPPLY INC." }, + { 0x1DD9, "EFFICERE TECHNOLOGIES" }, + { 0x1DDA, "TA Instruments" }, + { 0x1DDB, "Abon Touchsystems Inc." }, + { 0x1DDC, "id Quantique" }, + { 0x1DDD, "DOKING ELECTRONIC TECHNOLOGY CO., LTD." }, + { 0x1DDE, "TridonicAtco" }, + { 0x1DDF, "L&T Technology Services" }, + { 0x1DE0, "Shenzhen Excelstor Technology Ltd." }, + { 0x1DE1, "Actions Microelectronics Co., Ltd." }, + { 0x1DE2, "ENTERY INDUSTRIAL CO., LTD." }, + { 0x1DE3, "SHENZHEN REX ELECTRONICS CO., LTD." }, + { 0x1DE4, "DAEWOO ELECTRONICS CORPORATION" }, + { 0x1DE5, "AMONTEC" }, + { 0x1DE6, "MICRORISC S.R.O." }, + { 0x1DE7, "MIDAS TECHNOLOGY" }, + { 0x1DE8, "Applied Systems Engineering, Inc." }, + { 0x1DE9, "Seco Technology Co., Ltd." }, + { 0x1DEA, "Yesin Electronics Technology Co., Ltd." }, + { 0x1DEB, "SHIUH CHI PRECISION INDUSTRY CO., LTD." }, + { 0x1DEC, "HAGER CONTROLS SAS" }, + { 0x1DED, "COOLIT SYSTEMS, INC." }, + { 0x1DEE, "JCM II, Inc." }, + { 0x1DEF, "KYOTO KAGAKU CO., LTD." }, + { 0x1DF0, "TRICKLESTAR LIMITED" }, + { 0x1DF1, "HUATIANYUAN ELECTRONIC INDUSTRY CO., LTD." }, + { 0x1DF2, "China Telecommunication Technology Labs - Terminals" }, + { 0x1DF3, "CRESYN CO., LTD." }, + { 0x1DF4, "SHEN ZHEN FORMAN PRECISION INDUSTRY CO., LTD." }, + { 0x1DF5, "Universal Remote Control, Inc." }, + { 0x1DF6, "TakeMS International AG" }, + { 0x1DF7, "Mirics Semiconductor Ltd." }, + { 0x1DF8, "The Charles Machine Works, Inc." }, + { 0x1DF9, "Komax AG" }, + { 0x1DFA, "BLOCKMASTER AB" }, + { 0x1DFB, "marco Systemanalyse und Entwicklung GmbH" }, + { 0x1DFC, "YUNNAN NANTIAN ELECTRONICS INFORMATION CO., LTD." }, + { 0x1DFD, "Quality Thermistor, Inc." }, + { 0x1DFE, "BEDA Precision" }, + { 0x1DFF, "InfraRed Integrated Systems Ltd." }, + { 0x1E00, "Jupiter Systems" }, + { 0x1E01, "Dynalloy, Inc." }, + { 0x1E02, "GLOBEMASTER TECHNOLOGIES CO., LTD." }, + { 0x1E03, "OXFORD INSTRUMENTS ANALYTICAL OY" }, + { 0x1E04, "Coolsand Technologies (Hong Kong) Ltd." }, + { 0x1E05, "Microtronic AG" }, + { 0x1E06, "Moore Industries International" }, + { 0x1E07, "GETA ELECTRONICS (DONG GUAN) CO., LTD." }, + { 0x1E08, "Inventure, Inc." }, + { 0x1E09, "Baldwin Boxall Communication Ltd." }, + { 0x1E0A, "NOX Medical" }, + { 0x1E0B, "TUBITAK UEKAE" }, + { 0x1E0C, "NATIONAL HYBRID, INC." }, + { 0x1E0D, "NEOWAVE" }, + { 0x1E0E, "SHANGHAI BASECOM LTD." }, + { 0x1E0F, "mSilica Inc." }, + { 0x1E10, "FLIR Integrated Imaging Solutions" }, + { 0x1E11, "Hoya Xponent" }, + { 0x1E12, "OCTRIAN" }, + { 0x1E13, "Burgundy Electric, LLC" }, + { 0x1E14, "YANtide Corporation" }, + { 0x1E15, "mStation" }, + { 0x1E16, "SMARTIO" }, + { 0x1E17, "Mirion Technologies Inc." }, + { 0x1E18, "MIGHT Co., Ltd." }, + { 0x1E19, "Torus Networks Co., Ltd." }, + { 0x1E1A, "HITEC RCD KOREA" }, + { 0x1E1B, "e-Practical Solutions" }, + { 0x1E1C, "CMS PRODUCTS" }, + { 0x1E1D, "Kanguru Solutions" }, + { 0x1E1E, "Trans New Technology, Inc." }, + { 0x1E1F, "INVIA" }, + { 0x1E20, "JDSU" }, + { 0x1E21, "NEONUMERIC" }, + { 0x1E22, "LEDCO" }, + { 0x1E23, "Aeronix, Inc." }, + { 0x1E24, "Cine-tal Systems, Inc." }, + { 0x1E25, "3M Cogent, Inc." }, + { 0x1E26, "Multi Channel Systems MCS GmbH" }, + { 0x1E27, "NASA / Johnson Space Center / EV2" }, + { 0x1E28, "Raptor Innovations International" }, + { 0x1E29, "Festo AG & Co. KG" }, + { 0x1E2A, "NANOFORTI INC." }, + { 0x1E2B, "3M CMD (Communication Markets Division)" }, + { 0x1E2C, "KRONIK ELEKTRONIK SANAYI VETICARET LIMITED SIRKETI" }, + { 0x1E2D, "Cinterion Wireless Modules GmbH" }, + { 0x1E2E, "Syrinx Industrial Electronics b.v." }, + { 0x1E2F, "Celrun Co., Ltd." }, + { 0x1E30, "Kohler Co." }, + { 0x1E31, "Greatbatch" }, + { 0x1E32, "Opti-Sciences, Inc." }, + { 0x1E33, "KOBIAN CANADA INC." }, + { 0x1E34, "Sensory, Inc." }, + { 0x1E35, "BELLING Co., Ltd." }, + { 0x1E36, "Insulet Corporation" }, + { 0x1E37, "Rehoboth Tech. Co., Ltd." }, + { 0x1E38, "QRS Music Technologies Inc." }, + { 0x1E39, "YIS Corporation" }, + { 0x1E3A, "Continental Automotive Systems Inc." }, + { 0x1E3B, "MICROBIT 2.0 AB" }, + { 0x1E3C, "Vapor Bus Int'l Div of Westinghouse Air Brake Tech Corp" }, + { 0x1E3D, "Chipsbrand Technologies (HK) Co., Limited" }, + { 0x1E3E, "EMS Aviation" }, + { 0x1E3F, "JJ Keller & Associates Inc." }, + { 0x1E40, "SciLog, Inc." }, + { 0x1E41, "Cleverscope Ltd." }, + { 0x1E42, "SSE GmbH" }, + { 0x1E43, "Sagem Mobiles" }, + { 0x1E44, "SHIMANO INC." }, + { 0x1E45, "TADANO LTD." }, + { 0x1E46, "Danfoss A/S" }, + { 0x1E47, "HUNG TA H.T.ENTERPRISE CO., LTD." }, + { 0x1E48, "LABAU Technology" }, + { 0x1E49, "FES LLC" }, + { 0x1E4A, "CHIRON TECHNOLOGY LTD." }, + { 0x1E4B, "exxact GmbH" }, + { 0x1E4C, "Stereotaxis, Inc." }, + { 0x1E4D, "BST International GmbH" }, + { 0x1E4E, "Etron Technology, Inc." }, + { 0x1E4F, "SECOM Co., Ltd." }, + { 0x1E50, "VILTECHMEDA UAB" }, + { 0x1E51, "DiMoto" }, + { 0x1E52, "SZ TELSTAR CO., LTD." }, + { 0x1E53, "WYPLAY" }, + { 0x1E54, "TypeMatrix Inc." }, + { 0x1E55, "Memorysolution GmbH" }, + { 0x1E56, "EURINTEL" }, + { 0x1E57, "Bundesdruckerei GmbH" }, + { 0x1E58, "Horner APG" }, + { 0x1E59, "inTera Tecnologia" }, + { 0x1E5A, "VOXTRONIC TECHNOLOGY" }, + { 0x1E5B, "APRICO A/S" }, + { 0x1E5C, "Enova Technology Corp." }, + { 0x1E5D, "SAT Corporation" }, + { 0x1E5E, "Touch International" }, + { 0x1E5F, "Relpol SA" }, + { 0x1E60, "SEA Signalisation" }, + { 0x1E61, "Anoto AB" }, + { 0x1E62, "Uriver Inc." }, + { 0x1E63, "DRAEGER MEDICAL" }, + { 0x1E64, "IMSTORAGE CO., LTD." }, + { 0x1E65, "THE BOEING CO." }, + { 0x1E66, "KAPSYS" }, + { 0x1E67, "Orban/CRL Systems, Inc." }, + { 0x1E68, "TrekStor GmbH & Co. KG" }, + { 0x1E69, "Hormann Funkwerk Kolleda GmbH" }, + { 0x1E6A, "RGB Spectrum" }, + { 0x1E6B, "iRex Technologies B.V." }, + { 0x1E6C, "Sureshotgps Pty. Ltd." }, + { 0x1E6D, "WAN SHIH ELECTRONIC (H.K.) CO., LTD." }, + { 0x1E6E, "F&D Feinwerk-Und Drucktechnik GmbH" }, + { 0x1E6F, "Images Scientific Instruments Inc." }, + { 0x1E70, "POSBRO Inc." }, + { 0x1E71, "NZXT Corporation" }, + { 0x1E72, "Federal Signal Corporation" }, + { 0x1E73, "COMLINK ELECTRONICS CO., LTD." }, + { 0x1E74, "COBY COMMUNICATIONS, LIMITED" }, + { 0x1E75, "TLS Communication GmbH" }, + { 0x1E76, "Proview Technology (Shenzhen) Co., Ltd." }, + { 0x1E77, "Core Micro Technology Inc." }, + { 0x1E78, "Flextronics R & D (Shenzhen) Co., Ltd." }, + { 0x1E79, "ISA Co., Ltd." }, + { 0x1E7A, "The Tsurumi-Seiki Company, Limited" }, + { 0x1E7B, "Zurich Instruments AG" }, + { 0x1E7C, "biostep GmbH" }, + { 0x1E7D, "ROCCAT GmbH" }, + { 0x1E7E, "Bright Star Engineering Inc." }, + { 0x1E7F, "NEXS ELECTRONIC CORP." }, + { 0x1E80, "InterDigital Communications LLC" }, + { 0x1E81, "KIDS PREFERRED, LLC." }, + { 0x1E82, "Nortech Systems" }, + { 0x1E83, "AMICUS WIRELESS" }, + { 0x1E84, "VIVAX CORPORATION" }, + { 0x1E85, "Gigaset Communications GmbH" }, + { 0x1E86, "Japan Meditech Co., Ltd." }, + { 0x1E87, "W&W Communications Inc." }, + { 0x1E88, "GBS Laboratories, LLC" }, + { 0x1E89, "Vtion Information Technology (Fujian) Co., Ltd." }, + { 0x1E8A, "HIBEST Electronic (DongGuan) Co., Ltd." }, + { 0x1E8B, "ImTech, Inc." }, + { 0x1E8C, "Data Conversion Systems Ltd." }, + { 0x1E8D, "HIGHVOLT Prueftechnik Dresden GmbH" }, + { 0x1E8E, "EADS Secure Networks" }, + { 0x1E8F, "PublicSolution GmbH" }, + { 0x1E90, "Mego Afek" }, + { 0x1E91, "Other World Computing" }, + { 0x1E92, "Beyond Question Learning Technologies, Inc." }, + { 0x1E93, "GSI Group" }, + { 0x1E94, "RealD" }, + { 0x1E95, "DIRECTV, Inc." }, + { 0x1E96, "BlueAnt Wireless" }, + { 0x1E97, "TOMMYCA HONG KONG LIMITED" }, + { 0x1E98, "COMPASS SYSTEMS CORP." }, + { 0x1E99, "General Dynamics C4 Systems" }, + { 0x1E9A, "MANTHAN SEMICONDUCTOR PVT. LTD." }, + { 0x1E9B, "Netcom Sicherheitstechnik GmbH" }, + { 0x1E9C, "FirstPaper, LLC" }, + { 0x1E9D, "GEOTEST AG" }, + { 0x1E9E, "InnoSys Inc." }, + { 0x1E9F, "Chase Peabody and Associates, Inc." }, + { 0x1EA0, "DiabloSport, Inc." }, + { 0x1EA1, "NANOBASE" }, + { 0x1EA2, "N.V. Nederlandsche Apparatenfabriek Nedap" }, + { 0x1EA3, "Concraft Holding Co., Ltd." }, + { 0x1EA4, "MOBILE SYSTEM TECHNOLOGIES INC." }, + { 0x1EA5, "CEN LINK CO., LTD." }, + { 0x1EA6, "novero GmbH" }, + { 0x1EA7, "SEMITEK INTERNATIONAL (HK) HOLDING LTD." }, + { 0x1EA8, "Shenzhen Excelsecu Data Technology Co., Ltd." }, + { 0x1EA9, "ANDERS ELECTRONICS PLC" }, + { 0x1EAA, "Zeebo, Inc." }, + { 0x1EAB, "Fujian Newland Auto-ID Tech. Co., Ltd." }, + { 0x1EAC, "Thinkware Systems" }, + { 0x1EAD, "Industrial Control Communications, Inc." }, + { 0x1EAE, "YESCNC CO., LTD." }, + { 0x1EAF, "Continental Trading GmbH" }, + { 0x1EB0, "Centers for Disease Control & Prevention (CDC)" }, + { 0x1EB1, "Kramer Electronics Ltd." }, + { 0x1EB2, "IWAKI CO., LTD." }, + { 0x1EB3, "SAE MAGNETICS (HK) LTD." }, + { 0x1EB4, "YuhDing Precision Industry (KunShan) Co., Ltd." }, + { 0x1EB5, "Diablo Technologies Inc." }, + { 0x1EB6, "PHYLINKS LIMITED" }, + { 0x1EB7, "WIN WIN PRECISION INDUSTRIAL CO., LTD." }, + { 0x1EB8, "MODACOM CO., LTD." }, + { 0x1EB9, "Campbell Scientific Inc." }, + { 0x1EBA, "HITTITE MICROWAVE CORP." }, + { 0x1EBB, "NuCORE Technology, Inc." }, + { 0x1EBC, "Beijing Novel-Super Media Investment Co., Ltd." }, + { 0x1EBD, "Wireless Matrix Corp." }, + { 0x1EBE, "Qwizdom, Inc." }, + { 0x1EBF, "Yulong Computer Telecommunication Scientific" }, + { 0x1EC0, "VIGORHOOD PHOTOELECTRIC SHENZHEN CO., LTD." }, + { 0x1EC1, "PROTEK DEVICES" }, + { 0x1EC2, "CHUO ELECTRONICS CO., LTD." }, + { 0x1EC3, "ANDREAS STIHL AG & Co. KG" }, + { 0x1EC4, "ELTRONIC SOLUTION A/S" }, + { 0x1EC5, "SIDSA" }, + { 0x1EC6, "PHYWORKS LTD." }, + { 0x1EC7, "Gefen Inc." }, + { 0x1EC8, "TelePath Technologies Co., Ltd." }, + { 0x1EC9, "MOSER BAER INDIA LIMITED" }, + { 0x1ECA, "Mintpass Co., Ltd." }, + { 0x1ECB, "Advanced Mobile Telecom Co., Ltd." }, + { 0x1ECC, "Enfora, Inc." }, + { 0x1ECD, "Alverix Inc." }, + { 0x1ECE, "MyungMin Systems, Inc." }, + { 0x1ECF, "MDR Grup S.R.L." }, + { 0x1ED0, "Hirschmann Car Communication GmbH" }, + { 0x1ED1, "DIGITAL CHINA NETWORKS (BEIJING) LIMITED" }, + { 0x1ED2, "Crevis Co., Ltd." }, + { 0x1ED3, "Forsis GmbH" }, + { 0x1ED4, "Transwitch (Israel) Ltd." }, + { 0x1ED5, "LLC GlobalTest" }, + { 0x1ED6, "adidas International" }, + { 0x1ED7, "Headplay, Inc." }, + { 0x1ED8, "Fender Musical Instruments Corp." }, + { 0x1ED9, "ALBUMteam, Ltd." }, + { 0x1EDA, "AIRTIES WIRELESS NETWORKS" }, + { 0x1EDB, "BLACKMAGIC DESIGN PTY." }, + { 0x1EDC, "B-DeltaCom" }, + { 0x1EDD, "IRIDIUM SATELLITE LLC" }, + { 0x1EDE, "steute Schaltgerate GmbH & Co. KG" }, + { 0x1EDF, "Selectwireless Co., Ltd." }, + { 0x1EE0, "KYUDEN TECHNOSYSTEMS CORPORATION" }, + { 0x1EE1, "Matrix Key Inc." }, + { 0x1EE2, "NOVA GAMING" }, + { 0x1EE3, "3D INNOVATIONS, LLC" }, + { 0x1EE4, "Luff Technology Co., Ltd." }, + { 0x1EE5, "Spring Soft K.K." }, + { 0x1EE6, "SHENZHEN EVERWIN PRECISION TECHNOLOGY CO., LTD." }, + { 0x1EE7, "EPCOS" }, + { 0x1EE8, "ONDA COMMUNICATION S.p.a." }, + { 0x1EE9, "PC PARTNER LIMITED" }, + { 0x1EEA, "Yullin Technologies Co., Ltd." }, + { 0x1EEB, "GEOTATE" }, + { 0x1EEC, "CTC Analytics AG" }, + { 0x1EED, "Helo Oy / Helo Ltd." }, + { 0x1EEE, "RigiSystems AG" }, + { 0x1EEF, "I.C.Y. B.V." }, + { 0x1EF0, "Thunder Tiger Corp." }, + { 0x1EF1, "PQ Computing Ltd." }, + { 0x1EF2, "Vircion Inc." }, + { 0x1EF3, "JIANGXI SHIP ELECTRONICS CO., LTD." }, + { 0x1EF4, "TATA ELXSI LTD." }, + { 0x1EF5, "Impinj, Inc." }, + { 0x1EF6, "EADS Deutschland GmbH" }, + { 0x1EF7, "ZiiLABS Ltd." }, + { 0x1EF8, "CRITICAL LINK, LLC" }, + { 0x1EF9, "US Army Electronic Proving Ground" }, + { 0x1EFA, "SEIKO Precision Inc." }, + { 0x1EFB, "IMI Hydronic Engineering International SA" }, + { 0x1EFC, "IMOGEN STUDIO" }, + { 0x1EFD, "ROFIN-SINAR LASER GMBH" }, + { 0x1EFE, "Sound Design Technologies" }, + { 0x1EFF, "Kinemetrics, Inc." }, + { 0x1F00, "YUEQING ZHONGLI COMPUTER ELECTRONICS CO., LTD." }, + { 0x1F01, "Geo Studio Technology" }, + { 0x1F02, "Australian National University" }, + { 0x1F03, "PTW Freiburg GmbH" }, + { 0x1F04, "Watlow" }, + { 0x1F05, "Kyosai Technos Co., Ltd." }, + { 0x1F06, "K.T.E.-Keter Technologies Europe" }, + { 0x1F07, "OPTOQUEST Co., Ltd." }, + { 0x1F08, "Digital Ally Inc." }, + { 0x1F09, "DURAG GmbH" }, + { 0x1F0A, "AUROX Ltd." }, + { 0x1F0B, "INTRONIX TEST INSTURMENTS, INC." }, + { 0x1F0C, "Fourier Systems Ltd." }, + { 0x1F0D, "NAMOS" }, + { 0x1F0E, "Inflexis Corporation" }, + { 0x1F0F, "Action Technology (SZ) Co., Ltd." }, + { 0x1F10, "LTW TECHNOLOGY CO., LTD." }, + { 0x1F11, "VIRAGE LOGIC" }, + { 0x1F12, "Photometrics" }, + { 0x1F13, "CENTURY SYSTEMS Co., Ltd." }, + { 0x1F14, "Astoria Networks GmbH" }, + { 0x1F15, "Schmitt Industries Inc." }, + { 0x1F16, "Olidata SpA" }, + { 0x1F17, "APIS Device, Inc." }, + { 0x1F18, "Teseq GmbH" }, + { 0x1F19, "POLATIS INC." }, + { 0x1F1A, "Sanden Retail Systems Corporation" }, + { 0x1F1B, "NORTHROP GRUMMAN SPERRY MARINE" }, + { 0x1F1C, "LXE, INC." }, + { 0x1F1D, "How Weih Precision Technology (Shenzhen) Co., Ltd." }, + { 0x1F1E, "TSIEN (UK) LTD." }, + { 0x1F1F, "RaaX Co., Ltd." }, + { 0x1F20, "Shenzhen Tenwei Electronics Co., Ltd." }, + { 0x1F21, "Scosche Industries" }, + { 0x1F22, "STAr Technologies, Inc." }, + { 0x1F23, "KOUEI SYSTEM, LTD." }, + { 0x1F24, "EBTRON INC." }, + { 0x1F25, "Victron Energy B.V." }, + { 0x1F26, "INCAP GmbH" }, + { 0x1F27, "KEE Action Sports (Hater Paintball)" }, + { 0x1F28, "Cal-Comp Electronics & Communications" }, + { 0x1F29, "Analogix Semiconductor, Inc." }, + { 0x1F2A, "Scene Double Ltd." }, + { 0x1F2B, "JUKI CORPORATION" }, + { 0x1F2C, "SELESTA INGEGNERIA SPA" }, + { 0x1F2D, "Liteye Systems, Inc." }, + { 0x1F2E, "ARMOUR GROUP PLC." }, + { 0x1F2F, "UPOS SYSTEM SP. Z O.O." }, + { 0x1F30, "RENA GmbH" }, + { 0x1F31, "SASKEN COMMUNICATION TECH LTD." }, + { 0x1F32, "COCHLEAR TECHNOLOGY CENTRE BELGIUM" }, + { 0x1F33, "GrupoPIE Portugal, S.A." }, + { 0x1F34, "Dutronics" }, + { 0x1F35, "Amphenol ShouhMin Industry (ShenZhen) Co., Ltd" }, + { 0x1F36, "ddm hopt + schuler GmbH & Co. KG" }, + { 0x1F37, "Next Step Solutions Limited" }, + { 0x1F38, "Kesumo, LLC" }, + { 0x1F39, "Sumitomo Electric Networks, Inc." }, + { 0x1F3A, "Allwinner Technology Co., Ltd." }, + { 0x1F3B, "Biocryptodisk Sdn Bhd" }, + { 0x1F3C, "Chang Yang Electronics Company Ltd." }, + { 0x1F3D, "Advanced Engineering Services Co., Ltd." }, + { 0x1F3E, "Telenot Electronic GmbH" }, + { 0x1F3F, "SECA GmbH & Co. KG" }, + { 0x1F40, "JiangSu Dongda Integrated Circuits Sys. Eng. Tech. Co." }, + { 0x1F41, "Nipro Diagnostics, Inc" }, + { 0x1F42, "ID2P TECHNOLOGIES, INC." }, + { 0x1F43, "RAPID BRIDGE LLC" }, + { 0x1F44, "Digital Business Process (dba: The Neat Company)" }, + { 0x1F45, "QUALCOMM ENTERPRISE SERVICES" }, + { 0x1F46, "Gener8, Inc." }, + { 0x1F47, "Orb Networks, Inc." }, + { 0x1F48, "H-TRONIC GmbH" }, + { 0x1F49, "Exelis, Inc." }, + { 0x1F4A, "Key Ingredient Corporation" }, + { 0x1F4B, "Precision System Science Co., Ltd." }, + { 0x1F4C, "Cyber Sport Pty., Ltd." }, + { 0x1F4D, "SHENZHEN GENIATECH INC., LTD." }, + { 0x1F4E, "OFF-NET SERVICE LIMITED" }, + { 0x1F4F, "EXAR CORPORATION - JAPAN" }, + { 0x1F50, "KEMPPI OY" }, + { 0x1F51, "Helmut Hund GmbH" }, + { 0x1F52, "Systems & Electronic Development FZCO (SEDCO)" }, + { 0x1F53, "SK telesys" }, + { 0x1F54, "LOEC, INC." }, + { 0x1F55, "Fujitsu Electronics Europe GmbH" }, + { 0x1F56, "MUT" }, + { 0x1F57, "PIGNOLO S.P.A." }, + { 0x1F58, "Inmarsat" }, + { 0x1F59, "EL.MO. S.P.A." }, + { 0x1F5A, "Micronova srl." }, + { 0x1F5B, "KYODO COMMUNICATIONS & ELECTRONICS INC." }, + { 0x1F5C, "MIDORI ANZEN CO., LTD." }, + { 0x1F5D, "Mobii Systems (Pty) Ltd." }, + { 0x1F5E, "Johnson Outdoors Marine Electronics, Inc." }, + { 0x1F5F, "NETCLEUS SYSTEMS Corporation" }, + { 0x1F60, "Young at Heart International Ltd." }, + { 0x1F61, "Flexocard GmbH" }, + { 0x1F62, "Elquest Corporation" }, + { 0x1F63, "IriTech, Inc." }, + { 0x1F64, "actionXL, Inc." }, + { 0x1F65, "Taylor Technologies, Co., Ltd." }, + { 0x1F66, "Hokkaido Electronics Corporation" }, + { 0x1F67, "MICRO INNOVATIONS CORP." }, + { 0x1F68, "General Dynamics UK Limited" }, + { 0x1F69, "NVIS, Inc." }, + { 0x1F6A, "AJA VIDEO SYSTEMS INC." }, + { 0x1F6B, "Muve, Inc." }, + { 0x1F6C, "Cadex Electronics Inc." }, + { 0x1F6D, "AMTI" }, + { 0x1F6E, "AccuVein LLC" }, + { 0x1F6F, "ALIPHCOM, INC." }, + { 0x1F70, "MKD Technology Inc." }, + { 0x1F71, "Huaya Microelectronics (HK) Ltd." }, + { 0x1F72, "GM INSTRUMENTS LTD." }, + { 0x1F73, "Record4Free.TV AG" }, + { 0x1F74, "UNISTO Ltd." }, + { 0x1F75, "Innostor Co., Ltd." }, + { 0x1F76, "CYBER-RAIN, INC." }, + { 0x1F77, "POSITRON PUBLIC SAFETY SYSTEMS" }, + { 0x1F78, "UNION TOOL CO." }, + { 0x1F79, "Rosen Technology and Research Center GmbH" }, + { 0x1F7A, "WhiteOak Controls Inc." }, + { 0x1F7B, "AVMAP SRL" }, + { 0x1F7C, "Voltopia e.U." }, + { 0x1F7D, "UNICARD S.A." }, + { 0x1F7E, "Canon India Private Limited" }, + { 0x1F7F, "NOVA Sensors" }, + { 0x1F80, "MagicPixel Inc." }, + { 0x1F81, "HYB D.O.O." }, + { 0x1F82, "TANDBERG TELECOM AS" }, + { 0x1F83, "Beauty Up Co., Ltd." }, + { 0x1F84, "Inverness Medical Innovations, Inc." }, + { 0x1F85, "Netronix Inc." }, + { 0x1F86, "Skyworth Overseas Development Limited" }, + { 0x1F87, "STANTUM" }, + { 0x1F88, "Modu Ltd." }, + { 0x1F89, "Dongguan Goldconn Electronics Co., Ltd." }, + { 0x1F8A, "Morning Star Industrial Co., Ltd." }, + { 0x1F8B, "Rittal GmbH & Co. KG" }, + { 0x1F8C, "Reference, LLC." }, + { 0x1F8D, "DEVICE FUNCTIONS" }, + { 0x1F8E, "SENSE INSIDE GmbH" }, + { 0x1F8F, "Narda Safety Test Solutions GmbH" }, + { 0x1F90, "PURE TECHNOLOGIES" }, + { 0x1F91, "Wilhelm Mikroelektronik GmbH" }, + { 0x1F92, "INTERNATIONAL TECHNIDYNE CORP." }, + { 0x1F93, "Alcohol Monitoring Systems, Inc." }, + { 0x1F94, "Microhard Systems Inc." }, + { 0x1F95, "Art of Technology AG" }, + { 0x1F96, "Ascend Geo, LLC" }, + { 0x1F97, "OZMO, INC. DBA OZMO DEVICES" }, + { 0x1F98, "DSP Design Limited" }, + { 0x1F99, "TOKAI RIKEN CO., LTD." }, + { 0x1F9A, "Barron Associates, Inc." }, + { 0x1F9B, "UBIQUITI Networks, Inc." }, + { 0x1F9C, "ARVOO Engineering BV" }, + { 0x1F9D, "Tri Works" }, + { 0x1F9E, "MUTECH LIMITED" }, + { 0x1F9F, "CasaTools, LLC" }, + { 0x1FA0, "XLNT IDEA, INC." }, + { 0x1FA1, "Curtis Instruments, Inc." }, + { 0x1FA2, "AMETEK DENMARK A/S" }, + { 0x1FA3, "LAIRD TECHNOLOGIES" }, + { 0x1FA4, "BRIDGEPORT INSTRUMENTS, LLC" }, + { 0x1FA5, "DELTA DORE" }, + { 0x1FA6, "Daylight Solutions, Inc." }, + { 0x1FA7, "COSMOS WEB CO., LTD." }, + { 0x1FA8, "TCL Technoly Electronics (Hui Zhou) Co., Ltd." }, + { 0x1FA9, "Digital Information Technologies Corporation" }, + { 0x1FAA, "Zhong Shan City Li Tai Electronic Industrial Co., Ltd." }, + { 0x1FAB, "SAMSUNG DIGITAL IMAGING CO., LTD." }, + { 0x1FAC, "Franklin Technology Inc." }, + { 0x1FAD, "Cresta Technology Inc." }, + { 0x1FAE, "Lumidigm, Inc." }, + { 0x1FAF, "Weintek Labs, Inc." }, + { 0x1FB0, "Discera, Inc." }, + { 0x1FB1, "Weatronic GmbH" }, + { 0x1FB2, "WITHINGS" }, + { 0x1FB3, "Matchbeeper AB" }, + { 0x1FB4, "Owl Computing Technologies, Inc." }, + { 0x1FB5, "Unify Software and Solutions GmbH & Co. KG" }, + { 0x1FB6, "SheKel" }, + { 0x1FB7, "J & D Tech Co., Ltd." }, + { 0x1FB8, "DORMA TIME + ACCESS GmbH" }, + { 0x1FB9, "Lake Shore Cryotronics, Inc." }, + { 0x1FBA, "DERMALOG Identification Systems GmbH" }, + { 0x1FBB, "PC Worth Int'l Co., Ltd." }, + { 0x1FBC, "Kurzweil Education Systems, Inc." }, + { 0x1FBD, "STACK LTD." }, + { 0x1FBE, "CGS" }, + { 0x1FBF, "OVAL Corporation" }, + { 0x1FC0, "JUNE-ON Co., Ltd." }, + { 0x1FC1, "Blue Chip Technology Limited" }, + { 0x1FC2, "Poken SA" }, + { 0x1FC3, "ICOP Digital, Inc." }, + { 0x1FC4, "Alfons Haar Maschinenbau GmbH & Co. KG" }, + { 0x1FC5, "Adaxys Solutions AG" }, + { 0x1FC6, "LAUREL BANK MACHINES CO., LTD." }, + { 0x1FC7, "mrs GmbH" }, + { 0x1FC8, "Medis Technologies Ltd." }, + { 0x1FC9, "NXP Semiconductors" }, + { 0x1FCA, "ON TIM Technologies Ltd." }, + { 0x1FCB, "Thermo Process Instruments" }, + { 0x1FCC, "Hiro" }, + { 0x1FCD, "Aurora Scientific Inc." }, + { 0x1FCE, "WEBSCAN Inc." }, + { 0x1FCF, "ACK Co., Ltd." }, + { 0x1FD0, "GILSON S.A.S." }, + { 0x1FD1, "TEKWorx Limited" }, + { 0x1FD2, "LG Display Co., Ltd." }, + { 0x1FD3, "ASK SA" }, + { 0x1FD4, "FINSECUR" }, + { 0x1FD5, "Dream Multimedia GmbH" }, + { 0x1FD6, "Logitek Electronic Systems, Inc." }, + { 0x1FD7, "ASELSAN Elektronik Sanayi ve Ticaret. A.S." }, + { 0x1FD8, "Guangzhou Tianhe Changjiang Communication Industrial Co" }, + { 0x1FD9, "Knox Company" }, + { 0x1FDA, "Beckwith Electric Co., Inc." }, + { 0x1FDB, "Delphin Technology AG" }, + { 0x1FDC, "HOSA TECHNOLOGY, INC." }, + { 0x1FDD, "CHASE GLORY INDUSTRIAL LTD." }, + { 0x1FDE, "ILX Lightwave" }, + { 0x1FDF, "SEPURA PLC" }, + { 0x1FE0, "REALFLEET Co., Ltd." }, + { 0x1FE1, "Ubixum, Inc." }, + { 0x1FE2, "Aetas Systems Inc." }, + { 0x1FE3, "Amaranthine, LLC" }, + { 0x1FE4, "HANDY TECH ELEKTRONIK GmbH" }, + { 0x1FE5, "KUKA Roboter GmbH" }, + { 0x1FE6, "BOOKHAM INC." }, + { 0x1FE7, "VERTEX WIRELESS CO., LTD." }, + { 0x1FE8, "103mm Tech" }, + { 0x1FE9, "Harvard Bioscience" }, + { 0x1FEA, "SIMPLO TECHNOLOGY CO., LTD." }, + { 0x1FEB, "Tecella" }, + { 0x1FEC, "NIAN YEONG ENTERPRISE CO., LTD." }, + { 0x1FED, "SYSACOM R&D Plus Inc." }, + { 0x1FEE, "GALILEO ENGINEERING SRL" }, + { 0x1FEF, "RESOL - Elektronische Regelungen GmbH" }, + { 0x1FF0, "Kyoto Electronics Manufacturing Co., Ltd." }, + { 0x1FF1, "Remote Operations Solutions" }, + { 0x1FF2, "Carl Valentin GmbH" }, + { 0x1FF3, "SINTEF Energy Research" }, + { 0x1FF4, "HYUNDAI PETATEL INC." }, + { 0x1FF5, "Changzhou Wujin BEST Electronic Cables Co., Ltd." }, + { 0x1FF6, "ClickTech LLC" }, + { 0x1FF7, "Guangzhou Shi Rui Electronics Co., Ltd." }, + { 0x1FF8, "Infinite Memories" }, + { 0x1FF9, "Schulze Elektronik GmbH" }, + { 0x1FFA, "ARYGON Technologies AG" }, + { 0x1FFB, "Pololu Corporation" }, + { 0x1FFC, "Azimut Production Association JSC" }, + { 0x1FFD, "TESSERA, INC." }, + { 0x1FFE, "HOST ENGINEERING, INC." }, + { 0x1FFF, "Ideofy Inc." }, + { 0x2000, "RongTong Info & Tech Co., Ltd." }, + { 0x2001, "D-Link Corporation" }, + { 0x2002, "DAP Technologies Ltd." }, + { 0x2003, "detectomat GmbH" }, + { 0x2004, "Shanghai Bellmann Digital Source Co., Ltd." }, + { 0x2005, "Balluff GmbH" }, + { 0x2006, "Lenovo Mobile Communication Technology Ltd." }, + { 0x2007, "LEYIO" }, + { 0x2008, "ThingMagic, Inc." }, + { 0x2009, "MPEDIA" }, + { 0x200A, "ADVANCED RELAY CORP." }, + { 0x200B, "TRANSISTOR DEVICES INC." }, + { 0x200C, "HANPIN ELECTRON CO., LTD." }, + { 0x200D, "Belkin Electronic (Changzhou) Co., Ltd." }, + { 0x200E, "DAIICHI PARTS (HK) CO., LTD." }, + { 0x200F, "Progind Srl" }, + { 0x2010, "Tectonica Australia Pty. Ltd." }, + { 0x2011, "SHENZHEN HEXIN COM. TECH. CO., LTD." }, + { 0x2012, "Applied Radar, Inc." }, + { 0x2013, "PCTV Systems" }, + { 0x2014, "ONKEN CORPORATION" }, + { 0x2015, "Shenzhen Ephone Communication Technology Co., Ltd." }, + { 0x2016, "Norbit AS" }, + { 0x2017, "NAL Research Corporation" }, + { 0x2018, "SilverPAC, Inc." }, + { 0x2019, "Electronics Development Corp." }, + { 0x201A, "Vortran Laser Technology, Inc." }, + { 0x201B, "1064138 Ontario Ltd. O/A UNI-TEC ELECTRONICS" }, + { 0x201C, "Freeport Resources Enterprises Corp." }, + { 0x201D, "Dongguan Shunhui Electronic Co., Ltd." }, + { 0x201E, "Qingdao Haier Telecom Co., Ltd." }, + { 0x201F, "W.E.M. INC." }, + { 0x2020, "Shanghai BroadMobi Communication Technology Co., Ltd." }, + { 0x2021, "Smartd ltd" }, + { 0x2022, "AMICON Ltd." }, + { 0x2023, "Berthold Technologies GmbH & Co. KG" }, + { 0x2024, "Shoto Technologies LLC" }, + { 0x2025, "NANOSENSE" }, + { 0x2026, "EASUN REYROLLE LIMITED" }, + { 0x2027, "LOAD SYSTEMS INTERNATIONAL, INC." }, + { 0x2028, "DETAS TECHNOLOGY LTD." }, + { 0x2029, "MYTRAK HEALTH SYSTEM INC." }, + { 0x202A, "Fast Forward Video, Inc." }, + { 0x202B, "Damalini AB" }, + { 0x202C, "Enhanced Vision" }, + { 0x202D, "Snowbush IP (a division of Gennum)" }, + { 0x202E, "Lumio Inc." }, + { 0x202F, "US ARMY RDECOM-ARDEC" }, + { 0x2030, "VITEC Multimedia" }, + { 0x2031, "Vistec AG" }, + { 0x2032, "GFMesstechnik GmbH" }, + { 0x2033, "WYMA Tecnologia Ltda." }, + { 0x2034, "iSoft Silicon, Inc." }, + { 0x2035, "seowonintech" }, + { 0x2036, "Eitech Co., Ltd." }, + { 0x2037, "Control Devices Australia Pty., Ltd." }, + { 0x2038, "Wescor Inc." }, + { 0x2039, "SE-Elektronic GmbH" }, + { 0x203A, "Parallels, Inc." }, + { 0x203B, "EIT, Inc." }, + { 0x203C, "Steptechnica Co., Ltd." }, + { 0x203D, "Encore Electronics" }, + { 0x203E, "Pascher Instruments AB" }, + { 0x203F, "WPG System Pte. Ltd." }, + { 0x2040, "Hauppauge Computer Works, Inc." }, + { 0x2041, "WILL BEST (ELECTRONICS) LTD." }, + { 0x2042, "Eberspaecher Electronics GmbH & Co. KG" }, + { 0x2043, "Mobius Microsystems" }, + { 0x2044, "NOVUS PRODUTOS ELETRONICOS LTDA." }, + { 0x2045, "EMH - Energie-Messtechnik GmbH" }, + { 0x2046, "AbleNet Inc." }, + { 0x2047, "Texas Instruments Incorporated (MSP430 Group)" }, + { 0x2048, "Hongtech Electronics Co., Ltd." }, + { 0x2049, "APACEWAVE TECHNOLOGIES" }, + { 0x204A, "Enclustra GmbH" }, + { 0x204B, "HANSHIN INFORMATION TECHNOLOGY INC." }, + { 0x204C, "M7Lab., Co., Ltd." }, + { 0x204D, "Orthodyne Electronics" }, + { 0x204E, "LINO MANFROTTO + CO. S.P.A." }, + { 0x204F, "VIDEOTEC SpA" }, + { 0x2050, "CBF Systems, Inc." }, + { 0x2051, "N.A.T. GmbH" }, + { 0x2052, "Movidius Ltd." }, + { 0x2053, "HANSHIN TERMINAL CO., LTD." }, + { 0x2054, "Source R & D Inc. (DBA WARPIA)" }, + { 0x2055, "Opti B. I. Communications, Ltd." }, + { 0x2056, "CliniComp International Inc." }, + { 0x2057, "DICE ELECTRONICS, LLC" }, + { 0x2058, "NANO RIVER TECHNOLOGIES" }, + { 0x2059, "SMART Temps LLC" }, + { 0x205A, "Hankook Tire" }, + { 0x205B, "TRUMPF Medizin Systeme GmbH" }, + { 0x205C, "Shenzhen Tronixin Electronics Co., Ltd." }, + { 0x205D, "RESMED LTD." }, + { 0x205E, "CTI PRODUCTS, Inc." }, + { 0x205F, "Capella Microsystems Inc." }, + { 0x2060, "U.S. Army Aviation & Missile R & D & Engineering Center" }, + { 0x2061, "FIGMENT DESIGN LABORATORIES" }, + { 0x2062, "Trulife" }, + { 0x2063, "AirMagnet Inc." }, + { 0x2064, "Shenzhen AnNet Technology Co., Ltd." }, + { 0x2065, "MEASUREMENT SPECIALTIES INC." }, + { 0x2066, "Unicorn Electronics Components Co., Ltd." }, + { 0x2067, "TSB LAO COMPANY LIMITED" }, + { 0x2068, "Seven 45 Studios" }, + { 0x2069, "Vanguard Rugged Storage, LLC" }, + { 0x206A, "Fujian Star-net Communication Co., Ltd." }, + { 0x206B, "CETIM" }, + { 0x206C, "Seeker Technology Corp." }, + { 0x206D, "Hunan GreatWall Information Financial Equipment Co.Ltd." }, + { 0x206E, "ZAO MIRCOM" }, + { 0x206F, "JTOUCH Corporation" }, + { 0x2070, "Infinite Response, Inc." }, + { 0x2071, "SYSTEM S.P.A." }, + { 0x2072, "GOOD YEAR ELECTRONIC MFG. CO., LTD." }, + { 0x2073, "Shenzhen R-Way Technology Co., Ltd." }, + { 0x2074, "UNIVERSAL CHAMPION ELECTROACOUSTIC TECHNOLOGY COMPANY" }, + { 0x2075, "SecureKey Technologies Inc." }, + { 0x2076, "SHINKAWA Sensor Technology, Inc." }, + { 0x2077, "Shenzhen Gongjin Electronics Co., Ltd." }, + { 0x2078, "Epsilon Electronics, Inc dba Power Acoustik Electronics" }, + { 0x2079, "New Concept Gaming Ltd." }, + { 0x207A, "C.E.T.W.I.N System Solutions Sweden AB" }, + { 0x207B, "Technetix Group Ltd." }, + { 0x207C, "NESA International, Inc." }, + { 0x207D, "CESI Technology Co., Ltd." }, + { 0x207E, "ENHANCED VIDEO DEVICES, INC." }, + { 0x207F, "Profound BV" }, + { 0x2080, "Barnes and Noble" }, + { 0x2081, "UTRONIX Elektronikutreckling AB" }, + { 0x2082, "EKOMINI INC." }, + { 0x2083, "XEL SOLUTIONS LTD." }, + { 0x2084, "I Zone Technologies Co., Ltd." }, + { 0x2085, "SIXENSE ENTERTAINMENT INC." }, + { 0x2086, "SHENZHEN CATIC INFORMATION TECHNOLOGY INDUSTRY CO., LTD" }, + { 0x2087, "Cando Corporation" }, + { 0x2088, "WALTON CHAINTECH CORPORATION" }, + { 0x2089, "microdrones GmbH" }, + { 0x208A, "TECHNO ROAD Inc." }, + { 0x208B, "KONTRON EMBEDDED COMPUTERS GmbH" }, + { 0x208C, "Linkbit, Inc." }, + { 0x208D, "Attero Tech, LLC" }, + { 0x208E, "Luxshare-ICT" }, + { 0x208F, "Chi Mei Optoelectronics Corporation" }, + { 0x2090, "Transition Networks" }, + { 0x2091, "Callpod, Inc." }, + { 0x2092, "Logina" }, + { 0x2093, "Ambu A/S" }, + { 0x2094, "Yoostar Entertainment Group, Inc." }, + { 0x2095, "CE LINK LIMITED" }, + { 0x2096, "Shenzhen Microconn Investment and Development Co., Ltd." }, + { 0x2097, "USBPARTNER" }, + { 0x2098, "TouchTable, Inc." }, + { 0x2099, "Systematic Development Group, LLC" }, + { 0x209A, "Avedis Zildjian Company" }, + { 0x209B, "SATEL OY" }, + { 0x209C, "iPulse Systems" }, + { 0x209D, "Vector Co., Ltd." }, + { 0x209E, "GlideTV Inc." }, + { 0x209F, "Alcolizer Technology" }, + { 0x20A0, "Flirc" }, + { 0x20A1, "BRAINZSQUARE CO., LTD." }, + { 0x20A2, "SCANMATIK" }, + { 0x20A3, "Sterilucent" }, + { 0x20A4, "Itron Metering Solutions" }, + { 0x20A5, "Cardiorobotics, Inc." }, + { 0x20A6, "ZheJiang SEENSUN Communication&Electronic Equipment Co." }, + { 0x20A7, "GREAT LUSTRE (SPEEDY) CO., LTD." }, + { 0x20A8, "nLighten Technologies (Shanghai) Co., Ltd." }, + { 0x20A9, "Autotronic Controls Corp." }, + { 0x20AA, "ED-CONTRIVE Co., Ltd." }, + { 0x20AB, "Identification International, Inc." }, + { 0x20AC, "Wintek Corporation" }, + { 0x20AD, "Japan Probe Co., Ltd." }, + { 0x20AE, "SoCChip (Wuxi Youxin IC Design Co., Ltd.)" }, + { 0x20AF, "Shenzhen CARVE Electronics Co., Ltd." }, + { 0x20B0, "ICOMM TELE LIMITED" }, + { 0x20B1, "XMOS Ltd." }, + { 0x20B2, "Clubbhouse Inventions LLC" }, + { 0x20B3, "Hannstouch Solution Inc." }, + { 0x20B4, "SANDBRIDGE TECHNOLOGIES, INC." }, + { 0x20B5, "ACD Gruppe" }, + { 0x20B6, "Bohle AG" }, + { 0x20B7, "Qi Hardware, Inc." }, + { 0x20B8, "PARA INDUSTRIAL CO., LTD." }, + { 0x20B9, "TLAY Technologies Co., Ltd." }, + { 0x20BA, "jwin Electronics Corp." }, + { 0x20BB, "THALES TRANSPORTATION SYSTEMS" }, + { 0x20BC, "Guangzhou Pingzhong Electronic Technology Co., Ltd." }, + { 0x20BD, "KETEK" }, + { 0x20BE, "BURY GmbH & Co. KG" }, + { 0x20BF, "Dwyer Instruments, Inc." }, + { 0x20C0, "FENGHUA KINGSUN CO., LTD." }, + { 0x20C1, "HARWIN ASIA PTE. LTD." }, + { 0x20C2, "Sumitomo Electric Ind., Ltd., Optical Comm. R&D Lab" }, + { 0x20C3, "TECNOMOTOR ELETRONICA DO BRASIL S/A" }, + { 0x20C4, "Communications Laboratories, Inc. (Comlabs)" }, + { 0x20C5, "A.U. Physics Enterprises" }, + { 0x20C6, "Mutto Optronics Corporation" }, + { 0x20C7, "HMC INTERNATIONAL" }, + { 0x20C8, "CEC TELECOM CO., LTD." }, + { 0x20C9, "SYSTEMCORP Pty., Ltd." }, + { 0x20CA, "TRIPHOS Co., Ltd." }, + { 0x20CB, "Dave Smith Instruments" }, + { 0x20CC, "TAKARA" }, + { 0x20CD, "Schweers Informationstechnologie GmbH" }, + { 0x20CE, "Mini-Circuits" }, + { 0x20CF, "Gridmark Limited" }, + { 0x20D0, "FRESENIUS VIAL" }, + { 0x20D1, "Dascom Europe GmbH" }, + { 0x20D2, "ROBOTEQ INC." }, + { 0x20D3, "Provo Craft" }, + { 0x20D4, "SCDi" }, + { 0x20D5, "Lenexpo Inc. (dba: Atlona)" }, + { 0x20D6, "Bensussen Deutsch & Associates, Inc. (BDA)" }, + { 0x20D7, "SHENZHEN ZILI ELECTRONICS CO. LTD." }, + { 0x20D8, "Changzhou Xinchao Technologies, Inc." }, + { 0x20D9, "ZHEJIANG YONGCHENGGONG DIANSU.CO., LTD." }, + { 0x20DA, "LumaSense Technologies A/S" }, + { 0x20DB, "KTS GmbH" }, + { 0x20DC, "KCS Digital, Inc." }, + { 0x20DD, "FORTREND TAIWAN SCIENTIFIC CORP." }, + { 0x20DE, "OneSail HK Ltd." }, + { 0x20DF, "SIMTEC ELECTRONICS" }, + { 0x20E0, "Realway Electronics Technology Limited" }, + { 0x20E1, "Daiichi Co., Ltd." }, + { 0x20E2, "ASEQ INSTRUMENTS" }, + { 0x20E3, "LAUDA DR.R.WOBSER GMBH & CO. KG" }, + { 0x20E4, "Onecell Technologies" }, + { 0x20E5, "Cardreader, Inc." }, + { 0x20E6, "Brooks Automation, Inc." }, + { 0x20E7, "Scientific Digital Imaging plc" }, + { 0x20E8, "Jow Tong Technology Co., Ltd." }, + { 0x20E9, "adp Gauselmann GmbH" }, + { 0x20EA, "CACTUS TECHNOLOGIES, LIMITED" }, + { 0x20EB, "AOS Technologies AG" }, + { 0x20EC, "AMBIR TECHNOLOGY, INC." }, + { 0x20ED, "TRANZFINITY, INC." }, + { 0x20EE, "Emotiva Audio Corp." }, + { 0x20EF, "TIGRIS Elektronik GmbH" }, + { 0x20F0, "Insight Technology Incorporated" }, + { 0x20F1, "NET GmbH" }, + { 0x20F2, "Secured Mobility" }, + { 0x20F3, "Flexcore" }, + { 0x20F4, "TRENDnet" }, + { 0x20F5, "MKS Instruments - Technology for Productivity" }, + { 0x20F6, "EXMAN ELECTRIC" }, + { 0x20F7, "XIMEA s.r.o." }, + { 0x20F8, "Guangzhou Somic Digital & Electronic Technology Co, Ltd" }, + { 0x20F9, "Medical Computer Systems, Ltd." }, + { 0x20FA, "IC Intracom" }, + { 0x20FB, "Aptina Imaging Corporation" }, + { 0x20FC, "PIE SOFT LAB CORPORATION" }, + { 0x20FD, "NOVO NORDISK A/S" }, + { 0x20FE, "Bittium USA Inc." }, + { 0x20FF, "PNI Sensor Corp." }, + { 0x2100, "RT Systems Inc." }, + { 0x2101, "NAS Technologies Corp." }, + { 0x2102, "Vitalograph Ltd." }, + { 0x2103, "OHMORI ELECTRIC INDUSTRIES CO., LTD." }, + { 0x2104, "Tobii AB" }, + { 0x2105, "Retail Innovation HTT AB" }, + { 0x2106, "Sharp Korea Corporation" }, + { 0x2107, "Amstore CD Production Ltd." }, + { 0x2108, "NEATO ROBOTICS" }, + { 0x2109, "VIA Labs, Inc." }, + { 0x210A, "PULSUS TECHNOLOGIES" }, + { 0x210B, "Work Microwave GmbH" }, + { 0x210C, "DOT HILL SYSTEMS" }, + { 0x210D, "Plastoform Industries Ltd." }, + { 0x210E, "Commscope" }, + { 0x210F, "Tyco / Scott Health & Safety" }, + { 0x2110, "carina system co., ltd." }, + { 0x2111, "alphaNUCLEAR Inc." }, + { 0x2112, "Point Of Pay Pty. Ltd." }, + { 0x2113, "Softkinetic" }, + { 0x2114, "Innovision Technology Corporation Ltd." }, + { 0x2115, "Alliance Material Co., Ltd." }, + { 0x2116, "KT Tech Inc." }, + { 0x2117, "Frama AG" }, + { 0x2118, "RF WINDOW" }, + { 0x2119, "MoreDNA Technology Co., Ltd." }, + { 0x211A, "PILLKEY HOLDING BV" }, + { 0x211B, "MENTOR GmbH & Co. Praezisions-Bauteile KG" }, + { 0x211C, "SWENC Technology Co., Ltd." }, + { 0x211D, "Mutualink, Inc." }, + { 0x211E, "Dongbu HiTek" }, + { 0x211F, "XINETWORKS CO., LTD." }, + { 0x2120, "Odirrus Limited" }, + { 0x2121, "Escort Data Logging Systems Ltd." }, + { 0x2122, "ZEDEL" }, + { 0x2123, "SYNTEK DEVELOPMENT LTD." }, + { 0x2124, "ELSAGDATAMAT S.P.A." }, + { 0x2125, "FIBERPRO INC." }, + { 0x2126, "SUZA INTERNATIONAL FRANCE" }, + { 0x2127, "FutureDial, Inc." }, + { 0x2128, "Naval Research Laboratory" }, + { 0x2129, "Tokushu Denshi Kairo, Inc." }, + { 0x212A, "Kappa optronics GmbH" }, + { 0x212B, "GR Telecom Co., Ltd." }, + { 0x212C, "Shenzhen Linoya Electronic Co., Ltd." }, + { 0x212D, "Dong Guan City Wanhong Electric Co., Ltd." }, + { 0x212E, "Amphenol AssembleTech (Xiamen) Co., Ltd." }, + { 0x212F, "SUZUKI MUSICAL INST. MFG. CO., LTD." }, + { 0x2130, "Sanmu Communication Technology (H.K.) Ltd." }, + { 0x2131, "IES Co., Ltd." }, + { 0x2132, "EDAS, Inc." }, + { 0x2133, "SIGNOTEC GmbH" }, + { 0x2134, "CANESTA, INC." }, + { 0x2135, "W.O.M. World of Medicine AG" }, + { 0x2136, "Compunow Trading Corp." }, + { 0x2137, "Beyonics Technology Limited" }, + { 0x2138, "iVina, Inc." }, + { 0x2139, "Eigenlabs Ltd." }, + { 0x213A, "Carlo Gavazzi" }, + { 0x213B, "UICO, Inc." }, + { 0x213C, "ICON Health & Fitness" }, + { 0x213D, "DRS Data & Imaging Systems, Inc." }, + { 0x213E, "Phase Matrix, Inc." }, + { 0x213F, "Digitron Instrumentation Ltd." }, + { 0x2140, "Sichuan Jiuzhou Electric Group Co., Ltd." }, + { 0x2141, "ZT Group Int'l, Inc." }, + { 0x2142, "Enginuity Communications" }, + { 0x2143, "InDevR Inc." }, + { 0x2144, "Sea Tel, Inc." }, + { 0x2145, "Ballard Technology" }, + { 0x2146, "Victorinox AG" }, + { 0x2147, "Chin-Ban Electronics (Hong Kong) Co., Ltd." }, + { 0x2148, "Visteon Sistemas Automotives Ltda." }, + { 0x2149, "MasTouch Optoelectronics Technologies Co., Ltd." }, + { 0x214A, "Interlink Electronics" }, + { 0x214B, "AMECO TECHNOLOGIES (SHENZHEN) CO., LTD." }, + { 0x214C, "Y Soft Corporation" }, + { 0x214D, "SyTech Corporation" }, + { 0x214E, "Swiftpoint Limited" }, + { 0x214F, "Attainment Company, Inc." }, + { 0x2150, "AZOTEQ (PTY) LTD." }, + { 0x2151, "SeaSpace Corporation" }, + { 0x2152, "AD Semiconductor Co., Ltd." }, + { 0x2153, "Mastertouch Solutions Electronics Co., Ltd." }, + { 0x2154, "Trace Lighting Ltd." }, + { 0x2155, "Teledyne Controls" }, + { 0x2156, "Weistech Technology Co., Ltd." }, + { 0x2157, "Digital Imaging Technology" }, + { 0x2158, "TA WEI TECHNOLOGY CO., LTD." }, + { 0x2159, "TRIASX Pty Ltd." }, + { 0x215A, "Sling Media, Inc." }, + { 0x215B, "2D Debus & Diebold Messsysteme GmbH" }, + { 0x215C, "OTOVATION, LLC" }, + { 0x215D, "GeNUA mbH" }, + { 0x215E, "ST Embedded Engineering, LLC" }, + { 0x215F, "DECIMATOR DESIGN PTY LTD." }, + { 0x2160, "PULOON Technology Inc." }, + { 0x2161, "BEA SA" }, + { 0x2162, "Prime Audio Inc." }, + { 0x2163, "Digital Rapids Corp." }, + { 0x2164, "Witek System" }, + { 0x2165, "CONTROL SOLUTIONS, INC." }, + { 0x2166, "JVC KENWOOD Corporation" }, + { 0x2167, "Zhejiang Fousine Science & Technology Co., Ltd." }, + { 0x2168, "TZYR HWEY ENTERPRISE CO., LTD." }, + { 0x2169, "TIANJIN SHENNAN INFORMATION SECURITY CO., LTD." }, + { 0x216A, "Shenzhen San Jing Electronics Co., Ltd." }, + { 0x216B, "XceedID Corporation" }, + { 0x216C, "UniDisplay Inc." }, + { 0x216D, "BENSON MEDICAL INSTRUMENTS" }, + { 0x216E, "KHOMP INDUSTRIA E COMERCIO LTDA" }, + { 0x216F, "ALTAIR SEMICONDUCTOR" }, + { 0x2170, "Wurtec, Inc." }, + { 0x2171, "Bokam Engineering, Inc." }, + { 0x2172, "Torrey Pines Logic, Inc." }, + { 0x2173, "HUIZHOU HUANGJI PRECISIONS FLEX ELECTRONICAL CO., LTD." }, + { 0x2174, "Transcend Information, Inc." }, + { 0x2175, "Light Blue Optics, Inc." }, + { 0x2176, "TMC - Allion Test Labs" }, + { 0x2177, "CHAUVIN ARNOUX" }, + { 0x2178, "Ion Science" }, + { 0x2179, "UGtizer Corp." }, + { 0x217A, "Triple Eye" }, + { 0x217B, "BDP Semiconductors Ltd." }, + { 0x217C, "Sensitech Inc." }, + { 0x217D, "Bilcare Technologies Singapore Pte. Ltd." }, + { 0x217E, "TP RADIO" }, + { 0x217F, "REAL EAR A/S" }, + { 0x2180, "Icare Finland Oy" }, + { 0x2181, "GLOBAL TRAFFIC TECHNOLOGIES, LLC" }, + { 0x2182, "XAC Automation Corp." }, + { 0x2183, "Bonutti Research" }, + { 0x2184, "GOOD WILL Instrument Co., Ltd." }, + { 0x2185, "FUJIWORK Co., Ltd." }, + { 0x2186, "Home Server Technologies Inc." }, + { 0x2187, "ESPACE SERVICES MULTIMEDIAS" }, + { 0x2188, "CalDigit, Inc." }, + { 0x2189, "SEMNTECH" }, + { 0x218A, "EXELYS LLC" }, + { 0x218B, "Blackbird Technologies Inc." }, + { 0x218C, "Gammadata Instrument AB" }, + { 0x218D, "Adaptive I/O Technologies, Inc." }, + { 0x218E, "UNITRO-Fleischmann" }, + { 0x218F, "DHEF INC." }, + { 0x2190, "esonic Co., Ltd." }, + { 0x2191, "SecureAT Co., Ltd." }, + { 0x2192, "FlexRadio Systems" }, + { 0x2193, "Schnick-Schnack-Systems GmbH" }, + { 0x2194, "ROTH + WEBER GmbH" }, + { 0x2195, "Hans Eckes Hardware & Software" }, + { 0x2196, "XPMOBILE" }, + { 0x2197, "W & D, LLC" }, + { 0x2198, "Wonde Proud Technology Co., Ltd." }, + { 0x2199, "Image and Information Technology" }, + { 0x219A, "COSMO ELECTRONICS CO., LTD." }, + { 0x219B, "TPK Touch Solutions Inc." }, + { 0x219C, "SEAL ONE AG" }, + { 0x219D, "BDR Technologies Ltd." }, + { 0x219E, "VALKEE OY" }, + { 0x219F, "VENTIS" }, + { 0x21A0, "AXELSPACE Corporation" }, + { 0x21A1, "EMOTIV SYSTEMS INC." }, + { 0x21A2, "ABB Low Voltage Products" }, + { 0x21A3, "Optcom Co., Ltd." }, + { 0x21A4, "ELECTRONIC ARTS" }, + { 0x21A5, "Genesis Technology USA, Inc." }, + { 0x21A6, "YUPITERU CORPORATION" }, + { 0x21A7, "PAYPRINT SRL" }, + { 0x21A8, "GE Intelligent Platforms, Inc." }, + { 0x21A9, "Saleae LLC" }, + { 0x21AA, "TAKASAKI KYODO COMPUTING CENTER CO., LTD." }, + { 0x21AB, "Planeta Informatica Ltda." }, + { 0x21AC, "infoSense Technology Inc." }, + { 0x21AD, "Wobbegong Fitness and Therapy Products Pty. Ltd." }, + { 0x21AE, "Philips and Neusoft Medical System Co., Ltd." }, + { 0x21AF, "Euro-CB Phils. Inc." }, + { 0x21B0, "Grace Industries, Incorporated" }, + { 0x21B1, "TATA CONSULTANCY SERVICES" }, + { 0x21B2, "Felix Meier GmbH" }, + { 0x21B3, "Dongguan Teconn Electronics Technology Co., Ltd." }, + { 0x21B4, "Wavelength Audio, Ltd." }, + { 0x21B5, "SHENZHEN JASON ELECTRONICS CO., LTD." }, + { 0x21B6, "EUROAVIONICS GmbH & Co. KG" }, + { 0x21B7, "STAIB INSTRUMENTE GmbH" }, + { 0x21B8, "KONTRONIK GmbH" }, + { 0x21B9, "ZP ENGINEERING s.r.l." }, + { 0x21BA, "SI2 MICROSYSTEMS, Ltd." }, + { 0x21BB, "WWPass Corporation" }, + { 0x21BC, "Skyhawke Technologies, LLC" }, + { 0x21BD, "Code Red Technologies, Ltd." }, + { 0x21BE, "KEC Co., Ltd." }, + { 0x21BF, "Mayo Clinic" }, + { 0x21C0, "PIXTREE, Inc." }, + { 0x21C1, "Baumann Electronic Controls, LLC" }, + { 0x21C2, "Shenzhen V-Interface Technology Co., Ltd." }, + { 0x21C3, "MASIMO LABORATORIES INC." }, + { 0x21C4, "Longsys Electronics (HK) Co., Ltd." }, + { 0x21C5, "Vukic Computer Instruments GmbH" }, + { 0x21C6, "PSS Hong Kong Limited" }, + { 0x21C7, "Unisoku Co., Ltd." }, + { 0x21C8, "IDONDEMAND INC." }, + { 0x21C9, "Innoteletek, Inc." }, + { 0x21CA, "RAE Systems Inc." }, + { 0x21CB, "Vodafone Ltd." }, + { 0x21CC, "ChipsWork Microelectronics Corp." }, + { 0x21CD, "Infoxelle Co., Ltd." }, + { 0x21CE, "Polostar Technology Corporation" }, + { 0x21CF, "HISATOMI ELECTRIC IND. CO., LTD." }, + { 0x21D0, "Red Rapids" }, + { 0x21D1, "ADDER TECHNOLOGY LTD." }, + { 0x21D2, "NeoLAB Convergence" }, + { 0x21D3, "Compupack Technology Co., Ltd." }, + { 0x21D4, "Eduplayer Co., Ltd." }, + { 0x21D5, "M.G.F." }, + { 0x21D6, "Agecodagis SARL" }, + { 0x21D7, "VINCIAMO, Inc." }, + { 0x21D8, "P & A Technologies, Inc." }, + { 0x21D9, "Verification Technology, Inc." }, + { 0x21DA, "Valor Auto Companion, Inc." }, + { 0x21DB, "G-Max Technology Co., Ltd." }, + { 0x21DC, "ABB S.p.A., Low Voltage Products Division" }, + { 0x21DD, "Looxcie, Inc." }, + { 0x21DE, "Cloud Engines, Inc." }, + { 0x21DF, "Quanser Consulting Inc." }, + { 0x21E0, "OpenPattern" }, + { 0x21E1, "CAEN S.P.A." }, + { 0x21E2, "Ascension Technology Corp." }, + { 0x21E3, "Crest Technology Inc." }, + { 0x21E4, "Xcellen Co., Ltd." }, + { 0x21E5, "Kruglov Evgeniy Vladimirovich" }, + { 0x21E6, "OCZ Technology Group" }, + { 0x21E7, "Sagemcom Broadband SAS" }, + { 0x21E8, "BOEHNKE + PARTNER GmbH Steuerungssysteme" }, + { 0x21E9, "Jiafuh Metal & Plastic (ShenZhen) Co., Ltd." }, + { 0x21EA, "JUST MAKE ELECTRONICS CO., LTD." }, + { 0x21EB, "KOKORO CO., LTD." }, + { 0x21EC, "ApniCure, Inc." }, + { 0x21ED, "Accuphase Laboratories, Inc." }, + { 0x21EE, "MAVIN TECHNOLOGY INC." }, + { 0x21EF, "FEMTO Messtechnik GmbH" }, + { 0x21F0, "LivingLab Development Co., Ltd." }, + { 0x21F1, "ABS Group AB" }, + { 0x21F2, "Palmer Environmental Ltd." }, + { 0x21F3, "Inspired Instruments Inc." }, + { 0x21F4, "Minebea Technologies Taiwan Co., Ltd." }, + { 0x21F5, "Shenzhen Strong Rising Electronics Co., Ltd." }, + { 0x21F6, "QSR Automations, Inc." }, + { 0x21F7, "Wuerth-Elektronik eiSos GmbH & Co. KG" }, + { 0x21F8, "Goeasily Int'l Co., Ltd." }, + { 0x21F9, "American Thermal Instruments" }, + { 0x21FA, "Pitsco, Inc." }, + { 0x21FB, "HELIOS Electronic Design & Manufacture" }, + { 0x21FC, "Thum + Mahr GmbH" }, + { 0x21FD, "Associated Controls (Australia) Pty., Limited" }, + { 0x21FE, "ELAP S.p.A." }, + { 0x21FF, "DEIF A/S" }, + { 0x2200, "Nuribom" }, + { 0x2201, "Elan Digital Systems Ltd." }, + { 0x2202, "Walex Electronic (Wu Xi) Co., Ltd." }, + { 0x2203, "Shin Shin Co., Ltd." }, + { 0x2204, "Innov-X Systems Inc." }, + { 0x2205, "3eYamaichi Electronics Co., Ltd." }, + { 0x2206, "Wiretek International Investment Ltd." }, + { 0x2207, "Fuzhou Rockchip Electronics Co., Ltd." }, + { 0x2208, "CONNFLY ELECTRONIC CO., LTD." }, + { 0x2209, "SPoT LLC" }, + { 0x220A, "Anton Paar GmbH" }, + { 0x220B, "IKARIA Holdings, Inc." }, + { 0x220C, "Island Technology Co., Ltd." }, + { 0x220D, "Humanline Co., Ltd." }, + { 0x220E, "NetComm Ltd." }, + { 0x220F, "Italdata Ingegneria Dell'Idea s.p.a." }, + { 0x2210, "Klavis Technologies" }, + { 0x2211, "FLUID COMPONENTS INTERNATIONAL LLC" }, + { 0x2212, "Dev-Audio Pty. Ltd. (Dev-Audio)" }, + { 0x2213, "Ascon Co., Ltd." }, + { 0x2214, "Pollin Electronic GmbH" }, + { 0x2215, "InCOMM Technologies Co., Ltd." }, + { 0x2216, "Environmental Systems Corporation" }, + { 0x2217, "FTS Forest Technology Systems Ltd." }, + { 0x2218, "Listen Technologies Corp." }, + { 0x2219, "Hogahm Technology" }, + { 0x221A, "ZTEX" }, + { 0x221B, "Kyodo Denshi Engineering Co., Ltd." }, + { 0x221C, "CORTEX TECHNOLOGY APS" }, + { 0x221D, "fischertechnik GmbH" }, + { 0x221E, "Linktec Technologies Co., Ltd." }, + { 0x221F, "Resolution Audio" }, + { 0x2220, "FAMAS SYSTEM S.P.A." }, + { 0x2221, "EnovateIT Inc." }, + { 0x2222, "SOFTMECHA" }, + { 0x2223, "Ratioplast-Optoelectronics GmbH" }, + { 0x2224, "LM Technologies Ltd." }, + { 0x2225, "GETT Geratetechnik GmbH" }, + { 0x2226, "PLANAR LLC" }, + { 0x2227, "Northtronics Pty., Ltd." }, + { 0x2228, "Dantec Dynamics A/S" }, + { 0x2229, "Key Technologies, Inc." }, + { 0x222A, "ILI TECHNOLOGY CORP." }, + { 0x222B, "ALPHAMEDIA CO., LTD." }, + { 0x222C, "TOHAN DENSHI KIKI Co., Ltd." }, + { 0x222D, "LEIFHEIT AG" }, + { 0x222E, "OXYSEC s.r.l." }, + { 0x222F, "Tcom Technology Co., Ltd." }, + { 0x2230, "Plugable Technologies" }, + { 0x2231, "Coregate Inc." }, + { 0x2232, "NAMUGA Co., Ltd." }, + { 0x2233, "ARGtek Communication Inc." }, + { 0x2234, "T-CONN PRECISION CORPORATION" }, + { 0x2235, "WoundVision" }, + { 0x2236, "ACELLA" }, + { 0x2237, "Kobo Inc." }, + { 0x2238, "ELMO Motion Control Ltd." }, + { 0x2239, "PEIKER acustic GmbH & Co., KG" }, + { 0x223A, "BKtel Communications GmbH" }, + { 0x223B, "Crystalfontz America, Inc." }, + { 0x223C, "Audio Research Corp." }, + { 0x223D, "AlfaPlus Semiconductor, Inc." }, + { 0x223E, "Home Electronics" }, + { 0x223F, "Oga, Inc." }, + { 0x2240, "NETTALK.COM INC." }, + { 0x2241, "Envision Interface Engineering, LLC" }, + { 0x2242, "Zhihe Electronics Technology Co., Ltd." }, + { 0x2243, "EMIC CORPORATION" }, + { 0x2244, "Kronos" }, + { 0x2245, "ASPEED Technology Inc." }, + { 0x2246, "Nanjing Frentec Co., Ltd." }, + { 0x2247, "CHUNGHWA PICTURE TUBES, LTD." }, + { 0x2248, "KAISE CORPORATION" }, + { 0x2249, "Long Range Systems, Inc." }, + { 0x224A, "ORMEC SYSTEMS CORP." }, + { 0x224B, "Sirit Inc." }, + { 0x224C, "Datron World Communications, Inc." }, + { 0x224D, "Tescom Co., Ltd." }, + { 0x224E, "RDH2 Science" }, + { 0x224F, "APDM, INC." }, + { 0x2250, "Evernew Wire & Cable Co., Ltd." }, + { 0x2251, "QuieTek Corp." }, + { 0x2252, "TSANSUN TECH. CO., LTD." }, + { 0x2253, "Arpage AG" }, + { 0x2254, "RPO" }, + { 0x2255, "COOPER WIRELESS" }, + { 0x2256, "Mathias Fuchss Software - Entwicklung" }, + { 0x2257, "On the Go Video, Inc." }, + { 0x2258, "D+H Mechatronic AG" }, + { 0x2259, "Skypine Electronics (Shenzhen) Co., Ltd." }, + { 0x225A, "Vivanco GmbH" }, + { 0x225B, "Lineage Power" }, + { 0x225C, "Digital Check Corp" }, + { 0x225D, "Sagem Securite" }, + { 0x225E, "Unholtz-Dickie Corp." }, + { 0x225F, "Ace Karaoke Corp." }, + { 0x2260, "Multigig, Inc." }, + { 0x2261, "DOM-Sicherheitstechnik GmbH & Co. KG" }, + { 0x2262, "VIETTEL GROUP" }, + { 0x2263, "Nuovations" }, + { 0x2264, "Entourage Systems, Inc." }, + { 0x2265, "DailyCare BioMedical Inc." }, + { 0x2266, "Psychology Software Tools, Inc." }, + { 0x2267, "Boreal Genomics" }, + { 0x2268, "EXSUSS, Inc." }, + { 0x2269, "Schlumberger Ltd." }, + { 0x226A, "Ooma, Inc." }, + { 0x226B, "Bruker Nano GmbH" }, + { 0x226C, "HAL Communications Corp." }, + { 0x226D, "Wrenchman, Inc." }, + { 0x226E, "DISPLAX" }, + { 0x226F, "Koyo Trading Co., Ltd." }, + { 0x2270, "XiaMen GaoLuChang Electronics Co. Ltd." }, + { 0x2271, "Karl Storz GmbH & Co. KG" }, + { 0x2272, "E.E.P.D." }, + { 0x2273, "IMAX Corporation" }, + { 0x2274, "Morgan Schaffer Inc." }, + { 0x2275, "ReliOn Inc." }, + { 0x2276, "Pioneer CBC" }, + { 0x2277, "Ortho Neuro Technologies, Inc." }, + { 0x2278, "Infratec Datentechnik GmbH" }, + { 0x2279, "Goossens Engineering" }, + { 0x227A, "FLOM Corporation" }, + { 0x227B, "CYBELEC SA" }, + { 0x227C, "S. & A.S. LTD." }, + { 0x227D, "Unitec Co., Ltd." }, + { 0x227E, "JSC " }, + { 0x227F, "Granite River Labs" }, + { 0x2280, "Life Technologies Corp." }, + { 0x2281, "GI CORPORATION" }, + { 0x2282, "Mamiya Digital Imaging Co., Ltd." }, + { 0x2283, "NIHON DEMPA KOGYO Co., Ltd." }, + { 0x2284, "SuperSonic Inc." }, + { 0x2285, "IRIS ID" }, + { 0x2286, "Altierre Corporation" }, + { 0x2287, "Shenzhen Oversea Win Technology Co., Ltd." }, + { 0x2288, "Dt&C (Digital Technology and Certification)" }, + { 0x2289, "Sun Fair Electric Wire & Cable (HK) Co., Ltd." }, + { 0x228A, "Hotron Precision Electronic Ind. Corp." }, + { 0x228B, "Shenzhen DLK Electronics Technology Co., Ltd." }, + { 0x228C, "Analogic Corporation" }, + { 0x228D, "8D TECHNOLOGIES INC." }, + { 0x228E, "EKO Instruments Co., Ltd." }, + { 0x228F, "SIGMATEK GmbH & Co. KG" }, + { 0x2290, "Touchplus information Corp." }, + { 0x2291, "Vallen Systeme GmbH" }, + { 0x2292, "Global Industrial Services, Ltd." }, + { 0x2293, "Berger Elektronik GmbH" }, + { 0x2294, "KoCo Connector AG" }, + { 0x2295, "Sound ID" }, + { 0x2296, "Musashi Engineering Company Limited" }, + { 0x2297, "Grain Media, Inc." }, + { 0x2298, "PULSION Medical Systems AG" }, + { 0x2299, "BRAIN VISION SYSTEMS (BVS)" }, + { 0x229A, "Control Express Finland OY" }, + { 0x229B, "SFC Smart Fuel Cell AG" }, + { 0x229C, "Raytheon Company" }, + { 0x229D, "Solacia Inc." }, + { 0x229E, "JV2R - MacWay" }, + { 0x229F, "RRC power solutions GmbH" }, + { 0x22A0, "Winpos System Co., Ltd." }, + { 0x22A1, "Shenzhen Jiuzhou Electric Co., Ltd." }, + { 0x22A2, "Disruptive Ltd." }, + { 0x22A3, "DexCom" }, + { 0x22A4, "InnoComm Mobile Technology Corp." }, + { 0x22A5, "Yu Jeong System Co., Ltd." }, + { 0x22A6, "Pie Digital, Inc." }, + { 0x22A7, "Fortinet, Inc." }, + { 0x22A8, "OTTO" }, + { 0x22A9, "Valor Communication, Inc." }, + { 0x22AA, "AppliedMicro" }, + { 0x22AB, "Trigence Semiconductor, Inc." }, + { 0x22AC, "Sensor Switch, Inc." }, + { 0x22AD, "DCP Microdevelopments Limited" }, + { 0x22AE, "Buerkert Werke GmbH" }, + { 0x22AF, "JW Fishers Mfg." }, + { 0x22B0, "Business Security OL AB" }, + { 0x22B1, "Secret Labs LLC" }, + { 0x22B2, "EDGE Tech Corp." }, + { 0x22B3, "SOMFY" }, + { 0x22B4, "NIPPON ANTENNA Co., Ltd." }, + { 0x22B5, "Thyracont Vacuum Instruments GmbH" }, + { 0x22B6, "IMTRADEX Hoer-/Sprechsysteme GmbH" }, + { 0x22B7, "Unjo AB" }, + { 0x22B8, "Motorola Mobility Inc." }, + { 0x22B9, "eTurboTouch Technology Inc." }, + { 0x22BA, "Technology Innovation Holdings Ltd." }, + { 0x22BB, "Saris Cycling Group" }, + { 0x22BC, "OPWILL Technologies (Beijing) Co., Ltd." }, + { 0x22BD, "Basis Software, Inc." }, + { 0x22BE, "Cheetah-Medical Ltd." }, + { 0x22BF, "Bit Cauldron Corporation" }, + { 0x22C0, "ReLia Diagnostic Systems, Inc." }, + { 0x22C1, "ATEK Products, LLC" }, + { 0x22C2, "Fast And Safe Technology Co., Ltd." }, + { 0x22C3, "Tsinghua Tongfang Co., Ltd." }, + { 0x22C4, "Fresenius Medical Care Deutschland GmbH" }, + { 0x22C5, "Himax Technologies, Inc." }, + { 0x22C6, "Baker Hughes Production Quest" }, + { 0x22C7, "MEMUP" }, + { 0x22C8, "Shenzhen Xinerchang Electronics Co., Ltd." }, + { 0x22C9, "StepOver GmbH" }, + { 0x22CA, "Amimon Ltd." }, + { 0x22CB, "Forware Spain S.L." }, + { 0x22CC, "LAONEX CO., LTD." }, + { 0x22CD, "Kinova" }, + { 0x22CE, "Metters Industries" }, + { 0x22CF, "Marquess Co., Limited" }, + { 0x22D0, "Norsonic AS" }, + { 0x22D1, "ZeitControl GmbH" }, + { 0x22D2, "ZETT OPTICS GmbH" }, + { 0x22D3, "FAAC SpA" }, + { 0x22D4, "Laview Technology Ltd." }, + { 0x22D5, "Yellow Soft Co., Ltd." }, + { 0x22D6, "Numatic International Ltd." }, + { 0x22D7, "IntelliTech International, Inc." }, + { 0x22D8, "Shantery Co., Ltd." }, + { 0x22D9, "GuangDong OPPO Mobile Telecommunications Corp., Ltd." }, + { 0x22DA, "TXTR GmbH" }, + { 0x22DB, "Phase One A/S" }, + { 0x22DC, "TILERA CORPORATION" }, + { 0x22DD, "Kawasaki Heavy Industries, Ltd." }, + { 0x22DE, "WeTelecom" }, + { 0x22DF, "Medicom-MTD" }, + { 0x22E0, "Secunet Security Networks AG" }, + { 0x22E1, "TempoTec Corp" }, + { 0x22E2, "IDEA!" }, + { 0x22E3, "Escort, Inc." }, + { 0x22E4, "Shenyang Tongzhen Precision Electronic Technology Co." }, + { 0x22E5, "Mine Safety Appliances Co." }, + { 0x22E6, "Labo America, Inc." }, + { 0x22E7, "ZAFFER BVBA" }, + { 0x22E8, "Audio Partnership" }, + { 0x22E9, "Orion Diagnostica OY" }, + { 0x22EA, "Bit Trade One, Ltd." }, + { 0x22EB, "Vizimax Inc." }, + { 0x22EC, "Kozio, Inc." }, + { 0x22ED, "HannStar Display Corp." }, + { 0x22EE, "Struers A/S" }, + { 0x22EF, "Edutor Technologies India Private Limited" }, + { 0x22F0, "Allen + Heath Ltd." }, + { 0x22F1, "DATEQ BV" }, + { 0x22F2, "Quest Payment Systems" }, + { 0x22F3, "Zephyr Technology Corporation" }, + { 0x22F4, "Olive Global Holding Pvt. Ltd." }, + { 0x22F5, "oTHE Technology Inc." }, + { 0x22F6, "Clear Pulse Co., Ltd." }, + { 0x22F7, "Drivven, Inc." }, + { 0x22F8, "Universal Sats Ltd." }, + { 0x22F9, "Compass, s.r.l." }, + { 0x22FA, "Sifteo Inc." }, + { 0x22FB, "Beijing Chiplight IC Design Co., Ltd." }, + { 0x22FC, "ModusLink Global Solutions, Inc." }, + { 0x22FD, "Miltope Corp." }, + { 0x22FE, "Protium Technologies, Inc." }, + { 0x22FF, "Avnet" }, + { 0x2300, "Nanjing Magon Opto-Electrical Science & Technology Co." }, + { 0x2301, "Imaginant Inc." }, + { 0x2302, "Rafael Advanced Defense Systems Ltd." }, + { 0x2303, "Grosvenor Technology Ltd." }, + { 0x2304, "Pinnacle" }, + { 0x2305, "Lindemann Audiotechnik GmbH" }, + { 0x2306, "Syba Multimedia, Inc." }, + { 0x2307, "Madboy Audio International Oy" }, + { 0x2308, "UV Networks, Inc." }, + { 0x2309, "TimeLink Inc." }, + { 0x230A, "Data Locker Inc." }, + { 0x230B, "Shanda Interactive Entertainment Limited" }, + { 0x230C, "GarTech Enterprises, Inc." }, + { 0x230D, "Linktop Technology Co., Ltd." }, + { 0x230E, "eDAQ Pty., Ltd." }, + { 0x230F, "applause.elfmimi.jp" }, + { 0x2310, "WCE, Inc." }, + { 0x2311, "Francotyp-Postalia GmbH" }, + { 0x2312, "Learning Curve Brands, Inc." }, + { 0x2313, "Kunshan Jiahua Electronics Co., Ltd." }, + { 0x2314, "INQ Mobile Limited" }, + { 0x2315, "Avery Design Systems, Inc." }, + { 0x2316, "DongGuan Potec Electric Industrial Co., Ltd." }, + { 0x2317, "Huawei Device Co., Ltd." }, + { 0x2318, "Solar Components LLC" }, + { 0x2319, "Loewe Opta GmbH" }, + { 0x231A, "SANWA KAGAKU KENKYUSHO CO., LTD." }, + { 0x231B, "winner story Co., Ltd." }, + { 0x231C, "SONUUS LIMITED" }, + { 0x231D, "Fervian Technologies Limited" }, + { 0x231E, "Chongqing CYIT Communication Technologies Co., Ltd." }, + { 0x231F, "FandF Co., Ltd." }, + { 0x2320, "Redring AB" }, + { 0x2321, "iKingdom Corp. (d.b.a. iConnectivity)" }, + { 0x2322, "RichWave Technology Corp." }, + { 0x2323, "EFI TECHNOLOGY s.r.l." }, + { 0x2324, "Ubisense Limited" }, + { 0x2325, "Simbex" }, + { 0x2326, "CKM Electronics Co., Ltd." }, + { 0x2327, "DreamSecurity" }, + { 0x2328, "Radio Systems Corporation" }, + { 0x2329, "Infinite Technologies JLT" }, + { 0x232A, "Skalar Analytical b.v." }, + { 0x232B, "Zhuhai Pantum Technology Co., Ltd." }, + { 0x232C, "Digital Lumens" }, + { 0x232D, "Edinburgh Instruments Ltd." }, + { 0x232E, "EA, Elektro-Automatik GmbH & Co. KG" }, + { 0x232F, "Motic China Group Co., Ltd." }, + { 0x2330, "Tensorcom, Inc." }, + { 0x2331, "PUZZLE LOGIC INC." }, + { 0x2332, "Coges S.p.A." }, + { 0x2333, "Zamzee Co." }, + { 0x2334, "Opticos srl" }, + { 0x2335, "Personable Inc." }, + { 0x2336, "Vix Technology (Aust) Ltd." }, + { 0x2337, "linked IP GmbH" }, + { 0x2338, "RedE Innovations" }, + { 0x2339, "Sierra Nevada Corporation" }, + { 0x233A, "Telpar" }, + { 0x233B, "taberna pro medicum GmbH" }, + { 0x233C, "Julabo" }, + { 0x233D, "Microtech System" }, + { 0x233E, "Aastra Telecom Inc." }, + { 0x233F, "Stage Tec GmbH" }, + { 0x2340, "Teleepoch Limited" }, + { 0x2341, "Arduino, LLC" }, + { 0x2342, "nextEDGE Technology, K.K." }, + { 0x2343, "AquaScan A/S" }, + { 0x2344, "HAMBURG INDUSTRIES CO., LTD." }, + { 0x2345, "ZOWIE GEAR" }, + { 0x2346, "Data Transfer & Communications Ltd." }, + { 0x2347, "iControl Networks" }, + { 0x2348, "Ubisys Technology" }, + { 0x2349, "P2 Engineering Group, LLC" }, + { 0x234A, "Cypress Technology Co., Ltd." }, + { 0x234B, "Free Software Initiative of Japan" }, + { 0x234C, "Zenverge Inc." }, + { 0x234D, "Skype Inc." }, + { 0x234E, "Anewin" }, + { 0x234F, "VaniOs Consulting" }, + { 0x2350, "ZiiLABS Pte. Ltd." }, + { 0x2351, "EmbCodeAB" }, + { 0x2352, "SKYTEX Technology Inc." }, + { 0x2353, "PHiON Technology Inc." }, + { 0x2354, "BirdBrain Technologies LLC" }, + { 0x2355, "Pacific Northwest National Laboratory (PNNL)" }, + { 0x2356, "Grid Connect Inc." }, + { 0x2357, "TP-LINK Technologies Co., Ltd." }, + { 0x2358, "Greenconn Corporation" }, + { 0x2359, "Shenzhen Autone-Tronic Technology Co., Ltd." }, + { 0x235A, "Top Yang Technology Enterprise Co., Ltd." }, + { 0x235B, "KangXiang Electronic Co., Ltd." }, + { 0x235C, "Neuralieve" }, + { 0x235D, "Wavepod Technologies LLC" }, + { 0x235E, "Sage Electronic Engineering LLC" }, + { 0x235F, "Delux Technology Co., Ltd." }, + { 0x2360, "AudioProbe Inc." }, + { 0x2361, "Artiza Networks, Inc." }, + { 0x2362, "Intuity Medical" }, + { 0x2363, "SplitFish Ltd." }, + { 0x2364, "Friedrich Leutert GmbH & Co. KG" }, + { 0x2365, "Midwest Microwave Solutions" }, + { 0x2366, "Bitmanufaktur GmbH" }, + { 0x2367, "Teenage Engineering" }, + { 0x2368, "Peterson Electro-Musical Products, Inc." }, + { 0x2369, "Telspan Data, LLC" }, + { 0x236A, "SiBEAM, Inc." }, + { 0x236B, "Era Optoelectronics Inc." }, + { 0x236C, "ZheJiang Chunsheng Electronics Co., Ltd." }, + { 0x236D, "e-supplies Co., Ltd." }, + { 0x236E, "Idex ASA" }, + { 0x236F, "Risun Electric Information Technology Co., Ltd." }, + { 0x2370, "Vlatacom d.o.o." }, + { 0x2371, "Zetron, Inc." }, + { 0x2372, "Shenzhen Techaser Technologies Co., Ltd." }, + { 0x2373, "Pumatronix Equipamentos Eletronicos Ltda." }, + { 0x2374, "Codan Limited" }, + { 0x2375, "Nexell Co., Ltd." }, + { 0x2376, "Realfiction Aps" }, + { 0x2377, "Musa srl" }, + { 0x2378, "OnLive, INC." }, + { 0x2379, "Geotechnical Instruments (UK) Ltd." }, + { 0x237A, "Danatronics, Corp." }, + { 0x237B, "YUKAI Engineering" }, + { 0x237C, "POWERVAR" }, + { 0x237D, "CradlePoint, Inc." }, + { 0x237E, "Ernie Ball, Inc." }, + { 0x237F, "He Shan World Fair Electronics Technology Ltd." }, + { 0x2380, "Law Enforcement Associates, Inc." }, + { 0x2381, "IPE Music" }, + { 0x2382, "Trigaudio, Inc." }, + { 0x2383, "Super Pioneer Co., Ltd." }, + { 0x2384, "Tamara Electronics Design" }, + { 0x2385, "Booyco Electronics (Pty) Ltd." }, + { 0x2386, "Raydium Semiconductor Corporation" }, + { 0x2387, "N&S Services, Inc. dba XIM Technologies" }, + { 0x2388, "High Density Devices" }, + { 0x2389, "ShenZhen Handin Tech Co., Ltd." }, + { 0x238A, "ASAHI SANGYO CO., LTD." }, + { 0x238B, "Hytera Communications Co., Ltd." }, + { 0x238C, "Japan Care Net Service Corporation" }, + { 0x238D, "OMNIO Corporation" }, + { 0x238E, "Xtralis" }, + { 0x238F, "TRS Star GmbH" }, + { 0x2390, "Triex Technologies, Inc." }, + { 0x2391, "FUKUDA CO., LTD." }, + { 0x2392, "Deltatee Enterprises Ltd." }, + { 0x2393, "WonATech Co., Ltd." }, + { 0x2394, "J.MORITA MFG. CORP." }, + { 0x2395, "CNOGA MEDICAL LTD." }, + { 0x2396, "Advanced Multi Tech Pte. Ltd." }, + { 0x2397, "Simaudio Ltd." }, + { 0x2398, "Bluetechnix" }, + { 0x2399, "Lightwares" }, + { 0x239A, "Adafruit Industries LLC" }, + { 0x239B, "TZ Medical, Inc." }, + { 0x239C, "Braebon Medical Corporation" }, + { 0x239D, "Memjet Labels, Inc." }, + { 0x239E, "Rubin Informatikai Zrt." }, + { 0x239F, "Nikola Engineering Inc." }, + { 0x23A0, "BIFIT" }, + { 0x23A1, "Pepperl+Fuchs GmbH" }, + { 0x23A2, "Mobile Peak Holdings, Ltd." }, + { 0x23A3, "Dongguan City ShengJing Electronics Co., Ltd." }, + { 0x23A4, "MINGTECH CHINA CO., LTD." }, + { 0x23A5, "Instytut Fotonowy Sp. Z o.o." }, + { 0x23A6, "Tronical Components GmbH" }, + { 0x23A7, "System In Frontier Inc." }, + { 0x23A8, "Sagio A/S" }, + { 0x23A9, "SiliconGo Microelectronics Inc." }, + { 0x23AA, "DOK (HK) Trading Limited" }, + { 0x23AB, "SZZT ELECTRONICS CO., LTD" }, + { 0x23AC, "Marunix Electron Limited" }, + { 0x23AD, "voxeljet technology GmbH" }, + { 0x23AE, "DIGITAL DEVICES UG" }, + { 0x23AF, "iOWA AB" }, + { 0x23B0, "Seniorsoft Development Co., Ltd." }, + { 0x23B1, "Riken Keiki Co., Ltd." }, + { 0x23B2, "SEER Technology, Inc." }, + { 0x23B3, "Straubtec GmbH & Co. KG" }, + { 0x23B4, "Dental Wings Inc." }, + { 0x23B5, "Crowcon Detection Instruments Limited" }, + { 0x23B6, "FULL ELECTRONIC system" }, + { 0x23B7, "Isca Networks" }, + { 0x23B8, "Daruma Telecomunicacoes e Informatica S/A" }, + { 0x23B9, "Green Energy Options Ltd." }, + { 0x23BA, "Playback Designs LLC" }, + { 0x23BB, "EMI STOP CORP." }, + { 0x23BC, "ARIDIAN TECHNOLOGY COMPANY INC." }, + { 0x23BD, "Musashi Engineering, Inc." }, + { 0x23BE, "Raynet Technologies Pte. Ltd." }, + { 0x23BF, "Environics Oy" }, + { 0x23C0, "Kotec" }, + { 0x23C1, "MakerBot Industries" }, + { 0x23C2, "CREALOGIX E-Banking AG" }, + { 0x23C3, "Cydle Corp." }, + { 0x23C4, "Media Engineering" }, + { 0x23C5, "Promega Corporation" }, + { 0x23C6, "plawa-feinwerktechnik GmbH & Co. KG" }, + { 0x23C7, "GCI Technologies Corp." }, + { 0x23C8, "IML Ltd." }, + { 0x23C9, "IRM Touch Inc." }, + { 0x23CA, "IHP GmbH Innovations for High Performance Microelectro" }, + { 0x23CB, "Point Core SARL" }, + { 0x23CC, "Avitech International Corp." }, + { 0x23CD, "Avconn Precise Connector Co., Ltd." }, + { 0x23CE, "Gembird Electronics Ltd." }, + { 0x23CF, "Admesy BV" }, + { 0x23D0, "Youjie" }, + { 0x23D1, "LUFFT Mess-und Regeltechnik GmbH" }, + { 0x23D2, "WEAVERSMIND Inc." }, + { 0x23D3, "RFTECH SRL" }, + { 0x23D4, "ALLTRAX, Inc." }, + { 0x23D5, "SerialTek" }, + { 0x23D6, "DONGGUAN LICHENG ELECTRONICS CO., LTD." }, + { 0x23D7, "PENNYWISE PERIPHERALS PTY. LTD." }, + { 0x23D8, "CREATOR (CHINA) TECH CO., LTD." }, + { 0x23D9, "SIGLEAD Inc." }, + { 0x23DA, "THK Co., Ltd." }, + { 0x23DB, "Sonicweld" }, + { 0x23DC, "Phonic Ear, Inc. Frontrow Division" }, + { 0x23DD, "Ningbo Sunny Opotech Co., Ltd." }, + { 0x23DE, "ZAO Papillon" }, + { 0x23DF, "WebAthletics BV" }, + { 0x23E0, "BitifEye Digital Test Solutions GmbH" }, + { 0x23E1, "Vidyo, Inc." }, + { 0x23E2, "Shape Medical Systems, Inc." }, + { 0x23E3, "Christie Digital Systems Canada Inc." }, + { 0x23E4, "General Microsystems Sdn Bhd" }, + { 0x23E5, "Antelope Audio" }, + { 0x23E6, "DIGIT MOBILE INC." }, + { 0x23E7, "ROGER Dariusz Wensker Grzegorz Wensker S.P.j." }, + { 0x23E8, "Propellerhead Software AB" }, + { 0x23E9, "Peregrine Technology Co., Ltd." }, + { 0x23EA, "Inputek" }, + { 0x23EB, "TOPPAN FORMS CO., LTD." }, + { 0x23EC, "Alacer Biomedica Industria Eletronica Ltda." }, + { 0x23ED, "Optomotive, mehatronika d.o.o." }, + { 0x23EE, "Sofird, Inc." }, + { 0x23EF, "PPHU AWEX RAFAL STANUCH" }, + { 0x23F0, "Ecotronics Limited" }, + { 0x23F1, "WIMM Labs" }, + { 0x23F2, "Northern Digital Inc." }, + { 0x23F3, "Funke Digital TV" }, + { 0x23F4, "NXT Plc" }, + { 0x23F5, "Speed Conn Electronics (Shenzhen) Co., Ltd." }, + { 0x23F6, "Gamesman Ltd." }, + { 0x23F7, "TechRhythm, Inc." }, + { 0x23F8, "Xiangde Electronic Technologies (Shenzhen) Co., Ltd." }, + { 0x23F9, "RT Systems (Pty) Ltd." }, + { 0x23FA, "DJO, LLC" }, + { 0x23FB, "Janich & Klass Computertechnik GmbH" }, + { 0x23FC, "SesKion GmbH" }, + { 0x23FD, "AWare, Inc." }, + { 0x23FE, "Express Way Limited" }, + { 0x23FF, "UIworks Electronics" }, + { 0x2400, "Shenzhen Chuangyitong Technology Co., Ltd" }, + { 0x2401, "Deltronic Labs" }, + { 0x2402, "DA FACT" }, + { 0x2403, "XTRAMUS TECHNOLOGIES" }, + { 0x2404, "GE MDS" }, + { 0x2405, "Custom Computer Services, Inc." }, + { 0x2406, "WIseKey" }, + { 0x2407, "Incasolution Co., Ltd." }, + { 0x2408, "Catalyst Enterprises, Inc." }, + { 0x2409, "BCInet, Inc." }, + { 0x240A, "Infron Teknolojik Sistemleri San. Ve Tic. Ltd. STI" }, + { 0x240B, "Kawamura Electric, Inc." }, + { 0x240C, "Maples Micro System Corp" }, + { 0x240D, "Chinachip Technology Limited" }, + { 0x240E, "JEFF ROWLAND DESIGN GROUP, INC" }, + { 0x240F, "Trantek Electronics Co., Ltd." }, + { 0x2410, "Tenebraex Corp." }, + { 0x2411, "Industrial Scientific Oldham SAS" }, + { 0x2412, "Invision Biometrics Ltd." }, + { 0x2413, "Skyviia Corporation" }, + { 0x2414, "Leopold Kostal GmbH & Co. KG" }, + { 0x2415, "CipherLab Co., Ltd." }, + { 0x2416, "FUTURE DESIGNS, INC." }, + { 0x2417, "INIT GmbH" }, + { 0x2418, "Irphotonics" }, + { 0x2419, "Shenzhen Dnine Technology Co., Ltd." }, + { 0x241A, "The Silanna Group Pty. Ltd." }, + { 0x241B, "Dongguan City Qirui Electronics Co., Ltd." }, + { 0x241C, "ATMOS Medizin Technik GmbH & Co. KG" }, + { 0x241D, "Redbird Flight Simulations, Inc." }, + { 0x241E, "SHENZHEN FUNDUN TECHNOLOGY CO., LTD." }, + { 0x241F, "Global Geo Supplies, Inc." }, + { 0x2420, "M Seven System Limited" }, + { 0x2421, "Anasphere, Inc." }, + { 0x2422, "Tom Communication Industrial Co., Ltd." }, + { 0x2423, "Bio-Med Devices Inc." }, + { 0x2424, "CREATZ Inc." }, + { 0x2425, "PIQX Imaging Pte. Ltd." }, + { 0x2426, "Johnson Controls, Inc. - Building Efficiency Business" }, + { 0x2427, "Winkelmann UK Ltd." }, + { 0x2428, "SANTEC CORPORATION" }, + { 0x2429, "IWSCOPE Inc." }, + { 0x242A, "HUR OY" }, + { 0x242B, "Philips Healthcare" }, + { 0x242C, "ARMSTEL, Inc." }, + { 0x242D, "Flastar Technology Co., Ltd." }, + { 0x242E, "Vossloh-Schwabe Deutschland GmbH" }, + { 0x242F, "GPH Co., Ltd." }, + { 0x2430, "APE GmbH" }, + { 0x2431, "Yamazaki Co., Ltd." }, + { 0x2432, "Ceton Corp." }, + { 0x2433, "Asetek A/S" }, + { 0x2434, "NOVA electronics, Inc." }, + { 0x2435, "PAKSENSE, INC." }, + { 0x2436, "MediTECH Electronic GmbH" }, + { 0x2437, "NIKETECH ELECTRONICS GROUP LIMITED" }, + { 0x2438, "Innopower Technology Corporation" }, + { 0x2439, "Comex Electronics AB" }, + { 0x243A, "Mobile Devices Ingenierie" }, + { 0x243B, "OTAX Electronics (ShenZhen) Co., Ltd." }, + { 0x243C, "DiZiC Co., Ltd." }, + { 0x243D, "emz - Hanauer GmbH & Co KGaA" }, + { 0x243E, "Savi Elettronica srl" }, + { 0x243F, "Photonic GesmbH & Co. KG" }, + { 0x2440, "RB GeneralEkonomik" }, + { 0x2441, "TV One" }, + { 0x2442, "University of Central Florida" }, + { 0x2443, "Aessent Technology Ltd." }, + { 0x2444, "NetModule AG" }, + { 0x2445, "TOMY Company, Ltd." }, + { 0x2446, "Avionics Interface Technologies" }, + { 0x2447, "Knick Elektronische Messgerate GmbH & Co. KG" }, + { 0x2448, "Winterhalter GmbH" }, + { 0x2449, "SHAEFER GmbH" }, + { 0x244A, "Onzo Ltd." }, + { 0x244B, "Applied Technical Systems" }, + { 0x244C, "MinebeaMitsumi Inc." }, + { 0x244D, "Pantec Biosolutions AG" }, + { 0x244E, "ShopGuard Ltd." }, + { 0x244F, "iWall A/S" }, + { 0x2450, "Boule Medical AB" }, + { 0x2451, "AEM Performance Electronics" }, + { 0x2452, "Speeder Electronics Co., Ltd." }, + { 0x2453, "BAANTO" }, + { 0x2454, "Velosti Technology Limited" }, + { 0x2455, "Anton/Bauer, Inc." }, + { 0x2456, "CKD NIKKI DENSO CO., LTD" }, + { 0x2457, "Alcomp. Inc." }, + { 0x2458, "Bluegiga Technologies Oy" }, + { 0x2459, "Secure Holdings Limited" }, + { 0x245A, "KONDOH SEISAKUSHO Co., Ltd." }, + { 0x245B, "Zixsys Inc." }, + { 0x245C, "Steinbauer Electronics GmbH" }, + { 0x245D, "ID Technologies" }, + { 0x245E, "LNT - Automation GmbH" }, + { 0x245F, "Chord Electronics Limited" }, + { 0x2460, "NELS, Ltd." }, + { 0x2461, "Beam Communications" }, + { 0x2462, "IDENTICA S.A." }, + { 0x2463, "BAP Precision Ltd." }, + { 0x2464, "Nestlabs" }, + { 0x2465, "Microsoft Surface Hub" }, + { 0x2466, "Fractal Audio Systems, LLC" }, + { 0x2467, "Nektar Technology, Inc." }, + { 0x2468, "New Cosmos Electric Co., Ltd." }, + { 0x2469, "Gloria Music Corp." }, + { 0x246A, "UNH Interoperability Laboratory" }, + { 0x246B, "Perfect Fortune Electric Wire & Cable (ShenZhen) Co. Ltd." }, + { 0x246C, "Shanghai Fudan Microelectronics Co., Ltd." }, + { 0x246D, "TrackMan A/S" }, + { 0x246E, "Movinto Fun AB" }, + { 0x246F, "STORK PRINTS AUSTRIA GmbH" }, + { 0x2470, "Hale Microsystems" }, + { 0x2471, "Bloonn Srl" }, + { 0x2472, "Bossa Nova Robotics, Inc." }, + { 0x2473, "Trend Control Systems Limited" }, + { 0x2474, "Stamps.com" }, + { 0x2475, "JCM American Corporation" }, + { 0x2476, "Yost Engineering Inc." }, + { 0x2477, "UbiVelox" }, + { 0x2478, "Sonix Technology (Shenzhen) Co., Ltd." }, + { 0x2479, "smartek d.o.o." }, + { 0x247A, "Suzhou Jutze Technologies Co., Ltd" }, + { 0x247B, "Digibras Industria do Brasil S.A" }, + { 0x247C, "Fullconn Industry Inc." }, + { 0x247D, "JARGY CO. LTD." }, + { 0x247E, "GEWA music GmbH" }, + { 0x247F, "Lynx Studio Technology, Inc." }, + { 0x2480, "Omniware Inc." }, + { 0x2481, "Shenzhen SKY DRAGON Audio-Video Technology Co., Ltd." }, + { 0x2482, "SmartRoom LLC" }, + { 0x2483, "Valups Corp." }, + { 0x2484, "Unipolar Optics-Electrical Technology Co., Ltd." }, + { 0x2485, "Dream SAS" }, + { 0x2486, "DCG Systems, Inc." }, + { 0x2487, "SHANGHAI VEI SHENG AUTO PARTS MANUFACTURING CO., LTD." }, + { 0x2488, "SuperD Co., Ltd." }, + { 0x2489, "Irvine Sensors Corporation" }, + { 0x248A, "TeLink Semiconductor (Shanghai) Co., Ltd." }, + { 0x248B, "DONGGUAN SYNCONN PRECISION INDUSTRY CO. LTD." }, + { 0x248C, "Avicenna Instruments, LLC" }, + { 0x248D, "Digital Matter Pty Ltd." }, + { 0x248E, "Pulsar Informatics, Inc." }, + { 0x248F, "HMS Industrial Networks AB" }, + { 0x2490, "Zealtek electronic Co. Ltd." }, + { 0x2491, "OBSERVATOR instruments b.v." }, + { 0x2492, "Mofiria Corporation" }, + { 0x2493, "Sensolutions Inc." }, + { 0x2494, "Invoxia" }, + { 0x2495, "Summit Semiconductor LLC" }, + { 0x2496, "Dongguan DaTang Industrial Investment Co., Ltd." }, + { 0x2497, "HyunWoo Electronics Co., Ltd." }, + { 0x2498, "Aurora SFC Systems, Inc." }, + { 0x2499, "Governors America Corp." }, + { 0x249A, "Anedio, LLC" }, + { 0x249B, "Miller Electric Mfg. Co." }, + { 0x249C, "M2TECH SRL" }, + { 0x249D, "Ken-A-Vision Manufacturing Company, Inc." }, + { 0x249E, "Tlab West Systems AB" }, + { 0x249F, "ABC PCB Sarl" }, + { 0x24A0, "VIMAR SPA" }, + { 0x24A1, "AUTONICS Corporation" }, + { 0x24A2, "SafeTech Ltd." }, + { 0x24A3, "BioTillion, LLC" }, + { 0x24A4, "Primare AB" }, + { 0x24A5, "OWANDY" }, + { 0x24A6, "Shenzhen Pangngai Industrial Co., Ltd." }, + { 0x24A7, "PROMAX ELECTRONICA S.A." }, + { 0x24A8, "Hermes electronic GmbH" }, + { 0x24A9, "ASolid Technology Co., Ltd." }, + { 0x24AA, "Wasatch Photonics" }, + { 0x24AB, "IMERJ LTD." }, + { 0x24AC, "ToMiTec GmbH" }, + { 0x24AD, "embedded brains GmbH" }, + { 0x24AE, "Shenzhen Rapoo Technology Co., Ltd." }, + { 0x24AF, "Integrated Corporation" }, + { 0x24B0, "Echometer Company" }, + { 0x24B1, "SCR Engineers Ltd." }, + { 0x24B2, "DelSys Inc." }, + { 0x24B3, "Simbionix Ltd." }, + { 0x24B4, "Leema Acoustics" }, + { 0x24B5, "3C TEK CORP." }, + { 0x24B6, "Shenzhen New-Conn International Co., Ltd." }, + { 0x24B7, "Medical Equipment Europe GmbH" }, + { 0x24B8, "DongGuan CJ TOUCH Electronic Co., Ltd." }, + { 0x24B9, "Hoshin Electronics Co., Ltd." }, + { 0x24BA, "PRADOTEC Corporation Sdn. Bhd." }, + { 0x24BB, "SHANGHAI LIGHTSURFING INFORMATION TECHNOLOGY CO., LTD." }, + { 0x24BC, "Sartorius AG" }, + { 0x24BD, "Smart Solution" }, + { 0x24BE, "Mutewatch AB" }, + { 0x24BF, "NBS Payment Solutions, Inc." }, + { 0x24C0, "Chaney Instrument Co." }, + { 0x24C1, "Maction Technologies, Inc." }, + { 0x24C2, "DiCon Fiberoptics, Inc." }, + { 0x24C3, "Covaris, Inc." }, + { 0x24C4, "CMITECH Co., Ltd." }, + { 0x24C5, "HUINTECH" }, + { 0x24C6, "Xbox 3rd Party Partners" }, + { 0x24C7, "Laser Technology, Inc." }, + { 0x24C8, "CHAPP INC." }, + { 0x24C9, "Pilot Electronic (China) Ltd." }, + { 0x24CA, "SMARTEH d.o.o." }, + { 0x24CB, "Servotronix Motion Control Ltd." }, + { 0x24CC, "JSB Tech Pte. Ltd." }, + { 0x24CD, "Viking360.com LLC" }, + { 0x24CE, "Shenzhen Deren Electronic Co., Ltd." }, + { 0x24CF, "Lytro, Inc." }, + { 0x24D0, "Smith Micro Software, Inc." }, + { 0x24D1, "POS & Solution Company" }, + { 0x24D2, "DADT Holdings, LLC" }, + { 0x24D3, "Lexking Technology Co., Ltd." }, + { 0x24D4, "KOMATSU ELECTRONIC CO., LTD." }, + { 0x24D5, "SATEL Ltd." }, + { 0x24D6, "Develer S.r.l." }, + { 0x24D7, "ACORDE TECHNOLOGIES" }, + { 0x24D8, "Pittway Tecnologica Srl" }, + { 0x24D9, "Unfors Instruments AB" }, + { 0x24DA, "KYOCERA ELCO Korea Co., Ltd." }, + { 0x24DB, "DDUSB Technology" }, + { 0x24DC, "Aladdin Software Security R.D." }, + { 0x24DD, "Kingspan Environmental Ltd." }, + { 0x24DE, "Navicron" }, + { 0x24DF, "ALGO System. Co" }, + { 0x24E0, "Yoctopuce Sarl" }, + { 0x24E1, "Paratronic S.A." }, + { 0x24E2, "Digital Information Technology Studies (Shenzhen) Ltd." }, + { 0x24E3, "Beijing TianYu Communication Equipment Co., Ltd." }, + { 0x24E4, "Bytec Group Limited" }, + { 0x24E5, "Lanmark Controls Inc." }, + { 0x24E6, "ACI Analytical Control Instruments GmbH" }, + { 0x24E7, "maxon motor ag" }, + { 0x24E8, "ivee" }, + { 0x24E9, "Microelectronics Technology Inc." }, + { 0x24EA, "ZEBEX INDUSTRIES INC." }, + { 0x24EB, "SHENZHEN PCTX TECHNOLOGY DEVELOPMENT CO., LTD." }, + { 0x24EC, "CE-Infosys GmbH" }, + { 0x24ED, "ZEN FACTORY GROUP (ASIA) LTD." }, + { 0x24EE, "A C S Co., Ltd." }, + { 0x24EF, "DATONG PLC" }, + { 0x24F0, "Das Keyboard - Metadot" }, + { 0x24F1, "Silicon Communication Technology" }, + { 0x24F2, "Secure Electrans LTD." }, + { 0x24F3, "MartinLogan Ltd." }, + { 0x24F4, "Mind Media BV" }, + { 0x24F5, "QRS Diagnostic" }, + { 0x24F6, "Aplix IP Holdings Corporation" }, + { 0x24F7, "Seneye Ltd." }, + { 0x24F8, "Bang & Olufsen A/S" }, + { 0x24F9, "TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORP." }, + { 0x24FA, "Vectronix AG" }, + { 0x24FB, "GTECH Corporation" }, + { 0x24FC, "GPEG International" }, + { 0x24FD, "Nichiyu Giken Kogyo Co., Ltd." }, + { 0x24FE, "GOMETRICS, S.L." }, + { 0x24FF, "Acroname Inc." }, + { 0x2500, "Ettus Research LLC" }, + { 0x2501, "Bridge Publications, Inc." }, + { 0x2502, "Canadian Automotive Instruments Ltd." }, + { 0x2503, "Kurth Electronic GmbH" }, + { 0x2504, "Nemic Lambda Ltd." }, + { 0x2505, "Xiroku Accupoint Technology Inc." }, + { 0x2506, "Hind Technology Group" }, + { 0x2507, "Advion BioSystems" }, + { 0x2508, "Symplex Communications, Inc." }, + { 0x2509, "Chain-In Electronic Co., Ltd." }, + { 0x250A, "H-Squared" }, + { 0x250B, "Nautilus Lifeline Ltd." }, + { 0x250C, "PHX Inc." }, + { 0x250D, "Alstom Grid SAS" }, + { 0x250E, "Beijing MOPS Technology Co., Ltd." }, + { 0x250F, "itplants ltd." }, + { 0x2510, "SE Elektronische Systeme" }, + { 0x2511, "Morita Tech Co., Ltd." }, + { 0x2512, "RNDPLUS Co., Ltd." }, + { 0x2513, "RMI Laser, LLC" }, + { 0x2514, "Fullpower Technologies" }, + { 0x2515, "AMITEK" }, + { 0x2516, "Cooler Master Co., Ltd." }, + { 0x2517, "Marel EHF" }, + { 0x2518, "Anite Telecoms Inc." }, + { 0x2519, "n-gineric gmbh" }, + { 0x251A, "Daiichi Electronics" }, + { 0x251B, "Stable Imaging Solutions, LLC" }, + { 0x251C, "snom technology AG" }, + { 0x251D, "Fortebio Inc." }, + { 0x251E, "Polara Engineering, Inc." }, + { 0x251F, "Golden Emperor International Ltd." }, + { 0x2520, "ANA-U GmbH" }, + { 0x2521, "Fundacion Tekniker" }, + { 0x2522, "Light Harmonic" }, + { 0x2523, "Recon Instruments Inc." }, + { 0x2524, "CVRx" }, + { 0x2525, "Barron McCann Technology Ltd." }, + { 0x2526, "Weide Electronics Co., Ltd." }, + { 0x2527, "Software Bisque, Inc." }, + { 0x2528, "BittWare Inc." }, + { 0x2529, "SUZHOU XINYA ELECTRIC COMMUNICATION CO., LTD." }, + { 0x252A, "SUZHOU KELI TECHNOLOGY DEVELOPMENT CO., LTD." }, + { 0x252B, "TOP Exactitude Industry (ShenZhen) Co., Ltd." }, + { 0x252C, "VIGO System S.A." }, + { 0x252D, "Nokia Siemens Networks" }, + { 0x252E, "Heliox Technologies, Inc." }, + { 0x252F, "Pentronic AB" }, + { 0x2530, "STT Emtec AB" }, + { 0x2531, "Proteus Industries Inc." }, + { 0x2532, "C.R.D.E. (Cahors Group)" }, + { 0x2533, "Osaka Micro Computer, Inc." }, + { 0x2534, "Russia's Institute of Radionavigation and Time" }, + { 0x2535, "ShenZhen Hogend Precision Technology Co., Ltd." }, + { 0x2536, "Ubisys Technology Co., Ltd." }, + { 0x2537, "Norel Systems Ltd." }, + { 0x2538, "Cochlear Ltd." }, + { 0x2539, "Club Electronics" }, + { 0x253A, "System Sacom Industry Corporation" }, + { 0x253B, "RCF S.p.a." }, + { 0x253C, "Tri-Tech Manufacturing Inc." }, + { 0x253D, "Koss Corporation" }, + { 0x253E, "Creative Product Design Pty., Ltd." }, + { 0x253F, "ORANGE IT INC." }, + { 0x2540, "Applied Materials" }, + { 0x2541, "Shanghai AisinoChip Electronics Technology Co., Ltd." }, + { 0x2542, "Ditron S.R.L." }, + { 0x2543, "Spark Dental Technology Limited" }, + { 0x2544, "Energy Micro AS" }, + { 0x2545, "Digital Foci, Inc." }, + { 0x2546, "Ravensburger Spieleverlag GmbH" }, + { 0x2547, "YiDu Technology" }, + { 0x2548, "Pulse-Eight Limited" }, + { 0x2549, "Librestream Technologies" }, + { 0x254A, "Enegate Co., Ltd." }, + { 0x254B, "Toy Toy Toy Ltd." }, + { 0x254C, "X6D Limited" }, + { 0x254D, "ICAR VISION SYSTEMS S.L." }, + { 0x254E, "SHF Communication Technologies AG" }, + { 0x254F, "Jigeon Technologies Co., Ltd." }, + { 0x2550, "Teledyne" }, + { 0x2551, "A.E.B. Industriale S.r.l." }, + { 0x2552, "Striiv, Inc." }, + { 0x2553, "C8 MediSensor" }, + { 0x2554, "ASSA ABLOY AB" }, + { 0x2555, "Pulse Tracer, Inc." }, + { 0x2556, "United Radio-Electronic Technologies Co., Ltd." }, + { 0x2557, "Robatech AG" }, + { 0x2558, "INTECH ELECTRONICS CORP." }, + { 0x2559, "Jangus Music, Inc. (dba Wi Digital Systems)" }, + { 0x255A, "TaiDoc Technology Corp." }, + { 0x255B, "NDI Technologies, Inc." }, + { 0x255C, "HOSIWELL TECHNOLOGY CO., LTD." }, + { 0x255D, "ATEECS" }, + { 0x255E, "Beijing Bonxeon Technology Co., Ltd." }, + { 0x255F, "DORNIER-LTF GmbH" }, + { 0x2560, "e-con Systems India Private Limited" }, + { 0x2561, "Brookhaven Instruments Corp." }, + { 0x2562, "SHENGZHEN MAYA ELECTRONICS CREATION CO. LTD." }, + { 0x2563, "Shenzhen ShanWan Technology Co., Ltd." }, + { 0x2564, "TESSERA TECHNOLOGY INC." }, + { 0x2565, "Cyclone Industries Limited" }, + { 0x2566, "Cryptera A/S" }, + { 0x2567, "DongGuan LongTao Electronic Co., Ltd." }, + { 0x2568, "ALL LINK CONN. TECHNOLOGY CORP." }, + { 0x2569, "DongGuan City MingJi Electronics Co., Ltd." }, + { 0x256A, "TAIAN TECHNOLOGY (WUXI) Co., Ltd." }, + { 0x256B, "Perreaux Industries Ltd." }, + { 0x256C, "GRAPHICS TECHNOLOGY (HK) CO., LIMITED" }, + { 0x256D, "Compal Broadband Networks, Inc." }, + { 0x256E, "Valuest Co., Ltd." }, + { 0x256F, "3D CONNEXION SAM" }, + { 0x2570, "AVID Technologies, Inc." }, + { 0x2571, "CHIPMAST TECHNOLOGY CO., LTD." }, + { 0x2572, "Vmarker" }, + { 0x2573, "ESI Audiotechnik GmbH" }, + { 0x2574, "AVer Information Inc." }, + { 0x2575, "Weida Hi-Tech Co., Ltd." }, + { 0x2576, "AFO Co., Ltd." }, + { 0x2577, "LCDVF LLC" }, + { 0x2578, "MPEC Technology Limited" }, + { 0x2579, "Dongguan Wisechamp Electronic Co., Ltd." }, + { 0x257A, "Shanghai Yuga Information Technology Co., Ltd." }, + { 0x257B, "shenzhen dcard smart card tech. co., ltd." }, + { 0x257C, "Richard Woehr GmbH" }, + { 0x257D, "Panovel Technology Corporation" }, + { 0x257E, "RFL Electronics Inc." }, + { 0x257F, "8devices" }, + { 0x2580, "DJ Techtools (Golden Sol Music LLC. Is Holding Co.)" }, + { 0x2581, "Plug-up" }, + { 0x2582, "Helmholz GmbH & Co. KG" }, + { 0x2583, "VECTRUX DISTRIBUTORS LLC" }, + { 0x2584, "COSMO CO., LTD." }, + { 0x2585, "HomeChip Ltd." }, + { 0x2586, "PLANET Technology Corporation" }, + { 0x2587, "Ningbo Jiatang Electronic Co., Ltd." }, + { 0x2588, "Infinitegra, Inc." }, + { 0x2589, "Argon Technology Corporation" }, + { 0x258A, "Sino Wealth Electronic Ltd." }, + { 0x258B, "KORYO ELECTRONICS CO., LTD." }, + { 0x258C, "Fastec Imaging Corporation" }, + { 0x258D, "Sequans Communications" }, + { 0x258E, "ENJsoft Co., Ltd." }, + { 0x258F, "CME" }, + { 0x2590, "MuChip Co., Ltd." }, + { 0x2591, "Optimus Semiconductor Inc." }, + { 0x2592, "Quest International" }, + { 0x2593, "CELIZION, Inc." }, + { 0x2594, "Acsys Technologies Ltd." }, + { 0x2595, "SANYO DENKI CO., LTD." }, + { 0x2596, "Twisted Melon Inc." }, + { 0x2597, "Diagnostic Systems Associates Inc." }, + { 0x2598, "Aerocrine" }, + { 0x2599, "Q-tag AG" }, + { 0x259A, "TriQuint Semiconductor" }, + { 0x259B, "INUVIO" }, + { 0x259C, "Immedia Semiconductor Inc." }, + { 0x259D, "RCA DA AMAZONIA LTDA" }, + { 0x259E, "American Messaging Services LLC" }, + { 0x259F, "THERMO KING" }, + { 0x25A0, "Ciegus Ltd." }, + { 0x25A1, "Suitable Technologies, Inc." }, + { 0x25A2, "LEMKE ENG." }, + { 0x25A3, "Nanoteq (Pty) Ltd." }, + { 0x25A4, "ALGOLTEK, INC." }, + { 0x25A5, "Yakel Enterprises LLC" }, + { 0x25A6, "AADI AS" }, + { 0x25A7, "Beken Corporation" }, + { 0x25A8, "Guangzhou Geoelectron Science & Technology Co., Ltd." }, + { 0x25A9, "Advanced Bionics" }, + { 0x25AA, "Top Victory Investments Ltd. (HK)" }, + { 0x25AB, "Carmanah Signs" }, + { 0x25AC, "PLIGG" }, + { 0x25AD, "Aurora Networks, Inc." }, + { 0x25AE, "OXIPULSE" }, + { 0x25AF, "C&A Marketing" }, + { 0x25B0, "Musical Fidelity" }, + { 0x25B1, "Disc Soft Ltd." }, + { 0x25B2, "DRS-RSTA, Inc." }, + { 0x25B3, "DongGuan Elinke Industrial Co., Ltd." }, + { 0x25B4, "Fairhaven Health" }, + { 0x25B5, "FlatFrog Laboratories AB" }, + { 0x25B6, "Fructel AB" }, + { 0x25B7, "Neomitic Technologies S.A. de C.V." }, + { 0x25B8, "Neutronics Inc." }, + { 0x25B9, "Nujira Ltd." }, + { 0x25BA, "WITec Wissenschaftliche Instrumente & Technologie GmbH" }, + { 0x25BB, "Brunner Elektronik AG" }, + { 0x25BC, "CETRTA POT" }, + { 0x25BD, "TECHEYE SYSTEMS INC." }, + { 0x25BE, "Infinite Z" }, + { 0x25BF, "Elegant Invention" }, + { 0x25C0, "Beyond Music Industrial Co., Ltd." }, + { 0x25C1, "Vaddio" }, + { 0x25C2, "Smith + Nephew Inc." }, + { 0x25C3, "Phorus" }, + { 0x25C4, "A & R Cambridge Ltd." }, + { 0x25C5, "Securetec Detektions Systeme AG" }, + { 0x25C6, "AVA Group A/S" }, + { 0x25C7, "MEGATRON Elektronik AG & Co." }, + { 0x25C8, "Visualplanet Ltd." }, + { 0x25C9, "Proximiant" }, + { 0x25CA, "Hovding Sverige AB" }, + { 0x25CB, "ELZET80 Mikrocomputer Giesler & Danne GmbH & Co. KG" }, + { 0x25CC, "NKC Co., Ltd." }, + { 0x25CD, "Edwards Ltd." }, + { 0x25CE, "MYTEK DIGITAL" }, + { 0x25CF, "Corning Optical Communications LLC" }, + { 0x25D0, "AeVee Laboratories LLC" }, + { 0x25D1, "TOKAI-DENSHI Inc." }, + { 0x25D2, "MRA Tek LLC" }, + { 0x25D3, "Zhe Jiang Huasheng Technology Co., Ltd." }, + { 0x25D4, "LOOPCOMM TECHNOLOGY, INC." }, + { 0x25D5, "DATATON AB" }, + { 0x25D6, "KOUZIRO Co., Ltd." }, + { 0x25D7, "Audiomatica srl" }, + { 0x25D8, "Serious Integrated, Inc." }, + { 0x25D9, "Monarch Innovative Technologies Pvt. Ltd." }, + { 0x25DA, "NETATMO" }, + { 0x25DB, "Merrick Industries, Inc." }, + { 0x25DC, "Cobolt AB" }, + { 0x25DD, "bit4id srl" }, + { 0x25DE, "Gasmet Technologies OY" }, + { 0x25DF, "TTE Systems Ltd." }, + { 0x25E0, "MULTIPLEX Modellsport GmbH & Co. KG" }, + { 0x25E1, "Daimler AG" }, + { 0x25E2, "Domain Surgical" }, + { 0x25E3, "SCI Innovations Ltd." }, + { 0x25E4, "AnaJet" }, + { 0x25E5, "ALLFLEX EUROPE" }, + { 0x25E6, "Digital Drilling Data Systems, LLC" }, + { 0x25E7, "EIFELWERK Butler Systeme GmbH" }, + { 0x25E8, "ATOLL Electronique" }, + { 0x25E9, "Leybold Vacuum" }, + { 0x25EA, "Aeroflex Weinschel" }, + { 0x25EB, "Medical Intubation Technology Corp." }, + { 0x25EC, "VELUX A/S" }, + { 0x25ED, "Logic PD" }, + { 0x25EE, "Mimoco" }, + { 0x25EF, "BLITZ Co., Ltd." }, + { 0x25F0, "GOODBETTERBEST Ltd." }, + { 0x25F1, "Eden Innovations" }, + { 0x25F2, "Dongguan Jinyue Electronics Co., Ltd." }, + { 0x25F3, "Kicker" }, + { 0x25F4, "ADVANSEE" }, + { 0x25F5, "Lucas Holding bv" }, + { 0x25F6, "SaferZone Co., Ltd." }, + { 0x25F7, "Engineea Remote Technologies S.L." }, + { 0x25F8, "Keypair Co., Ltd." }, + { 0x25F9, "Donbass Soft Ltd. & Co. KG" }, + { 0x25FA, "SoftEther Corporation" }, + { 0x25FB, "RICOH IMAGING COMPANY, LTD." }, + { 0x25FC, "RWA (Hong Kong) Limited" }, + { 0x25FD, "Neuromonics Inc." }, + { 0x25FE, "Providence Enterprise Limited" }, + { 0x25FF, "Watermark Medical, Inc." }, + { 0x2600, "SMARTCORE Inc." }, + { 0x2601, "OFI Testing Equipment, Inc." }, + { 0x2602, "Magenta Research Ltd." }, + { 0x2603, "Swyx Solutions AG" }, + { 0x2604, "Shenzhen Tenda Technology, Ltd." }, + { 0x2605, "OSRAM SYLVANIA" }, + { 0x2606, "O-Network Engineering AB" }, + { 0x2607, "Prox Dynamics AS" }, + { 0x2608, "OLHO tronic GmbH" }, + { 0x2609, "FICOSA" }, + { 0x260A, "SPEMOT AG" }, + { 0x260B, "Schneider Electric Canada Inc. - Division of PCT" }, + { 0x260C, "Saiko Systems Ltd." }, + { 0x260D, "DongGuan Togran Electronic Co., Ltd." }, + { 0x260E, "DongGuan HYX Industrial Co., Ltd." }, + { 0x260F, "VITY" }, + { 0x2610, "Egan Teamboard Inc." }, + { 0x2611, "I.C.E. Co., Ltd." }, + { 0x2612, "Crave Innovations" }, + { 0x2613, "Gerd Bar GmbH" }, + { 0x2614, "VMC Consulting Corporation" }, + { 0x2615, "Gammaflux L.P." }, + { 0x2616, "PS Audio" }, + { 0x2617, "Front-End Technology, Inc." }, + { 0x2618, "MicroGate Systems Ltd." }, + { 0x2619, "Advanced Silicon SA" }, + { 0x261A, "Shandong Synthesis Electronic Technology Co., Ltd." }, + { 0x261B, "INTELLIGENT ENERGY, LTD." }, + { 0x261C, "EISST Limited" }, + { 0x261D, "Arkham Technology" }, + { 0x261E, "IFAM GmbH Erfurt" }, + { 0x261F, "Cooper Industries" }, + { 0x2620, "SUE unicon.uz Scientific, Engineering & Marketing RC" }, + { 0x2621, "CLIXUP LLC" }, + { 0x2622, "IAG Group Limited" }, + { 0x2623, "SGR Audio Pty Ltd." }, + { 0x2624, "L-3 Communications - Communications Systems West" }, + { 0x2625, "MilDef AB" }, + { 0x2626, "Aruba Networks" }, + { 0x2627, "Vectron Systems AG" }, + { 0x2628, "TEN-TEC, INC." }, + { 0x2629, "Winstars Technology Limited" }, + { 0x262A, "SAVITECH CORP." }, + { 0x262B, "YTOP Electronics Technical (Kunshan) Co., Ltd." }, + { 0x262C, "Scannx" }, + { 0x262D, "Fujian Witsi Microelectronics Technology Co., Ltd." }, + { 0x262E, "UNITEX Corporation" }, + { 0x262F, "MELAG Medizintechnik oHG" }, + { 0x2630, "ifm electronic gmbh" }, + { 0x2631, "NEOPROT TECNOLOGIA EM INFORMATICA LTDA." }, + { 0x2632, "ENSPERT Inc." }, + { 0x2633, "Inno Audio & Video (HK) Limited" }, + { 0x2634, "E.M.S. S.R.L." }, + { 0x2635, "uHDevice Technology Ltd." }, + { 0x2636, "MED-EL Medical Electronics" }, + { 0x2637, "TAEWOONG MEDICAL. CO., LTD." }, + { 0x2638, "Becker-Antriebe GmbH" }, + { 0x2639, "Xsens Technologies B.V." }, + { 0x263A, "Maury Microwave" }, + { 0x263B, "Time & Data Systems International Ltd." }, + { 0x263C, "Schultes Microcomputer-Vertriebs-GmbH & Co KG" }, + { 0x263D, "pls Programmierbare Logik & Systeme GmbH" }, + { 0x263E, "Odin TeleSystems Inc." }, + { 0x263F, "ES-Experts, Ltd." }, + { 0x2640, "Banner Engineering" }, + { 0x2641, "PRO TUNE ELECTRONIC SYSTEMS" }, + { 0x2642, "NPP ELIKS America Inc. DBA T&M Atlantic" }, + { 0x2643, "COMVOX AUDIO CO., LTD." }, + { 0x2644, "Sioux Electronics B.V." }, + { 0x2645, "Lead Data Inc." }, + { 0x2646, "Bel Canto Design, Ltd." }, + { 0x2647, "FORMER ENGINEERING SERVICE CO., LTD." }, + { 0x2648, "Telongo LLC" }, + { 0x2649, "Soundspring Audio, Inc" }, + { 0x264A, "THERMALTAKE Technology Co., Ltd." }, + { 0x264B, "Industrial Indexing Systems" }, + { 0x264C, "Si14 SpA" }, + { 0x264D, "Wolfrum Elektronik & Avionik" }, + { 0x264E, "3i Corporation" }, + { 0x264F, "RF Controls, LLC" }, + { 0x2650, "Electronics For Imaging, Inc." }, + { 0x2651, "Otis Instruments Inc." }, + { 0x2652, "Fallbrook Technologies, Inc." }, + { 0x2653, "AutoHotBox" }, + { 0x2654, "DarklingX, LLC" }, + { 0x2655, "Moog Inc." }, + { 0x2656, "Ashcroft Inc." }, + { 0x2657, "Embedia Technologies Corporation" }, + { 0x2658, "Sintermask GmbH" }, + { 0x2659, "Sundtek" }, + { 0x265A, "3Brain GmbH" }, + { 0x265B, "D-tect Systems" }, + { 0x265C, "IDEX Health + Science LLC" }, + { 0x265D, "H. Schomaecker GmbH" }, + { 0x265E, "JSC Engineering Centre Energoservice" }, + { 0x265F, "Azatrax" }, + { 0x2660, "YEONG DER (SUM-EM) Enterprises Co., Ltd." }, + { 0x2661, "WorldCast Systems" }, + { 0x2662, "MOOG Music Inc." }, + { 0x2663, "JOMESA Messsysteme GmbH" }, + { 0x2664, "NOHMI BOSAI Ltd." }, + { 0x2665, "Yamaki Electric Corporation" }, + { 0x2666, "BLX IC Design Corp., Ltd." }, + { 0x2667, "SuZhou ZhongXingLian Precision Industrial Co., Ltd." }, + { 0x2668, "Shenzhen Yuwenfa Electronic Technology Co., Ltd." }, + { 0x2669, "ME4SURE, Inc." }, + { 0x266A, "Linear LLC" }, + { 0x266B, "ProSys Development Services" }, + { 0x266C, "Brightsight BV" }, + { 0x266D, "Ergotest Innovation A.S." }, + { 0x266E, "Multimedia Link, Inc." }, + { 0x266F, "Shanghai Zhengyuan Technologies Co., Ltd." }, + { 0x2670, "Zhengzhou Xin Da Jie An Information Technology Co., Ltd" }, + { 0x2671, "Innovative Logic" }, + { 0x2672, "GoPro" }, + { 0x2673, "Wadia Digital" }, + { 0x2674, "Hoyt Monitor Technologies, LLC" }, + { 0x2675, "Peter Huber Kaeltemaschinenbau GmbH" }, + { 0x2676, "Basler AG" }, + { 0x2677, "Winegard Company" }, + { 0x2678, "Sky Deutschland GmbH & Co. KG" }, + { 0x2679, "BESTMEDIA CD-Recordable GmbH & Co. KG" }, + { 0x267A, "Xi'an YEP Telecommunication Technology Co., Ltd." }, + { 0x267B, "Palpilot International Corp." }, + { 0x267C, "OptiGene Limited" }, + { 0x267D, "KOHZU Precision Co., Ltd." }, + { 0x267E, "E.D. Bullard Company" }, + { 0x267F, "Acromag Inc." }, + { 0x2680, "DIGICO UK Limited" }, + { 0x2681, "MYLAPS B.V." }, + { 0x2682, "ROBOX S.P.A." }, + { 0x2683, "Gazogiken Co., Ltd." }, + { 0x2684, "Funkwerk Security Communications GmbH" }, + { 0x2685, "Cardo Systems Inc." }, + { 0x2686, "IP LABS Inc." }, + { 0x2687, "FITBIT" }, + { 0x2688, "Stratasys Inc." }, + { 0x2689, "StepOver Inc." }, + { 0x268A, "QEES" }, + { 0x268B, "Dimension Engineering LLC" }, + { 0x268C, "AMS-TAOS" }, + { 0x268D, "WEISS ENGINEERING LTD." }, + { 0x268E, "xyzmo Software GmbH" }, + { 0x268F, "LETech Co., Ltd." }, + { 0x2690, "K.K. Rabbit" }, + { 0x2691, "ZINK Imaging, Inc." }, + { 0x2692, "CELLIENT CO., LTD." }, + { 0x2693, "Silvershore Technology Partners" }, + { 0x2694, "RoboteX Inc." }, + { 0x2695, "DynaGen Technologies Inc." }, + { 0x2696, "Sensovation AG" }, + { 0x2697, "Anfatec Instruments" }, + { 0x2698, "EVTD Inc." }, + { 0x2699, "ECOUS Corp." }, + { 0x269A, "BETTER MANAGE INVESTMENTS LIMITED" }, + { 0x269B, "Novel Data Solutions (Suzhou) Corporation" }, + { 0x269C, "ECTRON CORPORATION" }, + { 0x269D, "Accessible Technologies, Inc." }, + { 0x269E, "Astro Gaming" }, + { 0x269F, "DKL TECHNOLOGY (SHENZHEN) CO., LTD." }, + { 0x26A0, "MIDAS" }, + { 0x26A1, "Miris AB" }, + { 0x26A2, "Eppendorf AG" }, + { 0x26A3, "EMKO ELEKTRONIK SAN. VE TIC. AS" }, + { 0x26A4, "Blue Goji" }, + { 0x26A5, "CAL TEST ELECTRONICS, INC." }, + { 0x26A6, "Radio Design Group, Inc." }, + { 0x26A7, "LOG-IN, Inc." }, + { 0x26A8, "UNIREX CORPORATION" }, + { 0x26A9, "Research Industrial Systems IT-Engineering (RISE) GmbH" }, + { 0x26AA, "YAESU MUSEN CO., LTD." }, + { 0x26AB, "Motion Control Systems, Inc." }, + { 0x26AC, "3D Robotics Inc." }, + { 0x26AD, "Global Distribution GmbH" }, + { 0x26AE, "Oscium" }, + { 0x26AF, "Bombardier Transportation GmbH, TCMS Development Ctr 2" }, + { 0x26B0, "Zhejiang Senda Electronics Co., Ltd." }, + { 0x26B1, "Bassett Electronic Systems Limited" }, + { 0x26B2, "RST Instruments Ltd." }, + { 0x26B3, "Global Inkjet Systems" }, + { 0x26B4, "Sensor Technology Limited" }, + { 0x26B5, "ELECTROCOMPANIET AS" }, + { 0x26B6, "Pacom Systems Pty. Ltd." }, + { 0x26B7, "Azusatekuno" }, + { 0x26B8, "InkControl, LLC" }, + { 0x26B9, "Satlantic LP" }, + { 0x26BA, "Freetronics Pty Ltd." }, + { 0x26BB, "Omega Elektronik Sanayi ve Ticaret A.S." }, + { 0x26BC, "CARDIN ELETTRONICA S.p.A." }, + { 0x26BD, "Integral Memory Plc." }, + { 0x26BE, "AKASA (ASIA) CORP." }, + { 0x26BF, "Broadway System, Inc." }, + { 0x26C0, "RADIODETECTION LTD." }, + { 0x26C1, "Viola Audio Laboratories" }, + { 0x26C2, "FUTURE UNIVERSITY HAKODATE" }, + { 0x26C3, "HARLEY-DAVIDSON MOTOR COMPANY" }, + { 0x26C4, "Logic Way GmbH" }, + { 0x26C5, "TOKAI RUBBER INDUSTRIES, LTD." }, + { 0x26C6, "GRAF-SYTECO GmbH & Co. KG" }, + { 0x26C7, "Beijing Stone New Technology Industry Co., Ltd." }, + { 0x26C8, "SCHMID mme - electronic product engineering" }, + { 0x26C9, "SPM INSTRUMENT AB" }, + { 0x26CA, "MSY Inc." }, + { 0x26CB, "Sung Kyung Precision Co., Ltd." }, + { 0x26CC, "Hunting Titan" }, + { 0x26CD, "Blendology Limited" }, + { 0x26CE, "ASRock Inc." }, + { 0x26CF, "The Gate Technologies" }, + { 0x26D0, "ZK Celltest, Inc." }, + { 0x26D1, "THORLABS LTD." }, + { 0x26D2, "Jiangsu Yinhe Electronics Co., Ltd." }, + { 0x26D3, "VIBRATION INSTRUMENTS CO., LTD." }, + { 0x26D4, "Truesense Imaging" }, + { 0x26D5, "Equinox Payments, LLC" }, + { 0x26D6, "Sistemi Elettronici Di Addonizio Luisa" }, + { 0x26D7, "POPSPA (HK) LTD." }, + { 0x26D8, "APR, LLC" }, + { 0x26D9, "ATC-NY" }, + { 0x26DA, "Dabi Atlante" }, + { 0x26DB, "American DJ Supply" }, + { 0x26DC, "Gato Audio" }, + { 0x26DD, "Monnit Corp." }, + { 0x26DE, "Velocity Micro, Inc." }, + { 0x26DF, "University of Cambridge" }, + { 0x26E0, "Shenzhen Shixin Digital Co., Ltd." }, + { 0x26E1, "CrucialTec Co., Ltd." }, + { 0x26E2, "Ingenieurbuero Dietzsch und Thiele PartG" }, + { 0x26E3, "SHENZHEN EXCEL DIGITAL TECHNOLOGY CO., LTD." }, + { 0x26E4, "VIZIO, Inc." }, + { 0x26E5, "Shaghal Ltd." }, + { 0x26E6, "ORC Manufacturing Co., Ltd." }, + { 0x26E7, "Fishman" }, + { 0x26E8, "Camgian Microsystems" }, + { 0x26E9, "Lumenergi Inc." }, + { 0x26EA, "OPTOVUE INC." }, + { 0x26EB, "emtrion GmbH" }, + { 0x26EC, "SLE quality engineering GmbH & Co. KG" }, + { 0x26ED, "a.tron3d GmbH" }, + { 0x26EE, "Grimm Audio" }, + { 0x26EF, "TAKEBISHI CORPORATION" }, + { 0x26F0, "EDM Corporation" }, + { 0x26F1, "Fujian LANDI Commercial Equipment Co., Ltd." }, + { 0x26F2, "AUDIS SARL" }, + { 0x26F3, "Raven Systems Design, Inc." }, + { 0x26F4, "RTW GmbH & Co. KG" }, + { 0x26F5, "Morning Star Digital Connector Co., Ltd." }, + { 0x26F6, "Sea-Bird Electronics" }, + { 0x26F7, "BFFT GmbH" }, + { 0x26F8, "Salon Transcripts, Inc." }, + { 0x26F9, "Outstanding Technology Co., Ltd." }, + { 0x26FA, "DAQ SYSTEM Co., Ltd." }, + { 0x26FB, "FLIR Advanced Imaging Systems" }, + { 0x26FC, "Raven Industries" }, + { 0x26FD, "Foot Levelers, Inc." }, + { 0x26FE, "ESPROS Photonics AG" }, + { 0x26FF, "MIA Corporation" }, + { 0x2700, "MITACHI CO., LTD." }, + { 0x2701, "Pro Design Electronic GmbH" }, + { 0x2702, "Hobart GmbH" }, + { 0x2703, "Greenwave Reality Pte. Ltd." }, + { 0x2704, "Unisun Innovation Incorporated" }, + { 0x2705, "CardioGrip Corporation" }, + { 0x2706, "iKey, Ltd." }, + { 0x2707, "Bardac Corporation" }, + { 0x2708, "Audient Limited" }, + { 0x2709, "ZEON CORPORATION" }, + { 0x270A, "Channel Islands Audio" }, + { 0x270B, "MSHeli Srl" }, + { 0x270C, "Inhon Computer Co., Ltd." }, + { 0x270D, "ROSAND Technologies" }, + { 0x270E, "Applied Security Inc." }, + { 0x270F, "Western Digital, HGST" }, + { 0x2710, "Kontron America, Inc." }, + { 0x2711, "ASD Inc." }, + { 0x2712, "US Army Benet Laboratories" }, + { 0x2713, "Datalink Electronics Ltd." }, + { 0x2714, "i'm S.p.A." }, + { 0x2715, "Photron Limited" }, + { 0x2716, "YUEN DA ELECTRONIC PRODUCTS FACTORY" }, + { 0x2717, "Xiaomi Communications Co., Ltd." }, + { 0x2718, "Tamaggo" }, + { 0x2719, "4iiii Innovations Inc." }, + { 0x271A, "KONE Industrial Ltd." }, + { 0x271B, "Tec.to" }, + { 0x271C, "KDDI Technology Corporation" }, + { 0x271D, "Gionee Communication Equipment Co., Ltd. ShenZhen" }, + { 0x271E, "Changzhou Traful Electronic Co., Ltd." }, + { 0x271F, "Shanghai Nufront Electronic Technology Co., Ltd." }, + { 0x2720, "motrona GmbH" }, + { 0x2721, "Germaneers GmbH" }, + { 0x2722, "TRANIT" }, + { 0x2723, "KUK Electronic AG" }, + { 0x2724, "XS Technology, Inc." }, + { 0x2725, "L-3 Applied Signal & Image Technology" }, + { 0x2726, "Universal Electronics Inc. (dba: TVIEW)" }, + { 0x2727, "ANM OPTO LIMITED" }, + { 0x2728, "STX-Med SPRL" }, + { 0x2729, "Regenersis (Glenrothes) Ltd." }, + { 0x272A, "StarLeaf Limited" }, + { 0x272B, "VAT Vakuumventile AG" }, + { 0x272C, "IAR Systems" }, + { 0x272D, "AKAR GAME LTD." }, + { 0x272E, "Teratronik elektronische Systeme GmbH" }, + { 0x272F, "tommis gmbh, Ingenieurburo f. Nachrichtentechnik u. Aut" }, + { 0x2730, "Camozzi spa" }, + { 0x2731, "Pebble Audio Oy" }, + { 0x2732, "Samsung Medison Co., Ltd." }, + { 0x2733, "ShenZhen SunSonny Electronic Technology Co., Ltd." }, + { 0x2734, "Wuhan XinAn LuoJia Technologies Co., Ltd." }, + { 0x2735, "Wilk Elektronik S.A." }, + { 0x2736, "Silver Palm Technologies LLC" }, + { 0x2737, "Blu Controls" }, + { 0x2738, "Bad Rabby Designs" }, + { 0x2739, "BluePacket Communications Co., Ltd." }, + { 0x273A, "Singular Technology Co., Ltd." }, + { 0x273B, "TecScan Systems Inc." }, + { 0x273C, "Etherstack Limited" }, + { 0x273D, "Thrimona Corporation" }, + { 0x273E, "LIFODAS" }, + { 0x273F, "Hughski Limited" }, + { 0x2740, "Apparent Corporation" }, + { 0x2741, "N2 Imaging Systems" }, + { 0x2742, "Organ Recovery Systems, Inc." }, + { 0x2743, "XS Embedded GmbH" }, + { 0x2744, "RIKEN KEIKI NARA MFG. Co., Ltd." }, + { 0x2745, "Unitech Electronics Co., Ltd." }, + { 0x2746, "Shenzhen YishunTai Metal Factory" }, + { 0x2747, "AHA INC. Co., Ltd." }, + { 0x2748, "Stresstech Oy" }, + { 0x2749, "GMV SISTEMAS" }, + { 0x274A, "Qdac Inc." }, + { 0x274B, "Automotive Data Solutions, Inc." }, + { 0x274C, "Atos Worldline" }, + { 0x274D, "FXI Technologies AS" }, + { 0x274E, "VECTRONIC Aerospace GmbH" }, + { 0x274F, "Dacuda AG" }, + { 0x2750, "SafeLine Sweden AB" }, + { 0x2751, "AMI International, Inc." }, + { 0x2752, "miniDSP Ltd." }, + { 0x2753, "Danville Signal Processing, Inc." }, + { 0x2754, "Trapeze Software Group, Inc." }, + { 0x2755, "Cosmic Circuits Pvt. Ltd." }, + { 0x2756, "Victor Hasselblad AB" }, + { 0x2757, "HiteVision Digital Media Technology Co., Ltd." }, + { 0x2758, "MobileEco Co., Ltd." }, + { 0x2759, "Philip Morris Products S.A." }, + { 0x275A, "Vertex Aquaristik GmbH" }, + { 0x275B, "PROPACK" }, + { 0x275C, "NITA, LLC" }, + { 0x275D, "NewSoc Tech Limited" }, + { 0x275E, "Scent Sciences Corporation" }, + { 0x275F, "Vishay Measurements Group, Inc." }, + { 0x2760, "Oxigraf, Inc." }, + { 0x2761, "CAST Navigation LLC" }, + { 0x2762, "FERMAX ELECTRONICA S.A.U." }, + { 0x2763, "PRIMES GmbH" }, + { 0x2764, "Ouman Oy" }, + { 0x2765, "Firstbeat Technologies Ltd." }, + { 0x2766, "LifeScan" }, + { 0x2767, "Cheetah Hi-Tech, Inc." }, + { 0x2768, "DongGuan City Lian Zhi Electronic Technology Co. Ltd." }, + { 0x2769, "SPI ENGINEERING Co., Ltd." }, + { 0x276A, "SUGIYAMA ELECTRIC SYSTEM INC." }, + { 0x276B, "CTI INFORMATION CENTER CO., LTD." }, + { 0x276C, "PROTEI" }, + { 0x276D, "YSTEK Technology Company" }, + { 0x276E, "RGB Lasersysteme GmbH" }, + { 0x276F, "Lightware Visual Engineering" }, + { 0x2771, "TTE Corporation" }, + { 0x2772, "Audio Tuning Vertriebs GmbH" }, + { 0x2773, "HILTI AG" }, + { 0x2774, "Novasina AG" }, + { 0x2775, "Sonardyne International Ltd." }, + { 0x2776, "KFI Trading s.r.l." }, + { 0x2777, "SingTrix LLC" }, + { 0x2778, "Cypher Labs LLC" }, + { 0x2779, "Qualnetics Corporation" }, + { 0x277A, "Occipital, Inc." }, + { 0x277B, "Moxtek, Inc" }, + { 0x277C, "SignalCore, Inc." }, + { 0x277D, "Microcom Corporation" }, + { 0x277E, "Sportable Scoreboards, Inc." }, + { 0x277F, "DongGuan City Shangjie Electronic Co., Ltd." }, + { 0x2780, "M31 Technology Corp." }, + { 0x2781, "Liteconn Co., Ltd." }, + { 0x2782, "TTS Inc." }, + { 0x2783, "Aktina Medical Corp." }, + { 0x2784, "A-One Co., Ltd." }, + { 0x2785, "Mayekawa Mfg. Co., Ltd." }, + { 0x2786, "Switch Science, Incorporation" }, + { 0x2787, "AVTECH Corporation" }, + { 0x2788, "Sanwin (HK) Electronic Technology Co., Ltd." }, + { 0x2789, "Suzhou WEIJU Electronics Technology Co., Ltd." }, + { 0x278A, "MARSHAL Corporation" }, + { 0x278B, "The Rotel Co., Ltd." }, + { 0x278C, "NAGATA ELECTRIC CO., LTD." }, + { 0x278D, "GPSports Systems Pty., Ltd." }, + { 0x278E, "TSS AB" }, + { 0x278F, "Bosch Sicherheitssysteme Engineering GmbH" }, + { 0x2790, "Cobalt Digital, Inc." }, + { 0x2791, "SunTech Medical, Inc." }, + { 0x2792, "SYSTEC Co., Limited" }, + { 0x2793, "i-KAIST" }, + { 0x2794, "SilverPlus, Inc." }, + { 0x2795, "QuantaScope Biotech" }, + { 0x2796, "Zhejiang Wellcom Technology Co., Ltd." }, + { 0x2797, "EUROIMMUN AG" }, + { 0x2798, "Turning Technologies" }, + { 0x2799, "Colorimetry Research, Inc." }, + { 0x279A, "Naim Audio Limited" }, + { 0x279B, "Bluefish Technologies Pty Ltd." }, + { 0x279C, "Advanced Anaesthesia Specialists" }, + { 0x279D, "Towa Electronics Co., Ltd." }, + { 0x279E, "Syntronix Corporation" }, + { 0x279F, "Hiragawa Electronics Industry Co., Ltd." }, + { 0x27A0, "Mondokey Limited" }, + { 0x27A1, "Autoliv Romania S.R.L." }, + { 0x27A2, "T.I.T. ENG CO., LTD." }, + { 0x27A3, "AU Optronics Corporation" }, + { 0x27A4, "Digital Act Inc." }, + { 0x27A5, "Advantest Corporation" }, + { 0x27A6, "iRobot Corporation" }, + { 0x27A7, "Delta Computer Systems, Inc." }, + { 0x27A8, "Square Inc." }, + { 0x27A9, "Global Mixed-mode Technology Inc." }, + { 0x27AA, "Just Connector Kunshan Co., Ltd." }, + { 0x27AB, "Shenzhen Maxmade Technology Co., Ltd." }, + { 0x27AC, "GP Electronics (HK) Limited" }, + { 0x27AD, "PAUL HARTMANN AG" }, + { 0x27AE, "TeleOrbit GmbH" }, + { 0x27AF, "HANNA Instruments, Inc." }, + { 0x27B0, "FOXPRO Inc." }, + { 0x27B1, "UltiMachine" }, + { 0x27B2, "OrthoAccel Technologies, Inc." }, + { 0x27B3, "Secure Systems Limited" }, + { 0x27B4, "Duerkopp Adler AG" }, + { 0x27B5, "J-MEX Inc." }, + { 0x27B6, "TechnoKom Ltd." }, + { 0x27B7, "Fraunhofer IMS" }, + { 0x27B8, "ThingM Corporation" }, + { 0x27B9, "Ziotech Corp" }, + { 0x27BA, "Aoptix Technologies, Inc." }, + { 0x27BB, "Plenom A/S" }, + { 0x27BC, "KeyView" }, + { 0x27BD, "Codethink Limited" }, + { 0x27BE, "InHand Electronics, Inc." }, + { 0x27BF, "Dongguan CPO Electronic Co., Ltd." }, + { 0x27C0, "Cadwell Laboratories, Inc." }, + { 0x27C1, "ARKAMI" }, + { 0x27C2, "ArcBotics LLC" }, + { 0x27C3, "Danfoss Turbocor Compressors Inc." }, + { 0x27C4, "KRYPTUS" }, + { 0x27C5, "SRT Marine Technology Limited" }, + { 0x27C6, "Shenzhen Huiding Technology Co. Ltd." }, + { 0x27C7, "TransluSense, LLC" }, + { 0x27C8, "Rigaku Corporation" }, + { 0x27C9, "ElaraTek LTD." }, + { 0x27CA, "JayBird LLC" }, + { 0x27CB, "ANXA Limited Hong Kong" }, + { 0x27CC, "GHL Matthias Gross GmbH & Co. KG" }, + { 0x27CD, "GHEO SA" }, + { 0x27CE, "Double Power Technology Inc." }, + { 0x27CF, "Weidmueller Interface GmbH & Co. KG" }, + { 0x27D0, "Traxon Technologies Europe GmbH" }, + { 0x27D1, "Angelbird Technologies GmbH" }, + { 0x27D2, "EURONOVATE SA" }, + { 0x27D3, "PRECIA MOLEN" }, + { 0x27D4, "Blackstar Amplification Ltd." }, + { 0x27D5, "BSkyB LTD." }, + { 0x27D6, "T3 Innovation" }, + { 0x27D7, "Senova Systems, Inc." }, + { 0x27D8, "Patriot Memory" }, + { 0x27D9, "Gallagher Group Limited" }, + { 0x27DA, "S Net Media Inc." }, + { 0x27DB, "Hiitop Technology Limited" }, + { 0x27DC, "Tennant Company" }, + { 0x27DD, "Shenzhen MinDe Electronics Technology Ltd." }, + { 0x27DE, "Newtec Cy" }, + { 0x27DF, "Charles Novacroft Direct Limited" }, + { 0x27E0, "Stelulu Technology" }, + { 0x27E1, "TRX Systems, Inc." }, + { 0x27E2, "Natus Medical Incorproated" }, + { 0x27E3, "Chemyx Inc." }, + { 0x27E4, "Easybotics LLC" }, + { 0x27E5, "Shiroshita Industrial Co., Ltd." }, + { 0x27E6, "SENECA srl" }, + { 0x27E7, "AVIWEST" }, + { 0x27E8, "takwak GmbH" }, + { 0x27E9, "Soeks Limited" }, + { 0x27EA, "Goldmund International" }, + { 0x27EB, "ACCUCOMM, INC." }, + { 0x27EC, "SEETECH CO., LTD." }, + { 0x27ED, "Tescom-Emerson Process Management" }, + { 0x27EE, "DashLogic Inc." }, + { 0x27EF, "TAIYO SEIKI CO., LTD." }, + { 0x27F0, "DITECT Corporation" }, + { 0x27F1, "VERTU Corporation Limited" }, + { 0x27F2, "Softnautics Private Limited" }, + { 0x27F3, "Indutherm Erwaermungsanlagen GmbH" }, + { 0x27F4, "LEGIC Identsystems Ltd." }, + { 0x27F5, "Relume Technologies, Inc." }, + { 0x27F6, "Advanced Simulation Technology Inc." }, + { 0x27F7, "Wyred 4 Sound" }, + { 0x27F8, "Wikipad, Inc." }, + { 0x27F9, "MIDAS Elektronik GmbH" }, + { 0x27FA, "Afag Automation AG" }, + { 0x27FB, "Barclays" }, + { 0x27FC, "CAREL SPA" }, + { 0x27FD, "GI Therapies Pty Ltd." }, + { 0x27FE, "DONGGUAN Rakecorp Co., Ltd." }, + { 0x27FF, "Cashway Technology Co., Ltd." }, + { 0x2800, "iluminage, Inc." }, + { 0x2801, "Pear Sports LLC" }, + { 0x2802, "Moixa Technology" }, + { 0x2803, "StarLine LLC" }, + { 0x2804, "4MOD Technology" }, + { 0x2805, "Shenzhen N-Pass Mobile Technology, Ltd." }, + { 0x2806, "RF DataTech" }, + { 0x2807, "Elliptic Laboratories AS" }, + { 0x2808, "FocalTech Systems, Ltd." }, + { 0x2809, "Sept Co., Ltd." }, + { 0x280A, "Culti Co., Ltd." }, + { 0x280B, "Dukane Corporation" }, + { 0x280C, "Linera" }, + { 0x280D, "Ai Electronic Industry Co., Ltd." }, + { 0x280E, "Leaf Imaging Ltd." }, + { 0x280F, "MBit Wireless, Inc." }, + { 0x2810, "Aphex, LLC" }, + { 0x2811, "DigiTalks INC." }, + { 0x2812, "Bridge Semiconductor Corp." }, + { 0x2813, "Brookfield Engineering Laboratories Inc." }, + { 0x2814, "OOO SMS-Soft" }, + { 0x2815, "KING TSUSHIN KOGYO CO., LTD." }, + { 0x2816, "Harvard Photonix" }, + { 0x2817, "Test Equipment Plus" }, + { 0x2818, "Codex Digital Limited" }, + { 0x2819, "MESSRING Systembau MSG GmbH" }, + { 0x281A, "SWAC Automation Consult GmbH" }, + { 0x281B, "HiES Tech s.r.o." }, + { 0x281C, "Presidium Instruments Pte. Ltd." }, + { 0x281D, "AISIN AW CO., LTD." }, + { 0x281E, "Symphodia Phil" }, + { 0x281F, "Motion Control, Inc." }, + { 0x2820, "Sanovas" }, + { 0x2821, "Aclima Inc." }, + { 0x2822, "REFLEXdigital" }, + { 0x2823, "Dongguan Jiumutong Industry Co., Ltd." }, + { 0x2824, "Vollsun Ltd." }, + { 0x2825, "Baumer Optronic GmbH" }, + { 0x2826, "BSH Bosch und Siemens Hausgerate GmbH" }, + { 0x2827, "DIGITTRADE GmbH" }, + { 0x2828, "SAPHYMO" }, + { 0x2829, "Scanomat A/S" }, + { 0x282A, "REDL GmbH" }, + { 0x282B, "Aevoe Inc." }, + { 0x282C, "Reichert, Inc." }, + { 0x282D, "Aeromax Technology Co., Ltd." }, + { 0x282E, "Vectawave Technology Ltd." }, + { 0x282F, "SANKEN ELECTRIC CO., LTD." }, + { 0x2830, "GD-Broadband" }, + { 0x2831, "Power Integrations" }, + { 0x2832, "Applied Research Associates" }, + { 0x2833, "Oculus VR LLC" }, + { 0x2834, "JM Concept" }, + { 0x2835, "SEIDENSHA ELECTRONICS Co., Ltd." }, + { 0x2836, "OUYA Inc." }, + { 0x2837, "Tunstall Healthcare (UK) Ltd." }, + { 0x2838, "Ontorix GmbH" }, + { 0x2839, "Grass Elektronik" }, + { 0x283A, "HIKe Mobile Co., Ltd." }, + { 0x283B, "Cellon Communications Technology (Shenzhen) Co., Ltd." }, + { 0x283C, "HIGH TEK HARNESS ENTERPRISE CO., LTD." }, + { 0x283D, "SigNET (AC) Ltd." }, + { 0x283E, "DECATHLON SA" }, + { 0x283F, "Elprosys Sp. Z.o.o." }, + { 0x2840, "Taiwan Carol Electronics Co., Ltd." }, + { 0x2841, "Artvision Technologies Inc." }, + { 0x2842, "RobotGroup" }, + { 0x2843, "SyncMOS Technologies International, Inc." }, + { 0x2844, "ELSIST Srl" }, + { 0x2845, "Systec Designs BV" }, + { 0x2846, "ATRON electronic GmbH" }, + { 0x2847, "TMG TE GmbH" }, + { 0x2848, "Sentons USA, Inc." }, + { 0x2849, "Astronics Advanced Electronic Systems Corp." }, + { 0x284A, "Yangtze Optical Fibre and Cable Company Ltd." }, + { 0x284B, "Leadingui Co., Ltd." }, + { 0x284C, "Full in Hope Co., Ltd." }, + { 0x284D, "Qltouch Tech Co., Ltd." }, + { 0x284E, "Flysky RC Model Co., Ltd." }, + { 0x284F, "ANTLIA SA" }, + { 0x2850, "Intellectual Property Group SA" }, + { 0x2851, "RETIA, a.s." }, + { 0x2852, "Virtual Console, LLC" }, + { 0x2853, "Ralston Instruments" }, + { 0x2854, "Great River Technology" }, + { 0x2855, "System Dimensions, Inc." }, + { 0x2856, "Thales Alenia Space - Italia" }, + { 0x2857, "Skardin Industrial Corporation" }, + { 0x2858, "PT Doo Won Precision Indonesia" }, + { 0x2859, "Viconn Technology (HK) Co., Ltd." }, + { 0x285A, "AiM Touch Technology Co., Ltd." }, + { 0x285B, "HARDWARE & SOFTWARE TECHNOLOGY CO., LTD." }, + { 0x285C, "URMET S.p.a." }, + { 0x285D, "Alarm.com, Inc." }, + { 0x285E, "Occam Robotics" }, + { 0x285F, "CyWee Group Limited" }, + { 0x2860, "WISYCOM UNIPERSONALE s.r.l." }, + { 0x2861, "Pacific Image Electronics Co., Ltd." }, + { 0x2862, "DeVilbiss Healthcare LLC" }, + { 0x2863, "BIOMATIQUES IDENTIFICATION SOLUTIONS PRIVATE LIMITED" }, + { 0x2864, "Wenngo Inc." }, + { 0x2865, "VIKING GmbH" }, + { 0x2866, "SLOW CONTROL" }, + { 0x2867, "DASCOM" }, + { 0x2868, "Chakra Energetics Ltd." }, + { 0x2869, "Comfort Audio AB" }, + { 0x286A, "Dipl. - Ing. H. Horstmann GmbH" }, + { 0x286B, "STANEO SAS" }, + { 0x286C, "Atest-Gaz A. M. Pachole sp. j." }, + { 0x286D, "Production Resource Group, LLC" }, + { 0x286E, "Geosense Inc." }, + { 0x286F, "Bretford Manufacturing Inc." }, + { 0x2870, "Typhoon HIL, Inc." }, + { 0x2871, "BYK-Gardner GmbH" }, + { 0x2872, "Brite Semiconductor (Shanghai) Corporation" }, + { 0x2873, "Spire Payments Holdings S.a.r.l." }, + { 0x2874, "Dexter Research Center, Inc." }, + { 0x2875, "nVideon, Inc." }, + { 0x2876, "Safety Innovations, Inc." }, + { 0x2877, "BrightSign LLC" }, + { 0x2878, "Cabletech Electronics (Hong Kong) Co., Ltd." }, + { 0x2879, "Rancore Technologies Private Limited" }, + { 0x287A, "Shenzhen Bojuxing Industrial Development Co., Ltd." }, + { 0x287B, "Pro-Tech" }, + { 0x287C, "Special Recording Systems Ltd." }, + { 0x287D, "Pettersson Elektronik AB" }, + { 0x287E, "Silicon Designs, Inc." }, + { 0x287F, "Beijing Jinke XinAn Technology Co., Ltd." }, + { 0x2880, "Black Diamond Video" }, + { 0x2881, "DX Antenna Co., Ltd." }, + { 0x2882, "GCOMM CORPORATION" }, + { 0x2883, "abatec group AG" }, + { 0x2884, "Bor" }, + { 0x2885, "Quantec SA" }, + { 0x2886, "Seeed Technology Co., Ltd." }, + { 0x2887, "Specwerkz" }, + { 0x2888, "VEX Robotics, Inc." }, + { 0x2889, "TrueVision Systems, Inc." }, + { 0x288A, "LEXIBOOK LIMITED" }, + { 0x288B, "Hierstar (Suzhou)" }, + { 0x288C, "Moswell Co., Ltd." }, + { 0x288D, "Centre for Development of Advanced Computing (C-DAC)" }, + { 0x288E, "mce-systems Ltd." }, + { 0x288F, "Voxx Accessories Corp." }, + { 0x2890, "Teknic, Inc." }, + { 0x2891, "Flytec AG" }, + { 0x2892, "NAVIgard" }, + { 0x2893, "LEVEL Ltd." }, + { 0x2894, "Hovercam" }, + { 0x2895, "INIM Electronics s.r.l." }, + { 0x2896, "TTAF Elektronik Sanayi ve Ticaret Ltd. Sti." }, + { 0x2897, "SDJ Technologies, Inc." }, + { 0x2898, "Accumetrics Associates, Inc." }, + { 0x2899, "Toptronic Industrial Co., Ltd." }, + { 0x289A, "Scan-Sense A.S." }, + { 0x289B, "DRACAL Technologies Inc." }, + { 0x289C, "TLS Corp." }, + { 0x289D, "Tyrian Systems, Inc." }, + { 0x289E, "Esselte Leitz GmbH & Co. KG" }, + { 0x289F, "inoage GmbH" }, + { 0x28A0, "I-CUBE TECHNOLOGY Co., Ltd." }, + { 0x28A1, "AVEST-SYSTEMS Private Unitary Enterprise" }, + { 0x28A2, "Meadowlark Optics Incorporated" }, + { 0x28A3, "SensoMotoric Instruments GmbH" }, + { 0x28A4, "Objective Solutions Sweden AB" }, + { 0x28A5, "TCS John Huxley" }, + { 0x28A6, "E-SEEK Inc." }, + { 0x28A7, "Hugo Brennenstuhl GmbH & Co. KG" }, + { 0x28A8, "AT Sciences, LLC" }, + { 0x28A9, "Alpha Technologies" }, + { 0x28AA, "Realta Entertainment Group" }, + { 0x28AB, "Navigil Ltd." }, + { 0x28AC, "euroBRAILLE" }, + { 0x28AD, "iDTRONIC GmbH" }, + { 0x28AE, "Zynaptic Limited" }, + { 0x28AF, "Sharkbay Technologies Pte. Ltd." }, + { 0x28B0, "PMC - Sierra" }, + { 0x28B1, "EcoTech, Inc." }, + { 0x28B2, "Siemens Infrastructure & Cities" }, + { 0x28B3, "Profoto AB" }, + { 0x28B4, "TOACK Corporation" }, + { 0x28B5, "Solacom Inc." }, + { 0x28B6, "Alcohol Countermeasure Systems Corp." }, + { 0x28B7, "Pleora Technologies Inc." }, + { 0x28B8, "Swiss Authentication Research & Development AG" }, + { 0x28B9, "Kapsch TrafficCom AB" }, + { 0x28BA, "RSscan International NV" }, + { 0x28BB, "ICP Systems b.v." }, + { 0x28BC, "Cyplex Corporation" }, + { 0x28BD, "GuangZhou Ugee Computer Technology Co., Ltd." }, + { 0x28BE, "GMG TECH. Co., Ltd." }, + { 0x28BF, "Vitetech Int'l Co., Ltd." }, + { 0x28C0, "SCVNGR, Inc." }, + { 0x28C1, "DOMMEL GmbH" }, + { 0x28C2, "Tapko Technologies GmbH" }, + { 0x28C3, "MITSUBISHI ELECTRIC SYSTEM & SERVICE CO., LTD." }, + { 0x28C4, "GALA, Inc." }, + { 0x28C5, "ShenZhen Innovate-link Precision Hardware Co., Ltd." }, + { 0x28C6, "FASTLITE" }, + { 0x28C7, "Ultimaker BV" }, + { 0x28C8, "ULTRACHIP Inc." }, + { 0x28C9, "DongGuan City DHE Wire & Cable Co., Ltd." }, + { 0x28CA, "NUMATA Corporation" }, + { 0x28CB, "GO engineering GmbH" }, + { 0x28CC, "MIWA ELECTRIC CO., LTD." }, + { 0x28CD, "SMARTMATIC INTERNATIONAL CORP." }, + { 0x28CE, "Changzhou Shi Wujin Miqi East Electronic Co., Ltd." }, + { 0x28CF, "Asiatelco Technologies Co." }, + { 0x28D0, "Stryker Corporation" }, + { 0x28D1, "Technomedica Co., Ltd." }, + { 0x28D2, "FTK Corporation" }, + { 0x28D3, "Golden Transmart International Co., Ltd." }, + { 0x28D4, "DEVIALET SAS" }, + { 0x28D5, "Vicor Corporation" }, + { 0x28D6, "Electrogamez USA Inc." }, + { 0x28D7, "Tekron International" }, + { 0x28D8, "Panda Ocean Inc." }, + { 0x28D9, "Shenzhen Yoshuo Precision Components Co., Ltd." }, + { 0x28DA, "G.SKILL Int'l Enterprice Co., Ltd." }, + { 0x28DB, "Konftel AB" }, + { 0x28DC, "Power Electronics International, Inc." }, + { 0x28DD, "AIWA COMPANY LTD. - Love Harmony (LH)" }, + { 0x28DE, "Valve Corporation" }, + { 0x28DF, "EMBED-IT" }, + { 0x28E0, "PRASIMAX" }, + { 0x28E1, "Shenzhen iSolution Technologies Co., Ltd." }, + { 0x28E2, "Surplus Electronic Technology Co., Ltd." }, + { 0x28E3, "Apollo Electrical Technology Co., Ltd." }, + { 0x28E4, "RKS, Inc." }, + { 0x28E5, "MEP TECH" }, + { 0x28E6, "BIAMP SYSTEMS" }, + { 0x28E7, "Glyph Production Technologies" }, + { 0x28E8, "Jefferson Audio Video Systems, Inc." }, + { 0x28E9, "GigaDevice Semiconductor (Beijing) Inc." }, + { 0x28EA, "Dongguan Vast Electronics Co.,Ltd" }, + { 0x28EB, "SHEN ZHEN SHI YUAN AI HARDWARE ELECTRONIC CO., LTD." }, + { 0x28EC, "Transcom Instruments Co., Ltd." }, + { 0x28ED, "Shenzhen AraTek Biometrics Technology Co., Ltd." }, + { 0x28EE, "China Mobile Group Device Co., Ltd." }, + { 0x28EF, "SEEFRONT GmbH" }, + { 0x28F0, "Elcus Electronic Company JSC" }, + { 0x28F1, "Leddartech Inc." }, + { 0x28F2, "Applied Vision Corporation" }, + { 0x28F3, "Clover Network" }, + { 0x28F4, "Sonoma Wire Works" }, + { 0x28F5, "Electrolux Laundry Systems Sweden AB" }, + { 0x28F6, "SERVOMEX Group Ltd." }, + { 0x28F7, "ANYWIRE CORPORATION" }, + { 0x28F8, "VTECH Technology Corp." }, + { 0x28F9, "Comcraft" }, + { 0x28FA, "iProtoXi Oy" }, + { 0x28FB, "Shin Hwa Contech Co., Ltd." }, + { 0x28FC, "Shandong Sinochiptp Electronic Technology Co., Ltd." }, + { 0x28FD, "Wolfson Microelectronics Plc." }, + { 0x28FE, "Marquardt Mechatronik GmbH" }, + { 0x28FF, "MIRAENANOTECH" }, + { 0x2900, "Labsphere" }, + { 0x2901, "Tolomatic Inc." }, + { 0x2902, "Woodward Inc." }, + { 0x2903, "Lightspeed Aviation" }, + { 0x2904, "Charon Technologies LLC" }, + { 0x2905, "iDea USA Products Inc." }, + { 0x2906, "Masimo Corporation" }, + { 0x2907, "Mimetics Inc." }, + { 0x2908, "Shenzhen Sen5 Technology Co., Ltd." }, + { 0x2909, "Active Mind Technology" }, + { 0x290A, "Electronic Systems Technology, Inc." }, + { 0x290B, "Beats Electronics LLC" }, + { 0x290C, "R. Hamilton & Co. Ltd." }, + { 0x290D, "IBCONN Technologies (Shenzhen) Co., Ltd." }, + { 0x290E, "Fugoo Inc." }, + { 0x290F, "AFL Noyes" }, + { 0x2910, "Cree, Inc." }, + { 0x2911, "Penetek, Inc." }, + { 0x2912, "Management Company ATOL Ltd." }, + { 0x2913, "Teladin Co., Ltd." }, + { 0x2914, "Kent Displays Inc." }, + { 0x2915, "Sage Microelectronics Corp." }, + { 0x2916, "Yota Devices Ltd." }, + { 0x2917, "Pan Xin Precision Electronics Co., Ltd." }, + { 0x2918, "Gigatronik Ingolstadt GmbH" }, + { 0x2919, "GE Analytical Instruments" }, + { 0x291A, "Anker Technology Co., Limited" }, + { 0x291B, "LONTEX PIOTR LONDZIN" }, + { 0x291C, "KEISOKUKI CENTER CO., LTD." }, + { 0x291D, "Research & Development Center ELVEES OJSC" }, + { 0x291E, "Shanghai DynamiCode Company Ltd." }, + { 0x291F, "CBN Inc." }, + { 0x2920, "Fiberplex Technologies, LLC" }, + { 0x2921, "BiovenTus, LLC" }, + { 0x2922, "Dongguan Digi-in Digital Technology Co., Ltd." }, + { 0x2923, "Vprime" }, + { 0x2924, "Chinon Corporation" }, + { 0x2925, "Flight System Consulting Inc." }, + { 0x2926, "Wildlife Acoustics, Inc." }, + { 0x2927, "BF1 Systems Ltd." }, + { 0x2928, "Dongguan Sineng Electronic Technology Co., Ltd." }, + { 0x2929, "Shenzhen Taishan Online Technology Co., Ltd." }, + { 0x292A, "T1Visions, Inc." }, + { 0x292B, "Precision Audio Device Lab Limited" }, + { 0x292C, "GENUSION, Inc." }, + { 0x292D, "Wellitec Development Limited" }, + { 0x292E, "HOYA Service Corporation" }, + { 0x292F, "Nanotec Electronic GmbH & Co. KG" }, + { 0x2930, "Ineda Systems Inc." }, + { 0x2931, "Jolla Ltd." }, + { 0x2932, "Peraso Technologies, Inc." }, + { 0x2933, "IEI Integration Corp." }, + { 0x2934, "CETA Testsysteme GmbH" }, + { 0x2935, "Nanjing Magewell Electronics Co., Ltd." }, + { 0x2936, "LEAP Motion" }, + { 0x2937, "Tmax Digital Inc." }, + { 0x2938, "Aides Technology Co., Ltd." }, + { 0x2939, "Zaber Technologies Inc." }, + { 0x293A, "The SmarTV Company" }, + { 0x293B, "Lucent Medical Systems, Inc." }, + { 0x293C, "Comcast" }, + { 0x293D, "Medicatec Inc." }, + { 0x293E, "EIDEN Co., Ltd." }, + { 0x293F, "Gan Zhou DPT-Technology Co., Ltd." }, + { 0x2940, "Shenzhen Yiwanda Electronics Co., Ltd." }, + { 0x2941, "Sanofi-Aventis Deutschland GmbH" }, + { 0x2942, "SoftLab - NSK" }, + { 0x2943, "ZAGG Inc." }, + { 0x2944, "RailComm" }, + { 0x2945, "Matrix Design Group, LLC" }, + { 0x2946, "OnAsset Intelligence Inc." }, + { 0x2947, "KAPELSE" }, + { 0x2948, "Access Network Technology Limited" }, + { 0x2949, "Shenzhen JSR Technology Co., Ltd." }, + { 0x294A, "Shenzhen Xinguodu Technology Co., Ltd." }, + { 0x294B, "snakebyte Asia Ltd." }, + { 0x294C, "Terminus Circuits Pvt Ltd." }, + { 0x294D, "Cellwise Holding Co., Ltd." }, + { 0x294E, "SHIH HUA TECHNOLOGY LTD." }, + { 0x294F, "Dollar Connection Ltd." }, + { 0x2950, "Resource One Inc." }, + { 0x2951, "Raytrix GmbH" }, + { 0x2952, "Seba Dynatronic GmbH" }, + { 0x2953, "Axes System sp. Z.o.o." }, + { 0x2954, "Human Design Medical, LLC" }, + { 0x2955, "Baidu Online Network Technology (Beijing) Co., Ltd." }, + { 0x2956, "Alfatest Ind. e Com. Produtos Eletronicos S/A" }, + { 0x2957, "OBSIDIAN RESEARCH CORPORATION" }, + { 0x2958, "Eleven Engineering Inc." }, + { 0x2959, "Inuitive" }, + { 0x295A, "ENERMAX TECHNOLOGY CORPORATION" }, + { 0x295B, "eflow Inc." }, + { 0x295C, "MediaNet M. Hermsen" }, + { 0x295D, "Positive Grid" }, + { 0x295E, "Britelite Enterprises" }, + { 0x295F, "Tecvox Connectivity, LLC" }, + { 0x2960, "Power Probe, Inc." }, + { 0x2961, "Miselu Inc." }, + { 0x2962, "Wilocity Ltd." }, + { 0x2963, "BIO-key International, Inc." }, + { 0x2964, "Kintech Co., Ltd." }, + { 0x2965, "Kortek" }, + { 0x2966, "Schatz AG" }, + { 0x2967, "St. Andrews Instrumentation Ltd." }, + { 0x2968, "Phoenix Avionics Systems, LLC" }, + { 0x2969, "Sumix" }, + { 0x296A, "Nitero, Inc." }, + { 0x296B, "Xacti Corporation" }, + { 0x296C, "KNC ONE GmbH - Research & Development" }, + { 0x296D, "Azuri Technologies Ltd" }, + { 0x296E, "LG CNS Co., Ltd." }, + { 0x296F, "Broadsound Corporation" }, + { 0x2970, "MERIDIAN SOFTWARE SYSTEMS LIMITED" }, + { 0x2971, "Ory Laboratory Ltd." }, + { 0x2972, "FiiO Electronics Technology Co., Ltd." }, + { 0x2973, "Wild Elektronik & Kunststoff GmbH & Co. KG" }, + { 0x2974, "Printrbot, Inc." }, + { 0x2975, "MPC Research Ltd." }, + { 0x2976, "COMOTA Co., Ltd." }, + { 0x2977, "Shenzhen Zowee Technology Co., Ltd." }, + { 0x2978, "Imaging Solutions Group of NY, Inc." }, + { 0x2979, "Williams Sound, LLC" }, + { 0x297A, "Innovative Developments LLC" }, + { 0x297B, "ALKERIA s.r.l." }, + { 0x297C, "HashFast Technologies LLC" }, + { 0x297D, "Krypton Solutions" }, + { 0x297E, "Shenzhen DTEC Electronic Technology Co., Ltd." }, + { 0x297F, "Emerging Technology (Holdings) Ltd." }, + { 0x2980, "CiDELEC" }, + { 0x2981, "Elektron Technology UK Limited" }, + { 0x2982, "Ableton AG" }, + { 0x2983, "Coyote System" }, + { 0x2984, "Glensound Electronics Ltd." }, + { 0x2985, "DUALO" }, + { 0x2986, "Rapt Touch (Ireland) Ltd." }, + { 0x2987, "Lyve Minds, Inc." }, + { 0x2988, "3D Systems Corporation" }, + { 0x2989, "Nanjing Fujitsu Electronics Information Technology Co., Ltd" }, + { 0x298A, "Singeen Electronics Technologies (Dongguan) Co., Ltd." }, + { 0x298B, "Hanil ProTech" }, + { 0x298C, "GL Solutions Inc." }, + { 0x298D, "NEXT Biometrics" }, + { 0x298E, "Delta Controls" }, + { 0x298F, "NIHON DENON CO., LTD." }, + { 0x2990, "SHIGA MEC Company Limited" }, + { 0x2991, "Orbitsound Ltd" }, + { 0x2992, "Lantos Technologies, Inc." }, + { 0x2993, "ADPlaus Technology Limited" }, + { 0x2995, "Resodyn Corporation" }, + { 0x2996, "Delphi Data Connectivity" }, + { 0x2997, "Inogeni Inc." }, + { 0x2998, "EOS S.r.l." }, + { 0x2999, "Fourtec Technologies Ltd." }, + { 0x299A, "Ogi Systems Ltd. by A.A. Lab Systems" }, + { 0x299B, "Ohio Semitronics, Inc." }, + { 0x299C, "WINTOUCH Co., Ltd." }, + { 0x299D, "Horst Platz Beratungs und Vertriebs GmbH" }, + { 0x299E, "TRE INNOVATORER AB" }, + { 0x299F, "MESTEC Technologies" }, + { 0x29A0, "Bang & Olufsen Medicom A/S" }, + { 0x29A1, "Union Electric Plug & Connector Corp." }, + { 0x29A2, "MUTEC GmbH" }, + { 0x29A3, "Cista System Corporation" }, + { 0x29A4, "Source Audio LLC" }, + { 0x29A5, "Harbo Entertainment LLC" }, + { 0x29A6, "Chiyoda Electronics Co., Ltd." }, + { 0x29A7, "Tekinvest Holding Ltd." }, + { 0x29A8, "Lester Electrical" }, + { 0x29A9, "Smartisan Technology Co., Ltd." }, + { 0x29AA, "Zivix, LLC" }, + { 0x29AB, "The Eye Tribe" }, + { 0x29AC, "Cool Control (S.D.) Ltd." }, + { 0x29AD, "Quest Engineering & Development, Inc." }, + { 0x29AE, "Japan Lifeline Co., Ltd." }, + { 0x29AF, "Zhongshan K-Mate General Electronics Co., Ltd." }, + { 0x29B0, "Diebold Financial Equipment Co., Ltd." }, + { 0x29B1, "Dongguan Haitai Precision Electronic Technology Co Ltd" }, + { 0x29B2, "Canova Tech" }, + { 0x29B3, "Dowling Software" }, + { 0x29B4, "Shenzhen Carbetter Technology Co., Ltd." }, + { 0x29B5, "PN Devices Int'l Limited" }, + { 0x29B6, "Gowin Technology International Holdings Limited" }, + { 0x29B7, "X.O.Ware, Inc." }, + { 0x29B8, "Hawk-Owl Systems" }, + { 0x29B9, "S.I.C.E.S. S.r.l." }, + { 0x29BA, "TOPTICA Photonics AG" }, + { 0x29BB, "SMUFS Biometric Solutions" }, + { 0x29BC, "IMBEL - Industria de Material Belico do Brasil" }, + { 0x29BD, "Silicon Works" }, + { 0x29BE, "Mamiya-OP NEQUOS Co., Ltd." }, + { 0x29BF, "BalanceMaster, Inc." }, + { 0x29C0, "Canopy Co." }, + { 0x29C1, "TazTag" }, + { 0x29C2, "Lewitt GmbH" }, + { 0x29C3, "Noviga" }, + { 0x29C4, "SoundHawk Corporation" }, + { 0x29C5, "Peachtree Audio" }, + { 0x29C6, "Shenzhen Jiali Asia Industry Co., Ltd." }, + { 0x29C7, "HANRICO ANFU ELECTRONICS CO., LTD." }, + { 0x29C8, "Samil CTS Co., Ltd." }, + { 0x29C9, "BEEVC-Electronic Systems, LDA" }, + { 0x29CA, "Cross the Road Electronics, LLC" }, + { 0x29CB, "Xima Software" }, + { 0x29CC, "Kodak Alaris" }, + { 0x29CD, "Carotron, Inc." }, + { 0x29CE, "JGR Optics Inc." }, + { 0x29CF, "Richtek Technology Corporation" }, + { 0x29D0, "ShenZhen Synergy Digital Co., Ltd." }, + { 0x29D1, "Binatone Electronics Int. Ltd." }, + { 0x29D2, "Crypto Control Limited" }, + { 0x29D3, "HESS Cash Systems GmbH & Co. KG" }, + { 0x29D4, "Twin Development S.A." }, + { 0x29D5, "Alibaba Cloud Computing Ltd." }, + { 0x29D6, "Ara Hub Design Inc." }, + { 0x29D7, "Suritel" }, + { 0x29D8, "Vigor Electric Corporation" }, + { 0x29D9, "San-Eisha, Ltd." }, + { 0x29DA, "The Modal Shop" }, + { 0x29DB, "Shenzhen iBoard Technology Co., Ltd." }, + { 0x29DC, "TOHO Electronics Inc." }, + { 0x29DD, "Embedded Micro" }, + { 0x29DE, "Korea Electric Terminal Co., Ltd." }, + { 0x29DF, "SMIT(HK) Limited" }, + { 0x29E0, "ARCCRA Technology Co., Ltd." }, + { 0x29E1, "TOSEI ENGINEERING CORP." }, + { 0x29E2, "Huatune Technology (Shanghai) Co., Ltd." }, + { 0x29E3, "Bio-Medical Research" }, + { 0x29E4, "Prestigio Plaza Ltd." }, + { 0x29E5, "Dongguan Kechenda Electronic Technology Co., Ltd." }, + { 0x29E6, "Fengshun Peiying Electro-Acoustic Co., Ltd." }, + { 0x29E7, "Brunel University" }, + { 0x29E8, "4Links Limited" }, + { 0x29E9, "Quanttus, Inc." }, + { 0x29EA, "Kinesis Corporation" }, + { 0x29EB, "Virtuix Inc." }, + { 0x29EC, "R. Stahl" }, + { 0x29ED, "CERA" }, + { 0x29EE, "Pinnacle Response Ltd." }, + { 0x29EF, "GamePop Inc." }, + { 0x29F0, "WirePath Home Systems dba Snap AV" }, + { 0x29F1, "0XF8 Limited" }, + { 0x29F2, "RECO Gesellschaft fur Industriefilterregelung mbH" }, + { 0x29F3, "Resonessence Labs" }, + { 0x29F4, "NeuroSky, Inc." }, + { 0x29F5, "AirNetix, LLC" }, + { 0x29F6, "Evoko Unlimited AB" }, + { 0x29F7, "Matica Technologies AG" }, + { 0x29F8, "MD ELEKTRONIK GmbH" }, + { 0x29F9, "EnerLab, LLC" }, + { 0x29FA, "LogTag Recorders Ltd." }, + { 0x29FB, "JSK Co., Ltd." }, + { 0x29FC, "Namsung Corporation" }, + { 0x29FD, "Bad Elf, LLC" }, + { 0x29FE, "GEO Semiconductor Inc." }, + { 0x29FF, "Thalmic Labs Inc." }, + { 0x2A00, "NTLab" }, + { 0x2A01, "Amuseway Korea Co., Ltd." }, + { 0x2A02, "OJI LTD." }, + { 0x2A03, "dog hunter AG" }, + { 0x2A04, "Microtech Laboratory Inc." }, + { 0x2A05, "EXO LABS INC." }, + { 0x2A06, "HiFiMAN Electronics" }, + { 0x2A07, "ise GmbH" }, + { 0x2A08, "Marshall Amplification PLC" }, + { 0x2A09, "cytonome" }, + { 0x2A0A, "All Star International Trading" }, + { 0x2A0B, "Leopard Imaging Inc." }, + { 0x2A0C, "MultiSoft Systems Ltd." }, + { 0x2A0D, "ADVANCE Co., Ltd." }, + { 0x2A0E, "Shenzhen DreamSource Technology Co., Ltd." }, + { 0x2A0F, "Shenzhen Giec Electronics Co., Ltd." }, + { 0x2A10, "Powerway Electronics Co., Ltd." }, + { 0x2A11, "P3 Ingenieurgesellschaft mbH" }, + { 0x2A12, "Vreo Limited" }, + { 0x2A13, "Grabba International" }, + { 0x2A14, "Kanex" }, + { 0x2A15, "navAero AB" }, + { 0x2A16, "Hella Gutmann Solutions" }, + { 0x2A17, "UDEA Electronic Ltd." }, + { 0x2A18, "King Abdulaziz City for Science and Technology" }, + { 0x2A19, "Numato Systems Pvt. Ltd." }, + { 0x2A1A, "ASCOT GmbH" }, + { 0x2A1B, "DRS Power & Control Technologies, Inc." }, + { 0x2A1C, "ThinkWrite" }, + { 0x2A1D, "Oxford Nanopore Technologies" }, + { 0x2A1E, "Obsidian Technology" }, + { 0x2A1F, "Lucent Trans Electronics Co., Ltd." }, + { 0x2A20, "GUOGUANG GROUP CO., LTD." }, + { 0x2A21, "ROL Ergo AB" }, + { 0x2A22, "CDEX CORP." }, + { 0x2A23, "Artec Design" }, + { 0x2A24, "CNPLUS" }, + { 0x2A25, "Fourstar Group" }, + { 0x2A26, "Tragant International Co., Ltd." }, + { 0x2A27, "DongGuan LianGang Optoelectronic Technology Co., Ltd." }, + { 0x2A28, "Higbie, LLC dba kinetuex" }, + { 0x2A29, "PayPal, Inc." }, + { 0x2A2A, "TARGAMITE LLC" }, + { 0x2A2B, "NooElec Inc." }, + { 0x2A2C, "Bkav Corporation" }, + { 0x2A2D, "Atrust Computer Corp." }, + { 0x2A2E, "VIA Alliance Semiconductor Co., Ltd." }, + { 0x2A2F, "BSUN Electronics Co., Ltd." }, + { 0x2A30, "KORR Medical Technologies" }, + { 0x2A31, "Sandia National Laboratories" }, + { 0x2A32, "Centre for Advanced Transport Engineering and Research" }, + { 0x2A33, "NTT R&D Laboratories" }, + { 0x2A34, "KT System, Inc." }, + { 0x2A35, "Quatius Limited" }, + { 0x2A36, "MOS Co., Ltd." }, + { 0x2A37, "RTD Embedded Technologies, Inc." }, + { 0x2A38, "Electronic Design Inc." }, + { 0x2A39, "RME GmbH" }, + { 0x2A3A, "K'NEX Limited Partnership Group" }, + { 0x2A3B, "Eschenbach Optik GmbH" }, + { 0x2A3C, "TRINAMIC Motion Control GmbH & Co. KG" }, + { 0x2A3D, "FIME" }, + { 0x2A3E, "Atlas Copco" }, + { 0x2A3F, "Yasunaga Corporation" }, + { 0x2A40, "Shenzhen Choseal Industrial Co., Ltd." }, + { 0x2A41, "Canyon Semiconductor" }, + { 0x2A42, "Spectra7 Microsystems Corp." }, + { 0x2A43, "Ekosur S.A." }, + { 0x2A44, "FUEL3D Technologies Limited" }, + { 0x2A45, "Meizu Technology Co., Ltd." }, + { 0x2A46, "Hubei Yingtong Telecommunication Cable Inc." }, + { 0x2A47, "Mundo Reader SL" }, + { 0x2A48, "Pointmobile" }, + { 0x2A49, "UNOWHY" }, + { 0x2A4A, "threeRivers 3D, Inc." }, + { 0x2A4B, "EMULEX Corporation" }, + { 0x2A4C, "Tianjin SharpNow Technology Co., Ltd." }, + { 0x2A4D, "Wilder Technologies" }, + { 0x2A4E, "Henge Docks, LLC" }, + { 0x2A4F, "L-3 Communications Avionics Systems" }, + { 0x2A50, "Akizuki Denshi Tsusho Co., Ltd." }, + { 0x2A51, "Multiclet Corp." }, + { 0x2A52, "L CARD Ltd." }, + { 0x2A53, "x-odos GmbH" }, + { 0x2A54, "Black Diamond Advanced Technology, LLC" }, + { 0x2A56, "eemagine Medical Imaging Solutions GmbH" }, + { 0x2A57, "Bellingham + Stanley Limited" }, + { 0x2A58, "ALIGN Corporation Limited" }, + { 0x2A59, "The Whistler Group" }, + { 0x2A5A, "Kromek Group Plc." }, + { 0x2A5B, "Integrity Applications Ltd." }, + { 0x2A5C, "Dalian Zonewin Electronics Co., Ltd." }, + { 0x2A5D, "Zhejiang Wanli Jo Ju Automation Technonolgy Co., Ltd." }, + { 0x2A5E, "The Chemours Company" }, + { 0x2A5F, "Tencent Technology (Shenzhen) Company Limited" }, + { 0x2A60, "Oscadi SAS" }, + { 0x2A61, "Ellex Medical Pty Ltd." }, + { 0x2A62, "Flymaster Avionics, LDA" }, + { 0x2A63, "Postek Electronics Co., Ltd." }, + { 0x2A64, "Zhejiang Songcheng Electronics Co., Ltd." }, + { 0x2A65, "FreeWave Technologies, Inc." }, + { 0x2A66, "JoyLabz LLC" }, + { 0x2A67, "Chart Industries" }, + { 0x2A68, "CheckSum, LLC" }, + { 0x2A69, "EDIC Systems Inc." }, + { 0x2A6A, "PINTSCH TIEFENBACH GmbH" }, + { 0x2A6B, "VSN Mobil" }, + { 0x2A6C, "Silego Technology" }, + { 0x2A6D, "SAsync, LLC" }, + { 0x2A6E, "Bare Conductive Ltd." }, + { 0x2A6F, "Shenzhen Justtide Tech Co., Ltd." }, + { 0x2A70, "Shenzhen Oneplus Science and Technology Co., Inc." }, + { 0x2A71, "Eyelock, Inc." }, + { 0x2A72, "Omega Engineering" }, + { 0x2A73, "IMAC Co., Ltd." }, + { 0x2A74, "Innoflight Tech., Ltd." }, + { 0x2A75, "Delta Dansk Elektronik, Lys & Akustik" }, + { 0x2A76, "Microsemi Corporation (Phoenix)" }, + { 0x2A77, "American Printing House for the Blind" }, + { 0x2A78, "mySkin, Inc." }, + { 0x2A79, "S.E. Technologies Limited" }, + { 0x2A7A, "Beijing Casue Technology Co., Ltd." }, + { 0x2A7B, "Bellwether Electronic Corp." }, + { 0x2A7C, "Acute Technology Inc." }, + { 0x2A7D, "ParTech, Inc." }, + { 0x2A7E, "VAIO Corporation" }, + { 0x2A7F, "Perixx Computer GmbH" }, + { 0x2A80, "Smart Start Inc." }, + { 0x2A81, "Hale Products, Inc." }, + { 0x2A82, "Printek, Inc." }, + { 0x2A83, "Autodesk Inc." }, + { 0x2A84, "ATE Systems" }, + { 0x2A85, "HANK ELECTRONICS CO., LTD" }, + { 0x2A86, "KITRIS AG" }, + { 0x2A87, "Kummler + Matter AG" }, + { 0x2A88, "DFU Technology Ltd." }, + { 0x2A89, "Robert Bosch Tool Corporation" }, + { 0x2A8A, "Benchmark Drives GmbH & Co. KG" }, + { 0x2A8B, "I.C. Lercher GmbH & Co. KG" }, + { 0x2A8C, "Sonnet Technologies, Inc." }, + { 0x2A8D, "Keysight Technologies Inc." }, + { 0x2A8E, "Starlink Electronics Corp." }, + { 0x2A8F, "Manutronics Vietnam Joint Stock Company" }, + { 0x2A90, "NowComputing, LLC" }, + { 0x2A91, "Seed Industrial Designing Co., Ltd." }, + { 0x2A92, "Woosim Systems Inc." }, + { 0x2A93, "Enblink Co., Ltd." }, + { 0x2A94, "G2 Touch Co., Ltd." }, + { 0x2A95, "Flipkart Internet Pvt. Ltd." }, + { 0x2A96, "Micromax Informatics Ltd" }, + { 0x2A97, "Broadway Semiconductor, Inc." }, + { 0x2A98, "Calix" }, + { 0x2A99, "Humanistic Robotics, Inc." }, + { 0x2A9A, "SRAM, LLC" }, + { 0x2A9B, "Doblet Inc." }, + { 0x2A9C, "Olorin AB" }, + { 0x2A9D, "LawMate International Co., Ltd." }, + { 0x2A9E, "SEIKO SOLUTIONS Inc." }, + { 0x2A9F, "Mobelisk LLC" }, + { 0x2AA0, "Casco Products Corp." }, + { 0x2AA1, "Ivanhoe (DE), Inc." }, + { 0x2AA2, "GTI Spindle Technology, Inc." }, + { 0x2AA3, "Strike Technologies a Division of Penbro Kelnick (Pty) Ltd" }, + { 0x2AA4, "Voim Technologies Inc." }, + { 0x2AA5, "Pen Generations, Inc." }, + { 0x2AA6, "ChengFong International Limited" }, + { 0x2AA7, "MJC Techno Co., Ltd." }, + { 0x2AA8, "Resus Industries NV" }, + { 0x2AA9, "Infrared Cameras Inc." }, + { 0x2AAA, "Virtium Technology, Inc." }, + { 0x2AAB, "Field and Company LLC, dba Leef USA" }, + { 0x2AAC, "Elinchrom S.A." }, + { 0x2AAD, "iCatch Technology, Inc." }, + { 0x2AAE, "Chipone Technology (Beijing) Co., Ltd." }, + { 0x2AAF, "Xiamen Hanin Electronic Technology Co., Ltd." }, + { 0x2AB0, "GM Global Technology Operations LLC" }, + { 0x2AB1, "Tesco Stores Ltd." }, + { 0x2AB2, "Maktar, Inc." }, + { 0x2AB3, "Key Asic Inc." }, + { 0x2AB4, "Line Seiki Co., Ltd." }, + { 0x2AB5, "Micro-Technica Co., Ltd." }, + { 0x2AB6, "T+A Elektroakustik GmbH + Co. KG" }, + { 0x2AB7, "foc.us" }, + { 0x2AB8, "Meggitt (Orange County), Inc." }, + { 0x2AB9, "Monsoon Solutions, Inc." }, + { 0x2ABA, "MagneMotion Inc." }, + { 0x2ABB, "HiDeep Inc." }, + { 0x2ABC, "Beijing Kingrich Medical Technology Co., Ltd." }, + { 0x2ABD, "Meeteasy Technology Limited" }, + { 0x2ABE, "Bluink Ltd" }, + { 0x2ABF, "Revolabs, Inc." }, + { 0x2AC0, "POWA Technologies Ltd." }, + { 0x2AC1, "Lattice Semiconductor Corp" }, + { 0x2AC2, "Toreck Co., Ltd." }, + { 0x2AC3, "Foshan Nanhai Saga Audio Equipment Co., Ltd." }, + { 0x2AC4, "BlackBox Biometrics, Inc." }, + { 0x2AC5, "PhotoFast Co., Ltd." }, + { 0x2AC6, "HAKKO Corporation" }, + { 0x2AC7, "Ultrahaptics Limited" }, + { 0x2AC8, "SimonsVoss Technologies GmbH" }, + { 0x2AC9, "TELPA Telekomunikasyon Tic. A.S. Brand: General Mobile" }, + { 0x2ACA, "Toledo do Brasil Industria de Balancas Ltda." }, + { 0x2ACB, "Pole/Zero Acquisition, Inc." }, + { 0x2ACC, "illunis LLC" }, + { 0x2ACD, "Silergy Corp." }, + { 0x2ACE, "Tonetron Electronic Ltd." }, + { 0x2ACF, "Ruffy Controls Inc." }, + { 0x2AD0, "Holley Performance Products (CANADA) Inc." }, + { 0x2AD1, "Pictronic GmbH" }, + { 0x2AD2, "Allnic Audio" }, + { 0x2AD3, "Shenzhen Hali-Power Industrial Co., Ltd." }, + { 0x2AD4, "L&F Corporation" }, + { 0x2AD5, "Baikal Electronics JSC" }, + { 0x2AD6, "Cozumo, Inc." }, + { 0x2AD7, "RHENAC Systems GmbH" }, + { 0x2AD8, "i2s" }, + { 0x2AD9, "Zound Industries International AB" }, + { 0x2ADA, "McCarthy Music Corp." }, + { 0x2ADB, "I-PEX (Dai-ichi Seiko)" }, + { 0x2ADC, "Absolute USA" }, + { 0x2ADD, "SEE-PLUS INDUSTRIAL LTD." }, + { 0x2ADE, "Orga BV" }, + { 0x2ADF, "Noiseless Security A/S" }, + { 0x2AE0, "Auma Riester GmbH & Co. KG" }, + { 0x2AE1, "EDEC PROGRESS CO., LTD." }, + { 0x2AE2, "VXi Corporation" }, + { 0x2AE3, "Jiuzhou Digital (Hong Kong) Limited" }, + { 0x2AE4, "Next! s.c. Slawomir Piela, Bartlomiej Dryja" }, + { 0x2AE5, "Fairphone B.V." }, + { 0x2AE6, "e-distribuzione Spa" }, + { 0x2AE7, "Advanced Media, Inc." }, + { 0x2AE8, "Quintic Microelectronics (Wuxi) Co., Ltd." }, + { 0x2AE9, "Regal Beloit Canada ULC. dba Thomson Power Systems" }, + { 0x2AEA, "Protonex Technology Corporation" }, + { 0x2AEB, "NovaTech, LLC" }, + { 0x2AEC, "Ambiq Micro, Inc." }, + { 0x2AED, "Technology Launch, LLC" }, + { 0x2AEE, "Adapt-IP Company" }, + { 0x2AEF, "Coronado Electronics, Inc." }, + { 0x2AF0, "Zhejiang Yuesui Electron Stock Co., Ltd." }, + { 0x2AF1, "Innovation Spring Tech, Inc." }, + { 0x2AF2, "CIS Corporation" }, + { 0x2AF3, "Rehan Electronics Ltd." }, + { 0x2AF4, "ROLI Ltd." }, + { 0x2AF5, "Libratone A/S" }, + { 0x2AF6, "Nix Sensor Ltd." }, + { 0x2AF7, "Shenzhen Hazens Automotive Electronics (SZ) Co., Ltd." }, + { 0x2AF8, "Jiangsu Toppower Automotive Electronics Co., Ltd." }, + { 0x2AF9, "Drapho Electronics Technology Co., Ltd." }, + { 0x2AFA, "Yokogawa Digital Computer Corporation" }, + { 0x2AFB, "EMC, Electronic Music Components" }, + { 0x2AFC, "Savox Communications OY AB" }, + { 0x2AFD, "McIntosh Laboratory, Inc." }, + { 0x2AFE, "IntriCon" }, + { 0x2AFF, "ARP Corporation" }, + { 0x2B00, "Novitec Co., Ltd." }, + { 0x2B01, "Zimi Corporation" }, + { 0x2B02, "AMGOO Telecom Co., Ltd." }, + { 0x2B03, "STEREOLABS" }, + { 0x2B04, "Spark Labs, Inc." }, + { 0x2B05, "Warn Industries" }, + { 0x2B06, "TEControl" }, + { 0x2B07, "ESA Elektroschaltanlagen Grimma GmbH" }, + { 0x2B08, "KYOEI ENGINEERING Co., Ltd." }, + { 0x2B09, "Shenzhen Lidacheng Technology Co., Ltd." }, + { 0x2B0A, "AMICCOM Electronics Corporation" }, + { 0x2B0B, "Qtul Enterprises" }, + { 0x2B0C, "Goclever Sp z o.o." }, + { 0x2B0D, "Dongguan Yulian Electronic Industrial Co., Ltd." }, + { 0x2B0E, "Le Shi Zhi Xin Electronic Technology (Tian Jin) Limited" }, + { 0x2B0F, "Best Integration Technology Co., Ltd." }, + { 0x2B10, "Cardiac Insight, Inc." }, + { 0x2B11, "Europe Net Srl" }, + { 0x2B12, "DeepSpar" }, + { 0x2B13, "Lightcomm Technology Co., Ltd." }, + { 0x2B14, "EverPro Technologies Company, Ltd." }, + { 0x2B15, "Rosenberger Hochfrequenztechnik" }, + { 0x2B16, "Spirometrix, Inc." }, + { 0x2B17, "Jaguar Land Rover" }, + { 0x2B18, "ProSign GmbH" }, + { 0x2B19, "JBSignal Co." }, + { 0x2B1A, "Fortune Ship Technology (HK) Limited" }, + { 0x2B1B, "Dongguan City Sanji Electronics Co., Ltd." }, + { 0x2B1C, "Shenzhen Virtual Reality Technology Company Limited" }, + { 0x2B1D, "Lintes Technology Co., Ltd." }, + { 0x2B1E, "NFUZD Technology Inc" }, + { 0x2B1F, "KinnexA, Inc." }, + { 0x2B20, "WaveLynx Technologies Corporation" }, + { 0x2B21, "Project Florida" }, + { 0x2B22, "Metra Electronics Corp." }, + { 0x2B23, "Red Hat, Inc." }, + { 0x2B24, "KeepKey, LLC" }, + { 0x2B25, "Logos Biosystems, Inc." }, + { 0x2B26, "Oltrade LLC" }, + { 0x2B27, "FluxData Incorporated" }, + { 0x2B28, "Enovation Controls, LLC" }, + { 0x2B29, "Lezyne" }, + { 0x2B2A, "BDX" }, + { 0x2B2B, "BITwave PTE LTD." }, + { 0x2B2C, "S1nn GmbH & Co. KG" }, + { 0x2B2D, "AEG Power Solutions GmbH" }, + { 0x2B2E, "pei tel Communications GmbH" }, + { 0x2B2F, "UL TS B.V." }, + { 0x2B30, "Neratec Solutions AG" }, + { 0x2B31, "JVIS USA, LLC" }, + { 0x2B32, "NVS Technologies AG" }, + { 0x2B33, "Commend International GmbH" }, + { 0x2B34, "Seemahale Telecoms" }, + { 0x2B35, "Assem Technology Co., Ltd." }, + { 0x2B36, "Dongguan City Jianghan Electronics Co., Ltd." }, + { 0x2B37, "Huizhou Desay SV Automotive Co., Ltd." }, + { 0x2B38, "Ningbo Rixing Electronics Co., Ltd." }, + { 0x2B39, "KANAI ELECTRONIC APPLIANCE Co., Ltd." }, + { 0x2B3A, "Cirrus Research plc" }, + { 0x2B3B, "ScriptPro, LLC" }, + { 0x2B3C, "Technikos Sports Inc." }, + { 0x2B3D, "GuangDong YuanFeng Automotive Electroics Co., Ltd." }, + { 0x2B3E, "NewAE Technology Inc." }, + { 0x2B3F, "ATL-SD Co., Ltd." }, + { 0x2B40, "Matsumura Engineering Co., Ltd." }, + { 0x2B41, "Image Match Design Inc." }, + { 0x2B42, "NEXO S.A." }, + { 0x2B43, "Doro AB" }, + { 0x2B44, "Wildfire, Inc." }, + { 0x2B45, "PRA Audio Systems, Inc." }, + { 0x2B46, "Centerm Information Co., Ltd." }, + { 0x2B47, "Huizhou Aorora Science & Technology Co., Ltd." }, + { 0x2B48, "Sounding Audio Industrial Limited" }, + { 0x2B49, "GECO Incorporated" }, + { 0x2B4A, "Yueqing Huaxin Electronic Co., Ltd." }, + { 0x2B4B, "China Hualu Group Co., Ltd." }, + { 0x2B4C, "Beijing SHENQI Technology Co., Ltd." }, + { 0x2B4D, "SMC Corporation" }, + { 0x2B4E, "Microcabin Inc." }, + { 0x2B4F, "Aeroscout Ltd. (Stanley Healthcare)" }, + { 0x2B50, "Denchi Power Ltd." }, + { 0x2B51, "Pax Instruments" }, + { 0x2B52, "Dongguan Evermax Electronics Technology Co., Ltd." }, + { 0x2B53, "Shenzhen Supernature Multimedia Co., Ltd." }, + { 0x2B54, "AMPAK Technology Inc." }, + { 0x2B55, "FUJIFILM Imaging Systems Co., Ltd." }, + { 0x2B56, "The Crypto Group" }, + { 0x2B57, "GIROPTIC" }, + { 0x2B58, "DJ Sound Electronics, LLC / BiZi Inc." }, + { 0x2B59, "ESI Motion" }, + { 0x2B5A, "Universal Audio, Inc." }, + { 0x2B5B, "Xiamen Home Meitu Technology Co., Ltd." }, + { 0x2B5C, "B&B Exporting Limited" }, + { 0x2B5D, "GSL Solutions, Inc." }, + { 0x2B5E, "Audio Alchemy" }, + { 0x2B5F, "b-plus GmbH" }, + { 0x2B60, "Viking Technology" }, + { 0x2B61, "Universal Biosensors, Inc." }, + { 0x2B62, "ICP Entwicklungs GmbH" }, + { 0x2B63, "Inora Technologies, Inc." }, + { 0x2B64, "Cyanogen Inc." }, + { 0x2B65, "Atelier Vision Corporation" }, + { 0x2B66, "Clinton Instrument Company" }, + { 0x2B67, "Lifesize, Inc." }, + { 0x2B68, "FLEXIM - Flexible Industriemesstechnik GmbH" }, + { 0x2B69, "Humax Automotive Co., Ltd." }, + { 0x2B6A, "FUJI TECOM INC." }, + { 0x2B6B, "Colorix SA" }, + { 0x2B6C, "Transbit Sp. z o.o." }, + { 0x2B6D, "SATORI ELECTRIC CO., LTD." }, + { 0x2B6E, "Airviz Inc." }, + { 0x2B6F, "Revolution Education Ltd." }, + { 0x2B70, "Micran, Research & Production Company" }, + { 0x2B71, "Zhejiang Flashforge 3D Technology Co., Ltd." }, + { 0x2B72, "RT Corporation" }, + { 0x2B73, "Pioneer DJ Corporation" }, + { 0x2B74, "Embedded Intelligence, Inc." }, + { 0x2B75, "New Matter" }, + { 0x2B76, "Shanghai Wingtech Electronic Technology Co., Ltd." }, + { 0x2B77, "Epiphan Systems Inc." }, + { 0x2B78, "Elyctis" }, + { 0x2B79, "Radio Sound, Inc." }, + { 0x2B7A, "Spin Master Far East Ltd." }, + { 0x2B7B, "Gigaset Digital Technology (Shenzhen) Co., Ltd." }, + { 0x2B7C, "Noveltek Semiconductor Corp." }, + { 0x2B7D, "ZEITEC Semiconductor Co., Ltd." }, + { 0x2B7E, "Shenzhen Kingcome Optoelectronic Co., Ltd." }, + { 0x2B7F, "NanoTS Co., Ltd." }, + { 0x2B80, "Miyuki Giken Co., Ltd." }, + { 0x2B81, "PULAX Corporation" }, + { 0x2B82, "TELE RADIO AB" }, + { 0x2B83, "Silicon Line GmbH" }, + { 0x2B84, "Ever Win International Corp." }, + { 0x2B85, "YICHUN YILIAN PRINT TECH CO., LTD." }, + { 0x2B86, "MITSUBISHI HITACHI POWER SYSTEMS ENGINEERING CO., LTD." }, + { 0x2B87, "ATP Industries Group Ltd." }, + { 0x2B88, "Socionext Inc." }, + { 0x2B89, "Ugreen Group Limited" }, + { 0x2B8A, "Shanghai Pateo Electronic Equipment Mfg. Co., Ltd." }, + { 0x2B8B, "Inner Mongolia Yinan Science & Technology Dev. Co., Ltd" }, + { 0x2B8C, "EDGE I&D" }, + { 0x2B8D, "Dr. Fritz Faulhaber GmbH & Co. KG" }, + { 0x2B8E, "Pentair PLC" }, + { 0x2B8F, "DxO Labs Corp." }, + { 0x2B90, "ACR Braendli & Voegeli AG" }, + { 0x2B91, "The Fredericks Company" }, + { 0x2B92, "i-BLADES, Inc." }, + { 0x2B93, "Altia Systems Inc." }, + { 0x2B94, "ShenZhen Baoyuanda Electronics Co., Ltd." }, + { 0x2B95, "iST - Integrated Service Technology Inc." }, + { 0x2B96, "HYUNDAI MOBIS Co., Ltd." }, + { 0x2B97, "Digen Co., Ltd." }, + { 0x2B98, "Glenair, Inc." }, + { 0x2B99, "360fly, Inc." }, + { 0x2B9A, "HUIZHOU CHENG SHUO HARDWARE PLASTIC CO., LTD." }, + { 0x2B9B, "Zhongshan Aute Electronics Technology Co., Ltd." }, + { 0x2B9C, "Guangdong King Link Industrial Co., Ltd." }, + { 0x2B9D, "HARTING Electric GmbH & Co. KG" }, + { 0x2B9E, "ZPower LLC" }, + { 0x2B9F, "Scietera Technologies, Inc." }, + { 0x2BA0, "InVue Security Products" }, + { 0x2BA1, "I-Sheng Electric Wire & Cable Co., Ltd." }, + { 0x2BA2, "China Daheng Group Inc Beijing Image Vision Tech Branch" }, + { 0x2BA3, "Shenzhen FeiTianXia Technology Ltd." }, + { 0x2BA4, "Shenzhen HengJia New Energy Auto Part Co., Ltd." }, + { 0x2BA5, "Yueguan Network Technology (Shanghai) Co., Ltd." }, + { 0x2BA6, "Cyberith GmbH" }, + { 0x2BA7, "77 Elektronika Kft." }, + { 0x2BA8, "YUDU EASON ELECTRONIC CO., LTD." }, + { 0x2BA9, "YanFeng Visteon Automotive Electronics Co., Ltd." }, + { 0x2BAA, "New World Technologies Inc." }, + { 0x2BAB, "Grandstream Networks, Inc." }, + { 0x2BAC, "Polyera Corporation" }, + { 0x2BAD, "XinJi Technologies Ltd." }, + { 0x2BAE, "Holinail H.K. Limited" }, + { 0x2BAF, "Getac Technology Corp." }, + { 0x2BB0, "ITES Co., Ltd." }, + { 0x2BB1, "Validata LLC" }, + { 0x2BB2, "HIDEX OY" }, + { 0x2BB3, "Elcoa Industria e Comercio Ltda" }, + { 0x2BB4, "PRINK Srl" }, + { 0x2BB5, "Silk ID Systems" }, + { 0x2BB6, "3D Imaging & Simulations Corp. (3DISC)" }, + { 0x2BB7, "Dongguan ChengXiang Industrial Co., Ltd." }, + { 0x2BB8, "OCC (Zhuhai) Electronic Co., Ltd." }, + { 0x2BB9, "ARGUS-SPECTRUM" }, + { 0x2BBA, "Sinseader Electronic Co., Ltd." }, + { 0x2BBB, "DONGGUAN YELLOW KNIFE Industrial Co., Ltd." }, + { 0x2BBC, "Guided Ultrasonics Ltd" }, + { 0x2BBD, "RF Creations Ltd." }, + { 0x2BBE, "Chengyi Semiconductors (Shanghai) Co., Ltd." }, + { 0x2BBF, "Shenzhen Shinning Electronic Co., Ltd." }, + { 0x2BC0, "Shenzhen WFD Electronics Co., Ltd." }, + { 0x2BC1, "Dongguan Sino Syncs Industrial Co., Ltd." }, + { 0x2BC2, "JNTC Co., Ltd." }, + { 0x2BC3, "Nihon Mechatronics Co., Ltd." }, + { 0x2BC4, "SR Research Ltd." }, + { 0x2BC5, "Orbbec 3D Tech. Int'l Inc." }, + { 0x2BC6, "Server Technology, Inc." }, + { 0x2BC7, "Zounds Hearing Inc." }, + { 0x2BC8, "DONGGUAN POLIXIN ELECTRIC CO., LTD." }, + { 0x2BC9, "Tama Electric (Suzhou) Co., Ltd." }, + { 0x2BCA, "Exvision, Inc." }, + { 0x2BCB, "Tanaka Electric Industry Co., Ltd." }, + { 0x2BCC, "InoTec GmbH Organisationssysteme" }, + { 0x2BCD, "Keyprocessor BV" }, + { 0x2BCE, "UV Partners" }, + { 0x2BCF, "Magtrol, Inc." }, + { 0x2BD0, "mophie, LLC" }, + { 0x2BD1, "Spectran LLC" }, + { 0x2BD2, "Nabtesco Corporation" }, + { 0x2BD3, "Dongguan ULT-unite electronic technology co., LTD" }, + { 0x2BD4, "JL Audio, Inc." }, + { 0x2BD5, "Cable Matters Inc." }, + { 0x2BD6, "CoroWare, Inc." }, + { 0x2BD7, "EcuTek International Ltd." }, + { 0x2BD8, "ROPEX Industrie-Elektronik GmbH" }, + { 0x2BD9, "Huddly" }, + { 0x2BDA, "Panono GmbH" }, + { 0x2BDB, "LOVEOX CO., LTD." }, + { 0x2BDC, "Automation Electronics Inc." }, + { 0x2BDD, "Charm Sciences Inc." }, + { 0x2BDE, "Pickering Interfaces Limited" }, + { 0x2BDF, "Hangzhou Hikvision Digital Technology Co., Ltd." }, + { 0x2BE0, "Fullink Technology Co., Ltd" }, + { 0x2BE1, "AutoChips Inc." }, + { 0x2BE2, "Electric Connector Technology Co., Ltd." }, + { 0x2BE3, "Hydac Electronic GmbH" }, + { 0x2BE4, "Cojali S.L. ES-B13210489" }, + { 0x2BE5, "LELTEK" }, + { 0x2BE6, "Dongguan KaiWin Electronics Co., Ltd." }, + { 0x2BE7, "BEFS Co., Ltd." }, + { 0x2BE8, "Archisite, Inc." }, + { 0x2BE9, "Magneti Marelli S.p.A Electr BL" }, + { 0x2BEA, "Inspire Medical Systems" }, + { 0x2BEB, "Gateworks Corporation" }, + { 0x2BEC, "Lumantek Co., Ltd." }, + { 0x2BED, "Econoburn LLC" }, + { 0x2BEE, "Ventev Mobile" }, + { 0x2BEF, "Quanta Storage Inc." }, + { 0x2BF0, "Tech-Top Technology Limited" }, + { 0x2BF1, "Murakami Color Research Laboratory" }, + { 0x2BF2, "ABB India Limited" }, + { 0x2BF3, "Photek Ltd." }, + { 0x2BF4, "Thunderbird International DBA Spectec" }, + { 0x2BF5, "Shenzhen YOOBAO Technology Co., Ltd." }, + { 0x2BF6, "Shenzhen Sinotek Technology Co., Ltd." }, + { 0x2BF7, "KEYW" }, + { 0x2BF8, "Visual Land Inc." }, + { 0x2BF9, "Poynt Co." }, + { 0x2BFA, "High Country Tek" }, + { 0x2BFB, "Strattec Advanced Logic, LLC" }, + { 0x2BFC, "Sulon Technologies Inc." }, + { 0x2BFD, "Kinematics GmbH" }, + { 0x2BFE, "Novexx Solutions GmbH" }, + { 0x2BFF, "Shindengen Electric Mfg. Co., Ltd." }, + { 0x2C00, "MEEM SL Ltd" }, + { 0x2C01, "Dongguan Arin Electronics Technology Co., Ltd." }, + { 0x2C02, "DongGuan City JianNuo Electronics Co., Ltd." }, + { 0x2C03, "Barrett Communications Pty. Ltd." }, + { 0x2C04, "Shenzhen XOX Electronics Co., Ltd." }, + { 0x2C05, "Protop International Inc." }, + { 0x2C06, "Microsemi Semiconductor (US) Inc." }, + { 0x2C07, "Webcloak LLC" }, + { 0x2C08, "INVECAS INC." }, + { 0x2C09, "Prediktor Medical AS" }, + { 0x2C0A, "ATANS Technology Inc." }, + { 0x2C0B, "Triple Win Precision Technology Co., Ltd." }, + { 0x2C0C, "IC Realtech" }, + { 0x2C0D, "Embrava Pty Ltd" }, + { 0x2C0E, "Unity Scientific" }, + { 0x2C0F, "Mantra Softech (India) Pvt Ltd" }, + { 0x2C10, "Sinotronics Co., Ltd." }, + { 0x2C11, "ALLBEST ELECTRONICS TECHNOLOGY CO., LTD." }, + { 0x2C12, "Shenzhen Xin Kai Feng Electronics Factory" }, + { 0x2C13, "MOST WELL Technology Corp." }, + { 0x2C14, "Buffalo Memory Co., Ltd." }, + { 0x2C15, "Xentris Wireless" }, + { 0x2C16, "Priferential Accessories Ltd" }, + { 0x2C17, "SVS-VISTEK GmbH" }, + { 0x2C18, "Euclideon Pty. Ltd." }, + { 0x2C19, "Sunlike Technology Co., Ltd." }, + { 0x2C1A, "Young Fast Optoelectronics Co., Ltd." }, + { 0x2C1B, "ISAW Camera Inc" }, + { 0x2C1C, "Daesung Eltec., Ltd" }, + { 0x2C1D, "Makita Corporation" }, + { 0x2C1E, "Global Fire Equipment S.A." }, + { 0x2C1F, "Cashmaster International Limited" }, + { 0x2C20, "Pulsar Instruments Plc." }, + { 0x2C21, "Prynt Corp." }, + { 0x2C22, "Qanba USA, LLC" }, + { 0x2C23, "Super Micro Computer Inc." }, + { 0x2C24, "SONOTEC Ultraschallsensorik Halle GmbH" }, + { 0x2C25, "Shanghai TAIDU INTELLIGENT TECHNOLOGY CO., LTD." }, + { 0x2C26, "Micromax International Corporation" }, + { 0x2C27, "YAWATA Electric Industrial Co., Ltd." }, + { 0x2C28, "Granite River Labs Japan Ltd." }, + { 0x2C29, "Coagent Enterprise Limited" }, + { 0x2C2A, "LEIA Inc." }, + { 0x2C2B, "NetScout Systems, Inc." }, + { 0x2C2C, "Fortify Technologies, LLC" }, + { 0x2C2D, "Shenzhen Ebull Technology Limited" }, + { 0x2C2E, "Hualun Technology Co., Ltd." }, + { 0x2C2F, "Sensel, Inc." }, + { 0x2C30, "Ariadne's Thread (USA), Inc. dba Immerex" }, + { 0x2C31, "tinnos" }, + { 0x2C32, "MCS Micronic Computer Systeme GmbH" }, + { 0x2C33, "Shinobiya.com Co., Ltd." }, + { 0x2C34, "Xerox Business Services (Switzerland) AG" }, + { 0x2C35, "Decto, Inc." }, + { 0x2C36, "Bonsai Lab, Inc." }, + { 0x2C37, "Shenzhen Adition Audio Science & Technology Co., Ltd." }, + { 0x2C38, "Goldenconn Electronics Technology (Suzhou) Co., Ltd." }, + { 0x2C39, "JIB Electronics Technology Co., Ltd." }, + { 0x2C3A, "Changzhou Shinco Automotive Electronics Co., Ltd." }, + { 0x2C3B, "Shenzhen Hangsheng Electronics Corp., Ltd." }, + { 0x2C3C, "Beartooth Radio, Inc." }, + { 0x2C3D, "Audience, A Knowles Company" }, + { 0x2C3E, "Verizon Telematics, Inc." }, + { 0x2C3F, "Nextbit Systems, Inc." }, + { 0x2C40, "Leadtrend" }, + { 0x2C41, "Adaptertek Technology Co., Ltd." }, + { 0x2C42, "Feature Integration Technology Inc." }, + { 0x2C43, "Avegant Corporation" }, + { 0x2C44, "Digital Design Corporation" }, + { 0x2C45, "Reid Heath Ltd." }, + { 0x2C46, "Soehnle Industrial Solutions GmbH" }, + { 0x2C47, "Chunghsin International Electronics Co., Ltd." }, + { 0x2C48, "Delphi Electrical Centers (Shanghai) Co., Ltd." }, + { 0x2C49, "Chikuma Seiki Co., Ltd." }, + { 0x2C4A, "System Industrie Electronic GmbH" }, + { 0x2C4B, "Huntleigh Healthcare Ltd." }, + { 0x2C4C, "Double Robotics, Inc." }, + { 0x2C4D, "VVETEK DOO" }, + { 0x2C4E, "Mercusys Technologies Co., Limited" }, + { 0x2C4F, "Canon Electronic Business Machines (H.K.) Co., Ltd." }, + { 0x2C50, "Vinghog AS" }, + { 0x2C51, "Lambda Acoustic" }, + { 0x2C52, "Comio Communication Co., Ltd." }, + { 0x2C53, "Huizhou Foryou General Electronics Co., Ltd." }, + { 0x2C54, "LifeWatch Technologies Ltd." }, + { 0x2C55, "Magicleap" }, + { 0x2C56, "Pocket Radar Inc." }, + { 0x2C57, "BMT Messtechnik GmbH" }, + { 0x2C58, "Dyden Corporation" }, + { 0x2C59, "EBARA CORPORATION" }, + { 0x2C5A, "Mobilus Automotive Inc" }, + { 0x2C5B, "Shenglan Technology Co. Ltd" }, + { 0x2C5C, "Neusoft Corporation" }, + { 0x2C5D, "SIP Simya Electronics Technology Co., Ltd." }, + { 0x2C5E, "ELVES Automotive Co., Ltd" }, + { 0x2C5F, "YOODS Co., Ltd." }, + { 0x2C60, "Sirin LABS AG" }, + { 0x2C61, "Jadmam Corporation dba: Boytone" }, + { 0x2C62, "Trice Medical" }, + { 0x2C63, "Electronica Steren, S.A. de C.V." }, + { 0x2C64, "Creaform Inc. (Ametek Ultra Precision Technologies)" }, + { 0x2C65, "Nokia Technologies" }, + { 0x2C66, "EMOTIQ srl" }, + { 0x2C67, "VentureCraft, Ltd." }, + { 0x2C68, "EMRight Technology Co., Ltd." }, + { 0x2C69, "BBPOS Limited" }, + { 0x2C6A, "Joint Stock Company Research Centre Module" }, + { 0x2C6B, "System JD Co., Ltd" }, + { 0x2C6C, "Nano TouchSystems co., Ltd." }, + { 0x2C6D, "Gibson Innovations" }, + { 0x2C6E, "Shen Zhen Xian Shuo Technology Co. Ltd." }, + { 0x2C6F, "PST Eletronica LTDA" }, + { 0x2C70, "PERI, Inc." }, + { 0x2C71, "Bozhou BoTong Information Technology Co., Ltd." }, + { 0x2C72, "BlueberryE GmbH" }, + { 0x2C73, "Qiku Internet Network Scientific (Shenzhen) Co., Ltd." }, + { 0x2C74, "CJSC Nordavind" }, + { 0x2C75, "Net And Print Inc." }, + { 0x2C76, "DATAPATH LTD" }, + { 0x2C77, "Profindustry GmbH" }, + { 0x2C78, "BRAGI GmbH" }, + { 0x2C79, "WAWGD, Inc. (DBA: Foresight Sports)" }, + { 0x2C7A, "AutoNavi Software Co., Ltd." }, + { 0x2C7B, "Beijing ASU Tech Co., Ltd." }, + { 0x2C7C, "Anysmart Technologies Co., Ltd." }, + { 0x2C7D, "Shenzhen Protruly Electronic Co., Ltd." }, + { 0x2C7E, "Dongguan Allpass Electronic Co., Ltd." }, + { 0x2C7F, "SHENZHEN D-VITEC INDUSTRIAL CO., LTD." }, + { 0x2C80, "motomobile AG" }, + { 0x2C81, "Indie Semiconductor" }, + { 0x2C82, "Cloud9 Technologies LLC" }, + { 0x2C83, "LRP electronic GmbH" }, + { 0x2C84, "Innodezign MauRitius Limited" }, + { 0x2C85, "Audientes" }, + { 0x2C86, "Ultraflux" }, + { 0x2C87, "ISKN" }, + { 0x2C88, "K-Tronic SRL" }, + { 0x2C89, "Younes Medical Technologies" }, + { 0x2C8A, "Advanced Casino Electronics" }, + { 0x2C8B, "Huizhou Dehong Technology Co., Ltd." }, + { 0x2C8C, "PowerCenter Technology Limited" }, + { 0x2C8D, "Mizco International, Inc." }, + { 0x2C8E, "Unique Secure Limited" }, + { 0x2C8F, "Regulus Company Ltd." }, + { 0x2C90, "I. AM. PLUS, LLC" }, + { 0x2C91, "Corigine, Inc." }, + { 0x2C92, "Ningbo Yinzhou Shengke Electronics Co., Ltd." }, + { 0x2C93, "SWFL Inc. dba: Filament" }, + { 0x2C94, "HIRATSUKA Engineering Co., Ltd." }, + { 0x2C95, "TOSHIBA MACHINE CO., LTD." }, + { 0x2C96, "KBS Industrieelektronik GmbH" }, + { 0x2C97, "LEDGER" }, + { 0x2C98, "Fosfomatic Technology LLC" }, + { 0x2C99, "Prusa Research s.r.o." }, + { 0x2C9A, "Lawo AG" }, + { 0x2C9B, "SPECIM, Spectral Imaging Ltd." }, + { 0x2C9C, "Vayyar Imaging LTD." }, + { 0x2C9D, "Nod Inc." }, + { 0x2C9E, "Shanghai Linguo Technology Co.,Ltd." }, + { 0x2C9F, "e-Smart Systems Pvt. Ltd." }, + { 0x2CA0, "Leagtech Jiangxi Electronic Co., Ltd." }, + { 0x2CA1, "Veetone Technologies Limited" }, + { 0x2CA2, "GuangZhou MingPing Electronics Technology" }, + { 0x2CA3, "DJI Technology Co., Ltd." }, + { 0x2CA4, "Shenzhen Alex Technology Co., Ltd." }, + { 0x2CA5, "Fussen Technology Co., Ltd." }, + { 0x2CA6, "Dai-ichi Dentsu Ltd." }, + { 0x2CA7, "Heptagon Advanced Micro Optics" }, + { 0x2CA8, "STATSports" }, + { 0x2CA9, "JITS TECHNOLOGY CO., LIMITED" }, + { 0x2CAA, "LIVV Brand llc" }, + { 0x2CAB, "AppWorld S. de R.L. de C.V." }, + { 0x2CAC, "MGF Sviesos Konversija, UAB" }, + { 0x2CAD, "EMS Security Group Ltd." }, + { 0x2CAE, "Clyde Broadcast Products Ltd." }, + { 0x2CAF, "IDS GmbH" }, + { 0x2CB0, "Creative bits Solutions" }, + { 0x2CB1, "Avista Corporation" }, + { 0x2CB2, "NAGANO KEIKI CO., LTD." }, + { 0x2CB3, "Shenzhen Bolin Image Science Technology Co., Ltd." }, + { 0x2CB4, "Ava Enterprises, Inc. dba Boss Audio Systems" }, + { 0x2CB5, "SUS Corp." }, + { 0x2CB6, "Borqs Hong Kong Limited" }, + { 0x2CB7, "Fibocom Wireless Inc." }, + { 0x2CB8, "Shenzhen Sydixon Electronic Technology Co., Ltd." }, + { 0x2CB9, "On-Bright Electronics (Shanghai) Co., Ltd." }, + { 0x2CBA, "Dongguan Puxu Industrial Co., Ltd." }, + { 0x2CBB, "Shenzhen Soling Indusrtial Co., Ltd." }, + { 0x2CBD, "EGGCYTE, INC." }, + { 0x2CBE, "uQontrol" }, + { 0x2CBF, "Donggguan Yuhua Electronic Co., Ltd." }, + { 0x2CC0, "Hangzhou Zero Zero Technology Co., Ltd." }, + { 0x2CC1, "SIGFOX" }, + { 0x2CC2, "Lautsprecher Teufel GmbH" }, + { 0x2CC3, "A-VEKT K.K." }, + { 0x2CC4, "Sanden Advanced Technology Corporation" }, + { 0x2CC5, "Metatronics" }, + { 0x2CC6, "Prodigy Technovations Pvt Ltd" }, + { 0x2CC7, "EmergiTech, Inc" }, + { 0x2CC8, "Hewlett Packard Enterprise" }, + { 0x2CC9, "Monolithic Power Systems Inc." }, + { 0x2CCA, "Amphenol Advanced Sensors" }, + { 0x2CCB, "USB Memory Direct" }, + { 0x2CCC, "Silicon Mitus Inc." }, + { 0x2CCD, "ITOS Inc." }, + { 0x2CCE, "SMARTY Performance King SA" }, + { 0x2CCF, "Hypersecu Information Systems, Inc." }, + { 0x2CD0, "Technics Global Electronics & JCE Co., Ltd." }, + { 0x2CD1, "Tamron Co., Ltd." }, + { 0x2CD2, "Mikrotikls S/A" }, + { 0x2CD3, "Life Robotics Inc." }, + { 0x2CD4, "NGK SPARK PLUG CO., LTD." }, + { 0x2CD5, "Institut Dr. Foerster GmbH & Co. KG" }, + { 0x2CD6, "Immersive Media" }, + { 0x2CD7, "Cosemi Technologies Inc." }, + { 0x2CD8, "Nanoport Technology, Inc." }, + { 0x2CD9, "Cambrionix Ltd" }, + { 0x2CDA, "CXUN Co. Ltd." }, + { 0x2CDB, "China Tsp Inc" }, + { 0x2CDC, "Sea & Sun Technology GmbH" }, + { 0x2CDD, "IAI Corporation" }, + { 0x2CDE, "RTI International" }, + { 0x2CDF, "Tecno Alarm S.R.L." }, + { 0x2CE0, "iClassmate Educational Technologies Co., Ltd." }, + { 0x2CE1, "Gradus Group" }, + { 0x2CE2, "Yanfeng Visteon (Chongqing) Automotive Electronics Co" }, + { 0x2CE3, "Alcorlink Corp." }, + { 0x2CE4, "ISBC Ltd." }, + { 0x2CE5, "InX8 Inc dba AKiTiO" }, + { 0x2CE6, "SDAN Tecchnology Co., Ltd." }, + { 0x2CE7, "Lemobile Information Technology (Beijing) Co., Ltd." }, + { 0x2CE8, "DongGuan Hongweixiang Electronic Technology Co., Ltd." }, + { 0x2CE9, "Suzhu Jingshi Electronic Technology Co., Ltd." }, + { 0x2CEA, "Zhong Shan City Richsound Electronic Industrial Ltd." }, + { 0x2CEB, "Dongguang Kangbang Electronics Co., Ltd." }, + { 0x2CEC, "Ascon Tecnologic" }, + { 0x2CED, "KMC Controls, Inc." }, + { 0x2CEE, "Winpower Qmadix Technology Co., Ltd." }, + { 0x2CEF, "Toptest Technologies Co., Ltd." }, + { 0x2CF0, "Nuand, LLC" }, + { 0x2CF1, "DTS, Inc." }, + { 0x2CF2, "KUNSHAN DLK Electronics Technology Co., Ltd." }, + { 0x2CF3, "Konekt, Inc." }, + { 0x2CF4, "CAM2 Technologies, LLC dba: Czitek" }, + { 0x2CF5, "EBARA REFRIGERATION EQUIPMENT & SYSTEMS CO., LTD." }, + { 0x2CF6, "Eye-Fi, Inc." }, + { 0x2CF7, "PPST, Inc." }, + { 0x2CF8, "Itron" }, + { 0x2CF9, "Terrafix Ltd." }, + { 0x2CFA, "Meta Company" }, + { 0x2CFB, "Nanchang Haozhun Electronics Co., Ltd." }, + { 0x2CFC, "DeLaval International AB" }, + { 0x2CFD, "GoerTek Inc." }, + { 0x2CFE, "Alpha Data Parallel Systems" }, + { 0x2CFF, "ITHAKi" }, + { 0x2D00, "VDO Cyclecomputing, Cycle Parts GmbH" }, + { 0x2D01, "Gopod Group Limited" }, + { 0x2D02, "Zhi Sheng Electronics Technology Co., Ltd." }, + { 0x2D03, "ECCO Safety Group" }, + { 0x2D05, "Technology Solutions (UK) Limited" }, + { 0x2D06, "Jireh Industries Ltd." }, + { 0x2D07, "MSI.TOKYO, Inc." }, + { 0x2D08, "ZIT Ltd." }, + { 0x2D09, "Dongguan Evervictory Electronic Co., Ltd." }, + { 0x2D0A, "Kingsignal Technology Co., Ltd." }, + { 0x2D0B, "IPD CO., LTD" }, + { 0x2D0C, "B & P Automation Dynamics Ltd" }, + { 0x2D0D, "Star Vision Electronics Limited" }, + { 0x2D0E, "Linxee (Beijing) Technology LTD." }, + { 0x2D0F, "M8TRIX TECH LLC" }, + { 0x2D10, "Shenzhen San Guan Si Yuan Technology Limited" }, + { 0x2D11, "Servelec Technologies" }, + { 0x2D12, "SICPA Security Solutions SA" }, + { 0x2D13, "DONG GUAN EBEN ELECTRONIC CO., LTD" }, + { 0x2D14, "Palit Microsystems Ltd" }, + { 0x2D15, "Si-Ware Systems" }, + { 0x2D16, "DONGGUAN WELLINK ELECTRONIC CO., LTD." }, + { 0x2D17, "TECHVIWIN INTERNATIONAL (HONGKONG) LIMITED" }, + { 0x2D18, "Hui Zhou Kai Yue Electronics Co., Ltd" }, + { 0x2D19, "Churchill Navigation" }, + { 0x2D1A, "Phononic" }, + { 0x2D1B, "Suzhou Yourfriend Electronic Co., Ltd." }, + { 0x2D1C, "Club 3D BV" }, + { 0x2D1D, "Design Pool Limited" }, + { 0x2D1E, "Excalibur" }, + { 0x2D1F, "Wacom Taiwan Information Co. Ltd." }, + { 0x2D20, "UL LLC" }, + { 0x2D21, "Koozyt, Inc." }, + { 0x2D22, "SEIKOSHA Co., Ltd." }, + { 0x2D23, "Shenzhen Microtest Automation Co., Ltd." }, + { 0x2D24, "Warwick Audio Technologies Ltd" }, + { 0x2D25, "Kronegger GmbH" }, + { 0x2D26, "Greenfield Technology" }, + { 0x2D27, "Global Optics Limited" }, + { 0x2D28, "Beijing ANTVR Technology Co., LTD" }, + { 0x2D29, "Beijing Baofengmojing Technologies Co. Ltd" }, + { 0x2D2A, "Shenzhen ZDT Technology Co., LTD" }, + { 0x2D2B, "STYL Solutions Pte Ltd" }, + { 0x2D2C, "Tankya Developing Co., Limited" }, + { 0x2D2D, "Guangzhou Botao Information Technology Co., Ltd" }, + { 0x2D2E, "Hieyoung International (Hong Kong) Limited" }, + { 0x2D2F, "PT Phototechnics AG" }, + { 0x2D30, "Addasound Denmark A/S" }, + { 0x2D31, "Synox Tech Co., Ltd." }, + { 0x2D32, "JR Technik Co., Ltd." }, + { 0x2D33, "Elysia-raytest GmbH" }, + { 0x2D34, "Nureva Inc." }, + { 0x2D35, "SIGMA TECH. CO., LTD" }, + { 0x2D36, "Blu5 View Pte. Ltd." }, + { 0x2D37, "Xprinter Co., Ltd" }, + { 0x2D38, "Shanghai OXi Technology Co., Ltd" }, + { 0x2D39, "Roofer Technology (Shenzhen) Co. Ltd" }, + { 0x2D3A, "Le Touch (Shenzhen) Electronics Co., Ltd." }, + { 0x2D3B, "Lencheng Electronics Co., Ltd" }, + { 0x2D3C, "FOVE, Inc." }, + { 0x2D3D, "Battlespace Simulations, Inc." }, + { 0x2D3E, "Technica Del Arte BV" }, + { 0x2D3F, "ViCentra B.V." }, + { 0x2D40, "Beijing Pico Technology Co., Ltd." }, + { 0x2D41, "Dongguan Mankind Plastic Electronics Co., Ltd" }, + { 0x2D42, "Protech Electronics & Technology Limited" }, + { 0x2D43, "OSSIC Corporation" }, + { 0x2D44, "FAMAR FUEGUINA S.A." }, + { 0x2D45, "JSC TION SMART MICROCLIMATE" }, + { 0x2D46, "JSC Yukon Advanced Optics Worldwide" }, + { 0x2D47, "INVENCO GROUP LIMITED" }, + { 0x2D48, "StarBridge, Inc." }, + { 0x2D49, "Shanghai Deepoon Technology Co., Ltd." }, + { 0x2D4A, "Helioway Enterprises Co., Ltd" }, + { 0x2D4B, "Dongguan Hongwei Electronics Co.,Ltd" }, + { 0x2D4C, "Ixtra Tech Inc" }, + { 0x2D4D, "Razer Inc" }, + { 0x2D4E, "Electronic Equipment BV" }, + { 0x2D4F, "Dongguan Hanker Electronic Technology Co., Ltd." }, + { 0x2D50, "CryLaS - Crystal Laser Systems GmbH" }, + { 0x2D51, "NITTA Corporation" }, + { 0x2D52, "YiQin Electronics Co.,Ltd" }, + { 0x2D53, "OWOW Products B.V." }, + { 0x2D54, "C-Smartlink Information Technology Co., Ltd." }, + { 0x2D55, "Nagravision SA" }, + { 0x2D56, "DongGuan Kelta Electro Mechanical Products CO, LTD" }, + { 0x2D58, "Lyra Semiconductor Incorporated" }, + { 0x2D59, "Sunyking Technology Co., Ltd" }, + { 0x2D5A, "Shenzhen YAAN Precision Connector Co., Ltd." }, + { 0x2D5B, "SunTo Technology (Shen Zhen) Corporation Limited" }, + { 0x2D5C, "Daiwoo Electronics Lo., LTD" }, + { 0x2D5D, "Loctek Ergonomic Technology Corp." }, + { 0x2D5E, "Sky UK Limited" }, + { 0x2D5F, "Shanghai Yuewen information technology Co., Ltd." }, + { 0x2D60, "Comarch S.A." }, + { 0x2D61, "Shenzhen Hongjixin Plastic & Electronics Co., Ltd" }, + { 0x2D62, "Weifang Genius Electronics Co.,Ltd." }, + { 0x2D63, "Cable Technology Corp." }, + { 0x2D64, "H.D.T. S.R.L" }, + { 0x2D65, "DPA Microphones" }, + { 0x2D66, "Oley Company Limited" }, + { 0x2D67, "Fengfan (Suzhou) Audio Technology Co., Ltd." }, + { 0x2D68, "Lumulabs d.o.o." }, + { 0x2D6A, "AIPHONE Co., LTD" }, + { 0x2D6B, "NetUP Inc." }, + { 0x2D6C, "Sphericam Inc." }, + { 0x2D6D, "Shenzhen HaiWei Technology Co., LTD" }, + { 0x2D6E, "Jiangsu Jing Lian Electronic Technology Co., Ltd" }, + { 0x2D6F, "Tobii Dynavox" }, + { 0x2D70, "Zhongshan Winner Electronic Technology CO., LTD" }, + { 0x2D71, "OVERKIZ" }, + { 0x2D72, "DOGAWIST - Investment GmbH" }, + { 0x2D73, "XtremeMac Sarl" }, + { 0x2D74, "CMO America; dba ZipKord Solutions" }, + { 0x2D75, "Shenzhen Taiji Electronics Co., Ltd." }, + { 0x2D76, "SiliConch Systems Private Limited" }, + { 0x2D77, "SweDeltaco AB" }, + { 0x2D78, "Dental Imaging Technology Corporation" }, + { 0x2D79, "Shenzhen Legendary Technologies Co., LTD." }, + { 0x2D7A, "Dongguan JingFeng Electronics Technology Co., Ltd" }, + { 0x2D7B, "Panasonic Lighting Americas, Inc." }, + { 0x2D7C, "Dongguan City Qingda Electronic Co., Ltd." }, + { 0x2D7D, "Televes S.A." }, + { 0x2D7E, "NISSIN ELECTRIC Corporation" }, + { 0x2D7F, "Sinar Photography AG" }, + { 0x2D80, "Pendo Technology China Corporation" }, + { 0x2D81, "Evollve Inc." }, + { 0x2D82, "boud" }, + { 0x2D84, "Zhuhai J-Speed Technology Co., Ltd." }, + { 0x2D85, "Asahi Electronics Laboratory" }, + { 0x2D86, "Dongguan Team Force Electronic Co., Ltd" }, + { 0x2D87, "Zhuhai Spark Electronic Equipment Co., Ltd" }, + { 0x2D88, "Prinics Co., Ltd." }, + { 0x2D89, "Ekahau" }, + { 0x2D8A, "I-O Conn (GuangDong) Technologies Co., Ltd" }, + { 0x2D8B, "Eclatkey Semiconductor Technology Company Limited" }, + { 0x2D8C, "Hongrida Electronic Technology Co. LTD" }, + { 0x2D8D, "MISUMI Corporation" }, + { 0x2D8E, "Color Sentinel Systems, LLC" }, + { 0x2D8F, "Shenzhen Bing Chuang Wei Technology Co., Ltd." }, + { 0x2D90, "Humanplus" }, + { 0x2D91, "SDI Technologies Inc." }, + { 0x2D92, "Shanghai Fengtian Electronic Co., LTD." }, + { 0x2D93, "STK TECHNOLOGY CO., LTD." }, + { 0x2D94, "TokenWorks Inc." }, + { 0x2D95, "Vivo Mobile Communication Co., Ltd." }, + { 0x2D96, "SHENZHEN WAMAXLINK ELECTRONIC TECHNOLOGY CO., LTD" }, + { 0x2D97, "Dong Guan JingHe Electronics Technology Co., Ltd" }, + { 0x2D98, "Shenzhen Ruiming Technology Co., Ltd." }, + { 0x2D99, "Edifier International Limited" }, + { 0x2D9A, "Jiangsu GuoGuang Electronic Information Technology Co.," }, + { 0x2D9B, "iStorage Limited" }, + { 0x2D9C, "Global Connector Technology" }, + { 0x2D9D, "Dongguan Suntes Electronics Technology Co., Ltd." }, + { 0x2D9E, "Sivantos GmbH" }, + { 0x2D9F, "SABRENT" }, + { 0x2DA0, "IN-VISION Digital Imaging Optics GmbH" }, + { 0x2DA1, "Koden Electronics Co., Ltd" }, + { 0x2DA2, "CIMA SPA con socio unico" }, + { 0x2DA3, "Superior Communications" }, + { 0x2DA4, "GE Multilin" }, + { 0x2DA5, "Tokai Rika Create Corporation" }, + { 0x2DA6, "SiChuan Rui Thai Electronic Technology Co., Ltd." }, + { 0x2DA7, "Topland Corporation" }, + { 0x2DA8, "Harmonic Drive Systems Inc." }, + { 0x2DA9, "ELECTRONIC ASSEMBLY GmbH" }, + { 0x2DAA, "Shenzhen Jing Tuo Jin Electronics Co., Ltd." }, + { 0x2DAB, "CYD Electronics (Shenzhen) Co., Ltd." }, + { 0x2DAC, "Shenzhen YZB Electronics Technology Co., Ltd" }, + { 0x2DAD, "GoerTek Dynaudio Co., Ltd" }, + { 0x2DAE, "Hex Technology Limited" }, + { 0x2DAF, "IF Link Electronics Co Limited" }, + { 0x2DB0, "Shenzhen Welltech Cable Co., Ltd" }, + { 0x2DB1, "DongGuan Greatek Electronics Technology Co., LTD" }, + { 0x2DB2, "Imperx, Inc" }, + { 0x2DB3, "i Digital Galaxy Ltd." }, + { 0x2DB4, "Dongguan Changtuo Hardware Technology Co., Ltd." }, + { 0x2DB5, "Fuji Ceramics Corporation" }, + { 0x2DB6, "Kunshan 3e Electronics Co., Ltd." }, + { 0x2DB7, "Premium Sound Solutions Sdn. Bhd." }, + { 0x2DB8, "Foshan Yami Electric Ltd." }, + { 0x2DB9, "Danelec Marine A/S" }, + { 0x2DBA, "Houwa System Design, k.k" }, + { 0x2DBB, "Huajie IMI Technology Co., Ltd." }, + { 0x2DBC, "Mikroelektronika d.o.o" }, + { 0x2DBD, "Shanghai Xiaoyi Technology Co., Ltd" }, + { 0x2DBE, "MA Lighting Technology GmbH" }, + { 0x2DBF, "Tul Corporation" }, + { 0x2DC0, "Chipsea Technologies (Shenzhen) Corp" }, + { 0x2DC1, "littleBits" }, + { 0x2DC2, "MintWave Co., Ltd." }, + { 0x2DC3, "Action Industries (M) SDN BHD" }, + { 0x2DC4, "Six 15 Technologies" }, + { 0x2DC5, "Cytek Biosciences, Inc." }, + { 0x2DC6, "Dongguan Kingtron Electronics Technology Co., Ltd." }, + { 0x2DC7, "Lacroix Sofrel" }, + { 0x2DC8, "8BITDO TECHNOLOGY HK LIMITED" }, + { 0x2DC9, "3T B.V." }, + { 0x2DCA, "OEM Systems Co., Ltd." }, + { 0x2DCB, "i-Money Technology Co., Ltd." }, + { 0x2DCC, "Suzhou Keda Technology Co., Ltd." }, + { 0x2DCD, "Yeonho Electronics" }, + { 0x2DCE, "Shen Zhen Farmer Technology Co., Limited" }, + { 0x2DCF, "Dialog Semiconductor (UK) Ltd" }, + { 0x2DD0, "iBaby Labs, Inc" }, + { 0x2DD1, "Empathy Co., Ltd." }, + { 0x2DD2, "HARNICS Co., LTD." }, + { 0x2DD3, "Viscell, LLC" }, + { 0x2DD5, "Gingy Technology Inc." }, + { 0x2DD6, "Suzhou SuperMax Smart System Co., Ltd." }, + { 0x2DD7, "enRoute Co., Ltd." }, + { 0x2DD8, "Perception Sensors and Instrumentation Ltd" }, + { 0x2DD9, "Dong Guan Fei Tai Electronics CO., LTD." }, + { 0x2DDA, "Miura Systems Ltd" }, + { 0x2DDB, "Shenzhen DAK Technology Co., Ltd" }, + { 0x2DDC, "Audiolink Co., Ltd" }, + { 0x2DDD, "Princeton Infrared Technologies, Inc." }, + { 0x2DDE, "The Chamberlain Group, Inc." }, + { 0x2DDF, "BOMTECH ELECTRONICS CO., LTD." }, + { 0x2DE0, "Active-semi, Inc" }, + { 0x2DE1, "Jiang Su Denseting Precision Technology Co., Ltd." }, + { 0x2DE2, "PathPartner Technology Pvt. Ltd" }, + { 0x2DE3, "Shanghai Yitu Technology Co., Ltd." }, + { 0x2DE4, "Best Case and Accessories, Inc." }, + { 0x2DE5, "KaiJet Technology International Limited, Inc. dba j5create" }, + { 0x2DE6, "Amazon Fulfillment Services, Inc." }, + { 0x2DE7, "The LightCo, Inc." }, + { 0x2DE8, "Shenzhen City Xiaoduan Electrical Co., LTD." }, + { 0x2DE9, "CAR MATE MFG. CO., LTD." }, + { 0x2DEA, "LightFactor" }, + { 0x2DEB, "Hold-Key Electric Wire & Cable Co Ltd" }, + { 0x2DEC, "ZNi Technology Co., Ltd" }, + { 0x2DED, "Aquil Star Precision Industrial (Shenzhen) Co., Ltd" }, + { 0x2DEE, "Shenzhen MeiG Smart Technology Co., Ltd" }, + { 0x2DEF, "Kirale Technologies SL" }, + { 0x2DF0, "CANVASBIO CO., LTD" }, + { 0x2DF1, "Inovonics Corp" }, + { 0x2DF2, "LIPS Corporation" }, + { 0x2DF3, "LongSung Technology (Shanghai) Co., Ltd." }, + { 0x2DF4, "Jumplux Technology Co., Ltd." }, + { 0x2DF5, "Helium Systems Inc." }, + { 0x2DF6, "Greektown Casino-Hotel, LLC" }, + { 0x2DF7, "Fastwel Group Ltd." }, + { 0x2DF8, "ITEST" }, + { 0x2DF9, "EZQuest, Inc." }, + { 0x2DFA, "3DRUDDER" }, + { 0x2DFB, "Bren-Tronics, Inc." }, + { 0x2DFC, "Graphic Products" }, + { 0x2DFD, "Ubisoft Entertainment SA" }, + { 0x2DFE, "Next Thing Co." }, + { 0x2DFF, "Unicept GmbH" }, + { 0x2E00, "CIB Security Inc" }, + { 0x2E01, "Symetrix, Inc." }, + { 0x2E02, "Softiron" }, + { 0x2E03, "Zhejiang Dahua Technology Co., Ltd." }, + { 0x2E04, "HMD Global Oy" }, + { 0x2E05, "CKD Corporation" }, + { 0x2E06, "Shenzhen Junlan Electronic Ltd" }, + { 0x2E07, "Lafayette Instrument Company" }, + { 0x2E08, "Zhongshan Dumei Weite Electronics Co., Ltd" }, + { 0x2E09, "Beijing LLVision Technology Co. LTD" }, + { 0x2E0A, "Dytran Instruments" }, + { 0x2E0B, "Datafield Industries (HK) Ltd" }, + { 0x2E0C, "Shenzhen Mek Intellisys PTE Ltd" }, + { 0x2E0D, "Suzhou FanglinTechnology Co., Ltd" }, + { 0x2E0E, "Hatteland Display AS" }, + { 0x2E0F, "Institute for Defense Analyses / Center for Computing Sciences" }, + { 0x2E10, "LinkMTech Inc." }, + { 0x2E11, "ShenZhen ShenTai WeiXiang Electronics Co., Ltd" }, + { 0x2E12, "Hongkong Chenyang Electronic Co., Limited" }, + { 0x2E13, "Intelligent Automation (Zhuhai) Co., Ltd" }, + { 0x2E14, "Expressive" }, + { 0x2E15, "Now Technologies" }, + { 0x2E16, "Glosys Inc." }, + { 0x2E17, "Essential Products, Inc." }, + { 0x2E18, "NorthStar Battery Company, LLC" }, + { 0x2E19, "Additel Corporation" }, + { 0x2E1A, "Shenzhen Arashi Vision Company Limited" }, + { 0x2E1B, "BeiJie Electronics Technology Co., Ltd" }, + { 0x2E1C, "Shenzhen Auto-Link World Information Technology Co., Ltd." }, + { 0x2E1D, "Clarion (Malaysia) Sdn. Bhd." }, + { 0x2E1E, "Sound Technology (C.Q.) Co., Ltd" }, + { 0x2E1F, "BrainScope Company, Inc." }, + { 0x2E20, "Guangzhou Long Do Co.,Ltd" }, + { 0x2E21, "DOSCH&AMAND Research GmbH&CoKG" }, + { 0x2E22, "DongGuan LinSong precision electronics CO., LTD" }, + { 0x2E23, "Shenzhen Baojia Battery Technology Co., Ltd." }, + { 0x2E24, "Hyperkin Inc." }, + { 0x2E25, "Gold Cable (Zhongshan) Electronic Co., Ltd." }, + { 0x2E26, "Monoprice, Inc." }, + { 0x2E27, "Lion Semiconductor" }, + { 0x2E28, "VOLTRONIC POWER TECHNOLOGY CORP." }, + { 0x2E29, "Clas Ohlson AB" }, + { 0x2E2B, "Shenzhen Qinps Technology Co Limited" }, + { 0x2E2C, "Dashine Electronics Co, Ltd" }, + { 0x2E2D, "Anaren Inc." }, + { 0x2E2E, "First Design System Inc." }, + { 0x2E2F, "Gulden Ophthalmics, Inc." }, + { 0x2E30, "Andon Health Co., Ltd." }, + { 0x2E31, "Thine Electronics, Inc." }, + { 0x2E32, "Shenzhen Red Star Electronics Co., Ltd." }, + { 0x2E33, "Squarehead Technology" }, + { 0x2E34, "ALLDATA LLC" }, + { 0x2E35, "Shenzhen PYS Industrial Co., LTD" }, + { 0x2E36, "Depo Electronics Limited" }, + { 0x2E37, "IRISO ELECTRONICS CO., LTD" }, + { 0x2E38, "OHM ELECTRONIC INC." }, + { 0x2E39, "Epic Tech, LLC" }, + { 0x2E3A, "Nanaboshi Electric Mfg. Co., Ltd." }, + { 0x2E3B, "uSens Inc" }, + { 0x2E3C, "ARTERY Technology Co., Ltd." }, + { 0x2E3D, "ASWAN ELEC. SALES CO., LTD." }, + { 0x2E3E, "Karma Automotive" }, + { 0x2E3F, "Poly-Planar Group LLC" }, + { 0x2E40, "Mobile Technologies Inc" }, + { 0x2E41, "DONGGUAN RONGDEKANG ELECTRONIC TECHNOLOGY CO., LTD." }, + { 0x2E42, "Hunan Ronghe Microelectronics Co., Ltd." }, + { 0x2E43, "Owl Labs, Inc" }, + { 0x2E44, "Idealens Technology (Chengdu) Co., Ltd." }, + { 0x2E45, "Widex A/S" }, + { 0x2E46, "Mobileconn Technology Co., Ltd." }, + { 0x2E47, "X-Media Tech, Inc." }, + { 0x2E48, "Andromium Inc." }, + { 0x2E49, "A&T Corporation" }, + { 0x2E4A, "Xiamen Jinhaode Electronic Co., Ltd" }, + { 0x2E4B, "ART SPA" }, + { 0x2E4C, "Carter Duncan Corp." }, + { 0x2E4D, "Vinpower, Inc." }, + { 0x2E4E, "METER Group, Inc" }, + { 0x2E4F, "Audiotec Fischer GmbH" }, + { 0x2E50, "beyerdynamic GmbH & Co. KG" }, + { 0x2E51, "EVER Sp. Z.o.o." }, + { 0x2E52, "Toughbuilt Industries Inc" }, + { 0x2E53, "Shenzhen East-Toptech Electronic Technology Co., Ltd" }, + { 0x2E54, "Yin Run Precise Metal Products CO., LTD." }, + { 0x2E55, "FIP Formatura Iniezione Polimeri an Aliaxis Company" }, + { 0x2E56, "Juchin Technology (JIANGXI) Co., Ltd" }, + { 0x2E57, "MEGWARE Computer Vertrieb und Service GmbH" }, + { 0x2E58, "GONGNIU GROUP CO., LTD." }, + { 0x2E59, "Maui Imaging, Inc." }, + { 0x2E5A, "Mysher Technology Co., Ltd." }, + { 0x2E5B, "Fitipower Integrated Technology Inc." }, + { 0x2E5C, "Y.H.S. Co., Ltd" }, + { 0x2E5D, "Dong Guan LM-Link Precise Electronic Co., Ltd." }, + { 0x2E5E, "Mei Shun He Electronic Limited" }, + { 0x2E5F, "Shenzhen BTC Technology Co., Ltd." }, + { 0x2E60, "castAR, Inc." }, + { 0x2E61, "NetBurner, Inc." }, + { 0x2E62, "Will Semiconductor Co., LTD" }, + { 0x2E63, "Polaris-Labs Shenzhen Co., Ltd" }, + { 0x2E64, "Shenzhen Kaibao Technology Co., Ltd." }, + { 0x2E65, "Kunshan Xintaili Precision Components Co., Ltd." }, + { 0x2E66, "SALICRU, S.A." }, + { 0x2E67, "Elevation Lab, Inc." }, + { 0x2E68, "Tessonics Inc." }, + { 0x2E69, "Swift Navigation Inc" }, + { 0x2E6A, "Wilderness Labs Inc." }, + { 0x2E6B, "DMX, LLC dba Mood Media" }, + { 0x2E6C, "Uwatec AG" }, + { 0x2E6D, "Laser Argentina S.A." }, + { 0x2E6E, "E4D Technologies LLC" }, + { 0x2E6F, "Areca Technology Corporation" }, + { 0x2E70, "Revision Electronics & Power Systems Inc." }, + { 0x2E71, "Futurepath Electronics Technology (Dongguan) Co., Ltd." }, + { 0x2E72, "DongGuan YongHao Electronics Co., LTD" }, + { 0x2E73, "Backyard Brains" }, + { 0x2E74, "Magenta Labs Inc." }, + { 0x2E75, "Shanghai Hinge Electronic Technologies Co., Ltd." }, + { 0x2E76, "Guangdong Jinrun Electronics Co., Ltd." }, + { 0x2E77, "LOGICDATA Electronics & Software Entwicklungs GmbH" }, + { 0x2E78, "ES Gear Ltd." }, + { 0x2E79, "NP System Development Co., Ltd." }, + { 0x2E7A, "Jiangsu BDSTAR Navigation Electronic Co., Ltd." }, + { 0x2E7B, "Terrada Music Score CO., Ltd." }, + { 0x2E7C, "Pyramid Solutions" }, + { 0x2E7D, "Shenzhen Xin Yong Yang Technology Co., Ltd." }, + { 0x2E7E, "ValueHD Corporation" }, + { 0x2E7F, "Aries Manufacturing - a division of Boss Tech Products Inc." }, + { 0x2E80, "Join Tek Corporation Co., Ltd." }, + { 0x2E81, "Zodiac Inflight Innovations" }, + { 0x2E82, "Sapphire Technology Limited" }, + { 0x2E83, "Ocean Tek Enterprise Co., Ltd." }, + { 0x2E84, "Sheng San Electronics (Shen Zhen) Co., Ltd." }, + { 0x2E85, "Verizon" }, + { 0x2E86, "SBO HEARING A/S" }, + { 0x2E87, "Shenzhen Injoinic Technology Co., Ltd." }, + { 0x2E88, "Huada Semiconductor Corporation Limited" }, + { 0x2E89, "Group Dekko, Inc." }, + { 0x2E8A, "Raspberry Pi (Trading) Limited" }, + { 0x2E8B, "Asia Optical International Ltd." }, + { 0x2E8C, "Aisino Wincor Manufacturing (Shanghai) Co., Ltd." }, + { 0x2E8D, "YSC Science Technique Electron (Yi Chun) Co., Ltd" }, + { 0x2E8E, "Bitatek CO., LTD" }, + { 0x2E8F, "Shenzhen Weiduli Technology Co., Ltd." }, + { 0x2E90, "Wireless Media Tech CO., Limited" }, + { 0x2E91, "Shenzhen Suprint Smart Technology Co., Ltd." }, + { 0x2E92, "bioMerieux, Inc." }, + { 0x2E93, "Shenzhen Huikeyuan Electronic Technology Co., Ltd." }, + { 0x2E94, "Graviton Inc." }, + { 0x2E95, "Scuf Gaming International, LLC" }, + { 0x2E96, "Aspect Microsystems Corp." }, + { 0x2E97, "Aerocool Advanced Technologies Corporation" }, + { 0x2E98, "Nekteck, Inc." }, + { 0x2E99, "Hynetek Semiconductor Co., Ltd" }, + { 0x2E9A, "MS Solutions Co., Ltd." }, + { 0x2E9B, "New Imaging Technologies" }, + { 0x2E9C, "Shenzhen Silkway Technology Co., Ltd." }, + { 0x2E9D, "Resolved Instruments Inc." }, + { 0x2E9E, "SoundAI Technology Co., Ltd." }, + { 0x2E9F, "EyeTech Digital Systems, Inc." }, + { 0x2EA0, "Magnescale Co., Ltd." }, + { 0x2EA1, "DASANELECTRON CO., LTD" }, + { 0x2EA2, "Ningbo Kangda Electronic Co., Ltd." }, + { 0x2EA3, "POSLAB Technology Corporation" }, + { 0x2EA4, "Hubbell Incorporated (Delaware), Wiring Device Kellems Division" }, + { 0x2EA5, "Dongguanshi Qitaiprecision Moulds Co., Ltd." }, + { 0x2EA6, "Foreign Trade Corporation dba. Technocel" }, + { 0x2EA7, "Muhanbit" }, + { 0x2EA8, "Changsha JingJia Microelectronics Co., LTD." }, + { 0x2EA9, "Yuneec International (China) Co., Ltd." }, + { 0x2EAA, "TSUME S.A." }, + { 0x2EAB, "Zong Cable Technology Co., Ltd." }, + { 0x2EAC, "Jia Yang Electronics (Dongguan) Co., Ltd." }, + { 0x2EAD, "Align Technology Inc." }, + { 0x2EAE, "Shenzhen TOMTOP Technology Co., Ltd." }, + { 0x2EAF, "microsonic co., ltd." }, + { 0x2EB0, "Commtech, Inc." }, + { 0x2EB1, "Samsung SmartThings" }, + { 0x2EB2, "Markus Klotz GmbH" }, + { 0x2EB3, "Shenzhen Tokwa Precision Technology Co., Ltd." }, + { 0x2EB4, "Beijer Automotive BV" }, + { 0x2EB5, "Dongguan HengYue Communication Technology Co., Ltd." }, + { 0x2EB6, "The Vehicle Group LTD" }, + { 0x2EB7, "Digital Divide Systems Ltd." }, + { 0x2EB8, "Yueqing Nuode Electronic Technology Co., Ltd." }, + { 0x2EB9, "SSI Computer Corp." }, + { 0x2EBA, "Shenzhen E&C Smart Link Technology Co., Ltd." }, + { 0x2EBB, "Shanghai Tuzheng Information Technology Co., Ltd." }, + { 0x2EBC, "RAIDON Technology Inc." }, + { 0x2EBD, "Netstor Technology Co., Ltd." }, + { 0x2EBE, "Delphi Automotive Systems, LLC" }, + { 0x2EBF, "Shenzhen D&D Technology Co., Ltd" }, + { 0x2EC0, "GuideTech" }, + { 0x2EC1, "Avid Identification Systems, Inc." }, + { 0x2EC2, "Loupedeck Oy" }, + { 0x2EC3, "Shenzhen Huntkey Electric Co., Ltd." }, + { 0x2EC4, "tetralux S.a.r.l." }, + { 0x2EC5, "Ariba Technology Co., LTD." }, + { 0x2EC6, "Facebook, Inc." }, + { 0x2EC7, "ITECH Electronic Co., Ltd." }, + { 0x2EC8, "Ningbo Prime Electronic Co., Ltd." }, + { 0x2EC9, "Shenzhou Rongan Technology (Beijing) Limited" }, + { 0x2ECA, "AQuantia Corp" }, + { 0x2ECB, "Zhejiang Quzhou Gelinte Wire and Cable Co., Ltd." }, + { 0x2ECC, "ASR Microelectronics (Shanghai) Co., Ltd." }, + { 0x2ECD, "EUROICC" }, + { 0x2ECE, "E-Lead Electronic Co., Ltd." }, + { 0x2ECF, "Fluo Technology Ltd." }, + { 0x2ED0, "Mind Alive Inc." }, + { 0x2ED1, "QBit Semiconductor LTD" }, + { 0x2ED2, "APOLLO GIKEN Co., Ltd." }, + { 0x2ED3, "Shenzhen Xinhongya Electronics Corporation" }, + { 0x2ED4, "Butterfly Network Inc." }, + { 0x2ED5, "QSAN Technology, Inc." }, + { 0x2ED6, "Shenzhen Xinliyang Co., Ltd." }, + { 0x2ED7, "Libratel Inc" }, + { 0x2ED8, "Dongguan Lontion Industrial Co., Ltd." }, + { 0x2ED9, "Microscopes International, LLC" }, + { 0x2EDA, "Wenzhou Haitong Communication Electronics Co., Ltd." }, + { 0x2EDB, "NeuroHabilitation Corporation" }, + { 0x2EDC, "Nippon Techno Lab., Inc." }, + { 0x2EDD, "reMarkable AS" }, + { 0x2EDE, "Technik Industrial Company Limited" }, + { 0x2EDF, "Huizhou Wealth Metal Micro Control Limited" }, + { 0x2EE0, "Pogotec Inc." }, + { 0x2EE1, "Safetrust Inc" }, + { 0x2EE2, "Kashimura Co., Ltd." }, + { 0x2EE3, "Kin Keung Electrical Mfg. Ltd." }, + { 0x2EE4, "Osprey Video, Inc." }, + { 0x2EE6, "NEURODIGITAL TECHNOLOGIES, S.L." }, + { 0x2EE7, "GOOGFIT TECH LIMITED" }, + { 0x2EE8, "Zunidata Systems, Inc." }, + { 0x2EE9, "Adigal LLC" }, + { 0x2EEA, "Loma Systems" }, + { 0x2EEB, "Jianduan Technology (Shenzhen) Co., Ltd." }, + { 0x2EEC, "Sensor Industries Limited" }, + { 0x2EED, "Shenzhen Panhui Technologies Co., Ltd." }, + { 0x2EEE, "Beijing Qunli Tiancheng Network Technology Company" }, + { 0x2EEF, "Booz Allen Hamilton" }, + { 0x2EF0, "Zhongshan Auxus Electronic Technology Co., Ltd." }, + { 0x2EF1, "Tatvik Biosystems Private Limited" }, + { 0x2EF2, "Shenzhen Goodwin Technology Co., Ltd." }, + { 0x2FB2, "Fujitsu Limited" }, + { 0x3176, "WHANAM ELECTRONICS CO., Ltd. MS division" }, + { 0x3552, "BD Consumer Healthcare" }, + { 0x3636, "INVIBRO" }, + { 0x3884, "Nicolet Biomedical Inc., a Viasys Healthcare Co." }, + { 0x3923, "National Instruments" }, + { 0x4102, "iRiver" }, + { 0x413C, "Dell Inc." }, + { 0x4234, "Powervar Inc. (UPS Products)" }, + { 0x4242, "USB Design By Example" }, + { 0x4317, "Broadcom WLAN" }, + { 0x4426, "TANITA Corporation" }, + { 0x4745, "Beijing Tiertime Technology Co., Ltd." }, + { 0x4791, "Western Digital, G-Tech" }, + { 0x4909, "GE Healthcare Bio-Sciences AB" }, + { 0x4971, "HITACHI GLOBAL STORAGE TECHNOLOGIES" }, + { 0x4B53, "Key Soft Service" }, + { 0x4C46, "DSPecialists GmbH" }, + { 0x4DDC, "Data Device Corporation" }, + { 0x5058, "ProXense, LLC" }, + { 0x5245, "RESPIRONICS, INC." }, + { 0x544D, "Transmeta Corporation" }, + { 0x5543, "UC-Logic Technology Corp." }, + { 0x5555, "Number Five, Software" }, + { 0x55AA, "OnSpec Electronic Inc." }, + { 0x5986, "BISON ELECTRONICS INC." }, + { 0x6000, "TRIDENT MICROSYSTEMS (Far East) Ltd." }, + { 0x630F, "Leapfrog Schoolhouse" }, + { 0x636C, "CoreLogic, Inc." }, + { 0x6400, "Springer Design, Inc." }, + { 0x6A75, "Shanghai Jujo Electronics Co., Ltd." }, + { 0x735F, "Beijing Techshino Technology Co., Ltd." }, + { 0x8020, "Trinity, Inc." }, + { 0x8086, "Intel Corporation" }, + { 0x8087, "Intel" }, + { 0x8829, "Beijing Daming Wuzhou Science & Technology Co., Ltd." }, + { 0x8873, "Dengineer Co., Ltd." }, + { 0x9696, "Digital Arts, Inc." }, + { 0x9710, "Moschip Semiconductor Technology" }, + { 0xA600, "ASIX s.r.o." }, + { 0xA625, "Wuhan Tianyu Information Industry Co., Ltd." }, + { 0xBEE5, "BEE SYSTEMS LLC" }, + { 0xC0B8, "Corbett Life Science" }, + { 0xC10C, "Given Imaging" }, + { 0xCACE, "CACE Technologies" }, + { 0xCC42, "Cardio Control NV" }, + { 0xEA01, "Eagle Technology" }, + { 0xEB1A, "Empia Technology, Inc." }, + { 0xFF01, "DisplayPort (VESA)" }, + { 0xFF02, "MHL, LLC" }, + { 0xFF03, "MIPI Debug" }, + { 0xFF04, "HDMI" }, + { 0x0000, "Vendor ID not listed with USB.org" } +}; + +#endif /* __VNDRLIST_H__ */ + diff --git a/tests/projects/windows/winsdk/usbview/xmake.lua b/tests/projects/windows/winsdk/usbview/xmake.lua new file mode 100644 index 000000000..5d5639429 --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/xmake.lua @@ -0,0 +1,13 @@ +-- add rules +add_rules("mode.debug", "mode.release") + +-- define target +target("usbview") + + -- windows application + add_rules("win.sdk.application") + + -- add files + add_files("*.c", "*.rc") + add_files("xmlhelper.cpp", {rule = "win.sdk.dotnet"}) + diff --git a/tests/projects/windows/winsdk/usbview/xmlhelper.cpp b/tests/projects/windows/winsdk/usbview/xmlhelper.cpp new file mode 100644 index 000000000..bac7d797b --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/xmlhelper.cpp @@ -0,0 +1,3235 @@ +/*++ + + Copyright (c) 1997-2011 Microsoft Corporation + + Module Name: + + XMLHELPER.CPP + +Abstract: + +This source file contains helper APIs for reading writing XML + +Environment: + +user mode + +Revision History: + +05-05-11 : created + +--*/ + +/***************************************************************************** + I N C L U D E S + *****************************************************************************/ +#include "uvcview.h" +#include "h264.h" +#include "xmlhelper.h" + +// usbschema.hpp is autogenerated from schema during build PASS0 +#include "usbschema.hpp" + +// Include code analysis suppressions +#include "codeanalysis.h" + +/***************************************************************************** + D E F I N E S + *****************************************************************************/ +#define COBJMACROS + +#define PACHAR_TO_STRING(X) ((X != NULL)? gcnew String(Marshal::PtrToStringAnsi((IntPtr) X )):nullptr) +#define PWCHAR_TO_STRING(X) ((X != NULL)? gcnew String(Marshal::PtrToStringUni((IntPtr) X )):nullptr) + +#define MAX_STRING_DESCRIPTOR_LENGTH 512 +#define STRING_DESCRIPTOR_EN_LANGUAGE_ID 0x0409 +#define DEVICE_DESCRIPTOR_LENGTH 18 + +#define SERVICE_EHCI "usbehci" +#define SERVICE_XHCI "usbxhci" +#define SERVICE_OHCI "usbohci" +#define SERVICE_UHCI "usbuhci" + +#define USB_1_1 "USB 1.1" +#define USB_2_0 "USB 2.0" +#define USB_3_0 "USB 3.0" +#define USB_GENERIC "USB GENERIC (UNKNOWN)" + +/***************************************************************************** + N A M E S P A C E S + *****************************************************************************/ + +using namespace System; +using namespace System::IO; +using namespace System::Runtime::InteropServices; +using namespace System::Collections; +using namespace Microsoft::Kits::Samples::Usb; + + +/***************************************************************************** + G L O B A L S + *****************************************************************************/ + +namespace Microsoft +{ + namespace Kits + { + namespace Samples + { + namespace Usb + { + public ref class XmlGlobal sealed + { + private: + static XmlGlobal ^ pInstance = gcnew XmlGlobal(); + + // Empty private constructor + XmlGlobal() + { + } + + public: + // + // Globals for XML view + // + property UvcViewAll ^ ViewAll; + property bool XmlViewInitialized; + + // + // Stack of parents of a given node. This is used for finding + // where a given object should be added + // + +#if CODE_ANALYSIS + // ParentStack need not be constant since we will only have one instance of this object + [SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible")] +#endif + static Stack ^ ParentStack = gcnew Stack(); + + static XmlGlobal ^ Instance() + { + return pInstance; + } + }; + }; + }; + }; +}; + +#define gXmlView ((XmlGlobal::Instance())->ViewAll->UvcView) +#define gXmlViewInitialized ((XmlGlobal::Instance())->XmlViewInitialized) +#define gXmlStack ((XmlGlobal::Instance())->ParentStack) + +/***************************************************************************** + D E C L A R A T I O N S + *****************************************************************************/ + +String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly); +void XmlAddHostControllerPowerMapping( UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo); +String ^ XmlGetDeviceClassString(UCHAR deviceClass); +void XmlAddHostControllerPowerMapping(UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo); +void XmlAddHub30Descriptor(Hub30DescriptorType ^hub30Desc, PUSB_30_HUB_DESCRIPTOR hub30Descriptor); +void XmlAddHubDescriptor(HubDescriptorType ^hubDesc, PUSB_HUB_DESCRIPTOR hubDescriptor); +void XmlAddPortConnectorProps(PortConnectorType ^portXmlProps, PUSB_PORT_CONNECTOR_PROPERTIES portProps); +void XmlAddHubCharacteristics(HubInformationType ^hubI, WORD hubChar); +HRESULT XmlAddHubNodeInformation(HubNodeInformationType ^ni, PUSB_NODE_INFORMATION nodeInfo); +HRESULT XmlAddHubInformationEx(HubInformationExType ^ex, PUSB_HUB_INFORMATION_EX hubInfoEx); +HRESULT XmlAddHubCapabilitiesEx(HubCapabilitiesExType ^ex, USB_HUB_CAPABILITIES_EX hubCapEx); +ExternalHubType ^ AddExternalHub(Object ^parent); +NoDeviceType ^ AddDisconnectedPort(Object ^parent); +UsbDeviceType ^ AddUsbDevice(Object ^parent); +void XmlAddEndpointDescriptor( + EndpointDescriptorType ^usbXmlEndpointDescriptor, + PUSB_ENDPOINT_DESCRIPTOR endPointDescriptor, + UCHAR connectionSpeed); +void XmlAddPipeInformation( + array< UsbPipeInfoType ^> ^ usbXmlPipeInfoList, + PUSB_PIPE_INFO pipeInfo, + ULONG numPipes, + UCHAR connectionSpeed); +void XmlAddUsbDeviceDescriptor( + UsbDeviceDescriptorType ^usbXmlDeviceDescriptor, + PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor); +void XmlAddConfigurationDescriptor( + UsbConfigurationDescriptorType ^ confXmlDesc, + PUSBDEVICEINFO deviceInfo, + PUSB_CONFIGURATION_DESCRIPTOR configDesc, + PSTRING_DESCRIPTOR_NODE stringDesc); +void XmlAddDeviceQualDescriptor( + UsbDeviceQualifierDescriptorType ^ qualXmlDesc, + PUSB_DEVICE_QUALIFIER_DESCRIPTOR qualDesc); +void XmlAddDeviceConfiguration( + UsbDeviceConfigurationType ^ confXmlDesc, + PUSBDEVICEINFO deviceInfo, + PUSB_CONFIGURATION_DESCRIPTOR configDesc, + PSTRING_DESCRIPTOR_NODE stringDesc, + int numInterfaces); +void XmlAddConnectionInfoSt( + NodeConnectionInfoExStructType ^xmlConnectionInfoSt, + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, + PDEVICE_INFO_NODE pNode); +String ^ XmlGetLangIdString(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc); +String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly); +String ^ XmlGetDeviceClassString(UCHAR deviceClass); +bool XmlAddDeviceClassDetails( + UsbDeviceClassDetailsType ^ deviceDetails, + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, + PUSBDEVICEINFO deviceInfo); +void XmlAddConnectionInfo( + NodeConnectionInfoExType ^xmlConnectionInfo, + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, + PUSBDEVICEINFO deviceInfo, + PSTRING_DESCRIPTOR_NODE stringDesc, + PDEVICE_INFO_NODE pNode); +void XmlAddHidDescriptor( + UsbDeviceHidDescriptorType ^ hidXmlDesc, + PUSB_HID_DESCRIPTOR hidDesc); +void XmlAddDeviceInterfaceDescriptor( + UsbDeviceInterfaceDescriptorType ^ ifXmlDesc, + PUSB_INTERFACE_DESCRIPTOR ifDesc, + PSTRING_DESCRIPTOR_NODE stringDesc); +void XmlAddOTGDescriptor( + UsbDeviceOTGDescriptorType ^ otgXmlDesc, + PUSB_OTG_DESCRIPTOR otgDesc); +void XmlAddIADDescriptor( + UsbDeviceIADDescriptorType ^ iadXmlDesc, + PUSB_IAD_DESCRIPTOR iadDesc, + PSTRING_DESCRIPTOR_NODE stringDesc, + int nInterfaces); +array < UsbDeviceConfigurationType ^> ^ XmlGetConfigDescriptors( + PUSBDEVICEINFO deviceInfo, + PUSB_CONFIGURATION_DESCRIPTOR configDescs, + PSTRING_DESCRIPTOR_NODE stringDesc); +UsbBosDescriptorType ^ XmlGetBosDescriptor( + PUSB_BOS_DESCRIPTOR bosDesc, + PSTRING_DESCRIPTOR_NODE stringDesc + ); +UsbDeviceClassType ^ XmlGetDeviceClass(UCHAR deviceClass, UCHAR deviceSubClass, UCHAR deviceProtocol); +UsbDeviceUnknownDescriptorType ^ XmlGetUnknownDescriptor( + PUSB_COMMON_DESCRIPTOR unknownDesc + ); +UsbUsb20ExtensionDescriptorType ^ XmlGetUsb20CapabilityExtensionDescriptor( + PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR capDesc + ); +UsbSuperSpeedExtensionDescriptorType ^ XmlGetSuperSpeedCapabilityExtensionDescriptor( + PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR capDesc + ); +UsbDispContIdCapExtDescriptorType ^ XmlGetContainerIdCapabilityExtensionDescriptor( + PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR capDesc + ); +UsbBillboardCapabilityDescriptorType ^ XmlGetBillboardCapabilityDescriptor( + PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR capDesc, + PSTRING_DESCRIPTOR_NODE stringDesc + ); + +/***************************************************************************** + D E F I N I T I O N S + *****************************************************************************/ + +/***************************************************************************** + XmlNotifyEndOfNodeList + + This function is called back by WalkTreeTopDown() function to notify us + that there are no more children to add for the current parent + + *****************************************************************************/ +VOID XmlNotifyEndOfNodeList(PVOID pContext) +{ + UNREFERENCED_PARAMETER(pContext); + + if (gXmlStack != nullptr && gXmlStack->Count > 0) + { + // Remove the last parent on the stack + gXmlStack->Pop(); + } +} + +/***************************************************************************** + + XmlAddHostControllerPowerMapping() + + add power info to xml structure + *****************************************************************************/ +void XmlAddHostControllerPowerMapping(UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo) +{ + int i, powerState; + PUSB_POWER_INFO pUPI = usbHCPowerInfo; + UsbHCPowerStateType ^ pwrState = nullptr; + + xmlPwrInfo->PowerMap = gcnew array (WdmUsbPowerSystemShutdown); + + for(i = 0, powerState = WdmUsbPowerSystemWorking; powerState < WdmUsbPowerSystemShutdown; i++, powerState++, pUPI++) + { + xmlPwrInfo->PowerMap[i] = gcnew UsbHCPowerStateType(); + pwrState = xmlPwrInfo->PowerMap[i]; + pwrState->SystemState = PACHAR_TO_STRING(GetPowerStateString(pUPI->SystemState)); + pwrState->HostControllerState = PACHAR_TO_STRING(GetPowerStateString(pUPI->HcDevicePowerState)); + pwrState->HubState = PACHAR_TO_STRING(GetPowerStateString(pUPI->RhDevicePowerState)); + pwrState->CanWakeUp = pUPI->CanWakeup? true:false; + pwrState->IsPowered = pUPI->IsPowered? true:false; + } + + xmlPwrInfo->LastSleepState = PACHAR_TO_STRING(GetPowerStateString(pUPI->LastSystemSleepState)); + return; +} + +/***************************************************************************** + + XmlAddHostController() + + Add an host controller to XML view + *****************************************************************************/ + +HRESULT XmlAddHostController(PSTR hcName, PUSBHOSTCONTROLLERINFO hcInfo) +{ + HRESULT hr = S_OK; + + UNREFERENCED_PARAMETER(hcName); + + HostControllerType ^ hc = nullptr; + // + // Check if the USB Tree array has been initialized + // It would have been great if XSD had a way of generating a list instead of array, but it does not + // So we have to do array.Resize everytime + // + if (gXmlView->UsbTree == nullptr) + { + // This is the first time we are being called, initialize the array with 1 element + gXmlView->UsbTree = gcnew array(1); + gXmlView->UsbTree[0] = gcnew HostControllerType(); + hc = gXmlView->UsbTree[0]; + } + else + { + // Create a new array every time as Array.Resize does not seem to work in our case (CLI) + // We do this using ArrayList. + ArrayList ^hcList = gcnew ArrayList; + hcList->AddRange(gXmlView->UsbTree); + hc = gcnew HostControllerType(); + hcList->Add(hc); + gXmlView->UsbTree = reinterpret_cast^> (hcList->ToArray(HostControllerType::typeid)); + } + + if (hc != nullptr) + { + ULONG debugPort = 0; + + UsbHCDeviceInfoType ^ ci = nullptr; + UsbHCPowerStateMappingType ^ pm = nullptr; + + if (NULL != hcInfo->UsbDeviceProperties) + { + hc->HwId = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->HwId); + hc->DeviceId = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceId); + hc->ServiceName = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->Service); + hc->DeviceName = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceDesc); + hc->DeviceClass = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceClass); + + bool foundUsbProtocol = false; + if (hcInfo->UsbDeviceProperties->Service != NULL) + { + foundUsbProtocol = true; + + if (_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_OHCI) == 0) + { + hc->UsbProtocol = gcnew String(USB_1_1); + } + else if(_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_EHCI) == 0 || + _stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_UHCI) == 0) + { + hc->UsbProtocol = gcnew String(USB_2_0); + } + else if (_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_XHCI) == 0) + { + hc->UsbProtocol = gcnew String(USB_3_0); + } + else + { + foundUsbProtocol = false; + } + } + + if (!foundUsbProtocol) + { + // If protocol lookup failed based on service name, try Controller flavor + if(NULL != hcInfo->ControllerInfo) + { + USB_CONTROLLER_FLAVOR flavor = hcInfo->ControllerInfo->ControllerFlavor; + + if(flavor == USB_HcGeneric) + { + hc->UsbProtocol = gcnew String(USB_GENERIC); + } + else if(flavor >= OHCI_Generic && flavor < UHCI_Generic) + { + hc->UsbProtocol = gcnew String(USB_1_1); + } + else if(flavor >= UHCI_Generic && flavor <= EHCI_Generic) + { + hc->UsbProtocol = gcnew String(USB_2_0); + } + else if(flavor > EHCI_Generic) + { + hc->UsbProtocol = gcnew String(USB_3_0); + } + } + } + } + + hc->ControllerInfo = gcnew UsbHCDeviceInfoType(); + hc->PowerMapping = gcnew UsbHCPowerStateMappingType(); + ci = hc->ControllerInfo; + pm = hc->PowerMapping; + + ci->VendorId = hcInfo->VendorID; + ci->DeviceId = hcInfo->DeviceID; + ci->DriverKey = PACHAR_TO_STRING(hcInfo->DriverKey); + ci->SubSysId = hcInfo->SubSysID; + ci->Revision = hcInfo->Revision; + + if(NULL != hcInfo->ControllerInfo) + { + ci->NumberOfRootPorts = hcInfo->ControllerInfo->NumberOfRootPorts; + ci->ControllerFlavor = hcInfo->ControllerInfo->ControllerFlavor; + ci->PortSwitchingEnabled = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_FLAG_PORT_POWER_SWITCHING)? true: false; + ci->SelectiveSuspendEnabled = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_FLAG_SEL_SUSPEND)? true: false; + ci->LegacyBios = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_LEGACY_BIOS)? true: false; + ci->ControllerFlavorString = PACHAR_TO_STRING(GetControllerFlavorString(hcInfo->ControllerInfo->ControllerFlavor)); + } + + // Add power mappings + XmlAddHostControllerPowerMapping(pm, (PUSB_POWER_INFO) (&(hcInfo->USBPowerInfo[0]))); + + // Add debug port + debugPort = GetEhciDebugPort(hcInfo->VendorID, hcInfo->DeviceID); + if (debugPort > 0) + { + ci->DebugPort = debugPort; + } + + gXmlStack->Push(hc); + + } + else + { + hr = E_FAIL; + } + + return hr; +} + +/***************************************************************************** + + XmlAddHub30Descriptor() + + Adds the hub 3.0 descriptor to the given hub object + *****************************************************************************/ +void XmlAddHub30Descriptor(Hub30DescriptorType ^hub30Desc, PUSB_30_HUB_DESCRIPTOR hub30Descriptor) +{ + + if (nullptr != hub30Desc && NULL != hub30Descriptor) + { + hub30Desc->Length = hub30Descriptor->bLength; + hub30Desc->DescriptorType = hub30Descriptor->bDescriptorType; + hub30Desc->NumberOfPorts = hub30Descriptor->bNumberOfPorts; + hub30Desc->HubCharacteristics = hub30Descriptor->wHubCharacteristics; + hub30Desc->PowerOntoPowerGood = hub30Descriptor->bPowerOnToPowerGood; + hub30Desc->HubControlCurrent = hub30Descriptor->bHubControlCurrent; + hub30Desc->HubHdrDecLat = hub30Descriptor->bHubHdrDecLat; + hub30Desc->DeviceRemovable = hub30Descriptor->DeviceRemovable; + } +} + +/***************************************************************************** + + XmlAddHubDescriptor() + + Adds the hub descriptor to the given hub object + *****************************************************************************/ +void XmlAddHubDescriptor(HubDescriptorType ^hubDesc, PUSB_HUB_DESCRIPTOR hubDescriptor) +{ + if (nullptr != hubDesc && NULL != hubDescriptor) + { + hubDesc->DescriptorLength = hubDescriptor->bDescriptorLength; + hubDesc->DescriptorType = hubDescriptor->bDescriptorType; + hubDesc->NumberOfPorts = hubDescriptor->bNumberOfPorts; + hubDesc->PowerOntoPowerGood = hubDescriptor->bPowerOnToPowerGood; + hubDesc->HubControlCurrent = hubDescriptor->bHubControlCurrent; + } +} + +/***************************************************************************** + + XmlAddPortConnectorProps() + + Adds the port connector properties to XML file + *****************************************************************************/ +void XmlAddPortConnectorProps(PortConnectorType ^portXmlProps, PUSB_PORT_CONNECTOR_PROPERTIES portProps) +{ + if (NULL != portProps) + { + portXmlProps->UsbPortProperties = gcnew UsbPortPropertiesType(); + + portXmlProps->ConnectionIndex = portProps->ConnectionIndex; + portXmlProps->ActualLength = portProps->ActualLength; + portXmlProps->CompanionIndex = portProps->CompanionIndex; + portXmlProps->CompanionPortNumber = portProps->CompanionPortNumber; + portXmlProps->CompanionHubSymbolicLinkName = PWCHAR_TO_STRING(portProps->CompanionHubSymbolicLinkName); + + portXmlProps->UsbPortProperties->PortIsUserConnectable = portProps->UsbPortProperties.PortIsUserConnectable? true:false; + portXmlProps->UsbPortProperties->PortIsDebugCapable = portProps->UsbPortProperties.PortIsDebugCapable? true:false; + } + return; +} + +/***************************************************************************** + + XmlAddConnectionInfoV2() + + Adds the V2 connection info structure + *****************************************************************************/ +void XmlAddConnectionInfoV2(NodeConnectionInfoExV2Type ^ connectionXmlInfo, PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfo) +{ + if (NULL != connectionInfo) + { + connectionXmlInfo->ConnectionIndex = connectionInfo->ConnectionIndex; + connectionXmlInfo->Length = connectionInfo->Length; + + connectionXmlInfo->Usb110Supported = connectionInfo->SupportedUsbProtocols.Usb110? true:false; + connectionXmlInfo->Usb200Supported = connectionInfo->SupportedUsbProtocols.Usb200? true:false; + connectionXmlInfo->Usb300Supported = connectionInfo->SupportedUsbProtocols.Usb300? true:false; + + connectionXmlInfo->DeviceIsOperatingAtSuperSpeedOrHigher = + connectionInfo->Flags.DeviceIsOperatingAtSuperSpeedOrHigher; + + connectionXmlInfo->DeviceIsSuperSpeedCapableOrHigher = + connectionInfo->Flags.DeviceIsSuperSpeedCapableOrHigher; + + connectionXmlInfo->DeviceIsOperatingAtSuperSpeedPlusOrHigher = + connectionInfo->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher; + + connectionXmlInfo->DeviceIsSuperSpeedPlusCapableOrHigher = + connectionInfo->Flags.DeviceIsSuperSpeedPlusCapableOrHigher; + + } + return; +} + +/***************************************************************************** + + XmlAddHubCharacteristics() + + Adds the hub characteristics to the given hub object + *****************************************************************************/ +void XmlAddHubCharacteristics(HubInformationType ^hubI, WORD hubChar) +{ + HubCharacteristicsType ^hubC = nullptr; + + hubI->HubCharacteristics = gcnew HubCharacteristicsType(); + hubC = hubI->HubCharacteristics; + hubC->HubCharacteristicsValue = hubChar; + switch(hubChar & 0x3) + { + case 0x0: + hubC->PowerSwitching = gcnew String("Ganged"); + break; + case 0x1: + hubC->PowerSwitching = gcnew String("Individual"); + break; + case 0x2: + case 0x3: + hubC->PowerSwitching = gcnew String("None"); + break; + default: + hubC->PowerSwitching = gcnew String("Unknown"); + } + + hubC->CompoundDevice = (hubChar & 0x4)? true:false; + + switch(hubChar & 0x18) + { + case 0x0: + hubC->OverCurrentProtection = gcnew String("Global"); + break; + case 0x8: + hubC->OverCurrentProtection = gcnew String("Individual"); + break; + case 0x10: + case 0x18: + hubC->OverCurrentProtection = gcnew String("No protection, bus power only"); + break; + default: + hubC->OverCurrentProtection = gcnew String("Unknown"); + } +} + +/***************************************************************************** + + XmlAddHubNodeInformation() + + Adds the node information to the hub object + *****************************************************************************/ +HRESULT XmlAddHubNodeInformation(HubNodeInformationType ^ni, PUSB_NODE_INFORMATION nodeInfo) +{ + PUSB_HUB_INFORMATION hubInfo = NULL; + + if (NULL == nodeInfo) + { + return E_FAIL; + } + + hubInfo = &(nodeInfo->u.HubInformation); + ni->HubNode = static_cast (nodeInfo->NodeType); + + ni->HubInformation = gcnew HubInformationType(); + ni->HubInformation->IsRootHub = true; + ni->HubInformation->IsBusPowered = hubInfo->HubIsBusPowered? true:false; + + // Add hub characteristics + XmlAddHubCharacteristics(ni->HubInformation, hubInfo->HubDescriptor.wHubCharacteristics); + // Add descriptor + ni->HubInformation->HubDescriptor = gcnew HubDescriptorType(); + XmlAddHubDescriptor(ni->HubInformation->HubDescriptor, &(hubInfo->HubDescriptor)); + + return S_OK; +} + +/***************************************************************************** + + XmlAddHubInformation() + + Adds the node information to the hub object + *****************************************************************************/ +HRESULT XmlAddHubInformationEx(HubInformationExType ^ex, PUSB_HUB_INFORMATION_EX hubInfoEx) +{ + HubDescriptorType ^hubDesc = nullptr; + Hub30DescriptorType ^hub30Desc = nullptr; + + if (NULL == hubInfoEx) + { + return E_FAIL; + } + + ex->HubType = static_cast (hubInfoEx->HubType); + ex->HighestPortNumber = hubInfoEx->HighestPortNumber; + switch(hubInfoEx->HubType) + { + case UsbRootHub: + case Usb20Hub: + ex->HubDescriptor = hubDesc = gcnew HubDescriptorType(); + XmlAddHubDescriptor(hubDesc, &(hubInfoEx->u.UsbHubDescriptor)); + break; + case Usb30Hub: + ex->Hub30Descriptor = hub30Desc = gcnew Hub30DescriptorType(); + XmlAddHub30Descriptor(hub30Desc, &(hubInfoEx->u.Usb30HubDescriptor)); + break; + } + return S_OK; +} + +/***************************************************************************** + + XmlAddHubCapabilitiesEx() + + Adds the hub capabilities information to the hub object + *****************************************************************************/ +HRESULT XmlAddHubCapabilitiesEx(HubCapabilitiesExType ^ex, PUSB_HUB_CAPABILITIES_EX hubCapEx) +{ + if(NULL != hubCapEx) + { + ex->HubIsHighSpeedCapable = hubCapEx->CapabilityFlags.HubIsHighSpeedCapable?true:false; + ex->HubIsHighSpeed = hubCapEx->CapabilityFlags.HubIsHighSpeed?true:false; + ex->HubIsMultiTtCapable = hubCapEx->CapabilityFlags.HubIsMultiTtCapable?true:false; + ex->HubIsMultiTt = hubCapEx->CapabilityFlags.HubIsMultiTt?true:false; + ex->HubIsRoot = hubCapEx->CapabilityFlags.HubIsRoot?true:false; + ex->HubIsArmedWakeOnConnect = hubCapEx->CapabilityFlags.HubIsArmedWakeOnConnect?true:false; + ex->HubIsBusPowered = hubCapEx->CapabilityFlags.HubIsBusPowered?true:false; + } + return S_OK; +} + +/***************************************************************************** + + ExternalHubType ^ AddExternalHub(Object ^parent) + + This routine finds the type of the parent and adds an external hub object to the + parent's list of external hubs. The newly created object is returned + We are using arrays insted of better types of collections becaused the code generated + by xsd.exe does not support other types. + *****************************************************************************/ +ExternalHubType ^ AddExternalHub(Object ^parent) +{ + RootHubType ^ rhParent = nullptr; + ExternalHubType ^ ehParent = nullptr; + array ^ exHubArray = nullptr; + ExternalHubType ^ exHub = nullptr; + boolean arrayCreated = false; + + // An external hub can be connected to a Root Hub or another External Hub + // We need to determine the type of the object. + + // Try root hub first + + rhParent = dynamic_cast (parent); + if (rhParent == nullptr) + { + // RootHub cast was not successfult, try external hub + ehParent = dynamic_cast (parent); + if (ehParent != nullptr) + { + // External hub parent + if (ehParent->ExternalHub == nullptr) + { + // First hub in the list of external hubs + ehParent->ExternalHub = gcnew array (1); + arrayCreated = true; + } + exHubArray = ehParent->ExternalHub; + } + + } + else + { + // Parent is a root hub + if (rhParent->ExternalHub == nullptr) + { + // First hub in root hub list + rhParent->ExternalHub = gcnew array(1); + arrayCreated = true; + } + exHubArray = rhParent->ExternalHub; + } + + if (exHubArray != nullptr) + { + if (arrayCreated) + { + // We created the array in this function, so we use offset 0 + exHubArray[0] = gcnew ExternalHubType(); + exHub = exHubArray[0]; + } + else + { + // The array was already present, we need to do elaborate things + // as array.resize does not work. + ArrayList ^exList = gcnew ArrayList(); + exList->AddRange(exHubArray); + exHub = gcnew ExternalHubType(); + exList->Add(exHub); + + if (rhParent != nullptr) + { + rhParent->ExternalHub = reinterpret_cast^> (exList->ToArray(ExternalHubType::typeid)); + } + else + { + ehParent->ExternalHub = reinterpret_cast^> (exList->ToArray(ExternalHubType::typeid)); + } + } + } + return exHub; +} +/***************************************************************************** + + NoDeviceType ^ AddDisconnectedPort(Object ^parent) + + This routine finds the type of the parent and adds a empty port connection object to the + parent's list of devices. The newly created object is returned + We are using arrays insted of better types of collections becaused the code generated + by xsd.exe does not support other types. + *****************************************************************************/ +NoDeviceType ^ AddDisconnectedPort(Object ^parent) +{ + RootHubType ^ rhParent = nullptr; + ExternalHubType ^ ehParent = nullptr; + array ^ devicesArray = nullptr; + NoDeviceType ^ noD = nullptr; + boolean arrayCreated = false; + + // An external hub can be connected to a Root Hub or another External Hub + // We need to determine the type of the object. + + // Try RH first + + rhParent = dynamic_cast (parent); + if (rhParent == nullptr) + { + // RootHub cast was not successfult, try external hub + ehParent = dynamic_cast (parent); + if (ehParent != nullptr) + { + // External hub parent + if (ehParent->NoDevice == nullptr) + { + // First hub in the list of external hubs + ehParent->NoDevice = gcnew array (1); + arrayCreated = true; + } + devicesArray = ehParent->NoDevice; + } + + } + else + { + // Parent is a root hub + if (rhParent->NoDevice == nullptr) + { + // First hub in root hub list + rhParent->NoDevice = gcnew array(1); + arrayCreated = true; + } + devicesArray = rhParent->NoDevice; + } + + if (devicesArray != nullptr) + { + if (arrayCreated) + { + // We created the array in this function, so we use offset 0 + devicesArray[0] = gcnew NoDeviceType(); + noD = devicesArray[0]; + } + else + { + // The array was already present, we need to do elaborate things + // as array.resize does not work. + ArrayList ^exList = gcnew ArrayList(); + exList->AddRange(devicesArray); + noD = gcnew NoDeviceType(); + exList->Add(noD); + + if (rhParent != nullptr) + { + rhParent->NoDevice = reinterpret_cast^> (exList->ToArray(NoDeviceType::typeid)); + } + else + { + ehParent->NoDevice = reinterpret_cast^> (exList->ToArray(NoDeviceType::typeid)); + } + } + } + return noD; +} + +/***************************************************************************** + + UsbDeviceType ^ AddUsbDevice(Object ^parent) + + This routine finds the type of the parent and adds a port connection object to the + parent's list of port connectors. The newly created object is returned + We are using arrays insted of better types of collections becaused the code generated + by xsd.exe does not support other types. + *****************************************************************************/ +UsbDeviceType ^ AddUsbDevice(Object ^parent) +{ + RootHubType ^ rhParent = nullptr; + ExternalHubType ^ ehParent = nullptr; + array ^ devicesArray = nullptr; + UsbDeviceType ^ usbD = nullptr; + boolean arrayCreated = false; + + // An external hub can be connected to a Root Hub or another External Hub + // We need to determine the type of the object. + + // Try RH first + + rhParent = dynamic_cast (parent); + if (rhParent == nullptr) + { + // RootHub cast was not successfult, try external hub + ehParent = dynamic_cast (parent); + if (ehParent != nullptr) + { + // External hub parent + if (ehParent->UsbDevice == nullptr) + { + // First hub in the list of external hubs + ehParent->UsbDevice = gcnew array (1); + arrayCreated = true; + } + devicesArray = ehParent->UsbDevice; + } + + } + else + { + // Parent is a root hub + if (rhParent->UsbDevice == nullptr) + { + // First hub in root hub list + rhParent->UsbDevice = gcnew array(1); + arrayCreated = true; + } + devicesArray = rhParent->UsbDevice; + } + + if (devicesArray != nullptr) + { + if (arrayCreated) + { + // We created the array in this function, so we use offset 0 + devicesArray[0] = gcnew UsbDeviceType(); + usbD = devicesArray[0]; + } + else + { + // The array was already present, we need to do elaborate things + // as array.resize does not work. + ArrayList ^exList = gcnew ArrayList(); + exList->AddRange(devicesArray); + usbD = gcnew UsbDeviceType(); + exList->Add(usbD); + + if (rhParent != nullptr) + { + rhParent->UsbDevice = reinterpret_cast^> (exList->ToArray(UsbDeviceType::typeid)); + } + else + { + ehParent->UsbDevice = reinterpret_cast^> (exList->ToArray(UsbDeviceType::typeid)); + } + } + } + return usbD; +} + +/***************************************************************************** + + XmlAddIADDescriptor() + + This routine adds usb IAD descriptor + *****************************************************************************/ +void XmlAddIADDescriptor( + UsbDeviceIADDescriptorType ^ iadXmlDesc, + PUSB_IAD_DESCRIPTOR iadDesc, + PSTRING_DESCRIPTOR_NODE stringDesc, + int nInterfaces) +{ + if (NULL == iadDesc || NULL == stringDesc) + { + return; + } + + // Update structure fields + iadXmlDesc->BLength = iadDesc->bLength; + iadXmlDesc->BDescriptorType = iadDesc->bDescriptorType; + iadXmlDesc->BFirstInterface = iadDesc->bFirstInterface; + iadXmlDesc->BInterfaceCount = iadDesc->bInterfaceCount; + iadXmlDesc->BFunctionClass = iadDesc->bFunctionClass; + iadXmlDesc->BFunctionSubclass = iadDesc->bFunctionSubClass; + iadXmlDesc->BFunctionProtocol = iadDesc->bFunctionProtocol; + iadXmlDesc->IFunction = iadDesc->iFunction; + + // Validate fields + if (iadDesc->bInterfaceCount == 1) + { + iadXmlDesc->InterfaceError = gcnew String("ERROR: bInterfaceCount must be greater than 1"); + } + if (nInterfaces < iadDesc->bFirstInterface + iadDesc->bInterfaceCount) + { + iadXmlDesc->InterfaceError = gcnew String("ERROR: The total number of interfaces"); + iadXmlDesc->InterfaceError += nInterfaces; + iadXmlDesc->InterfaceError += " must be greater than or equal to the highest linked interface number (base "; + iadXmlDesc->InterfaceError += iadDesc->bFirstInterface; + iadXmlDesc->InterfaceError += " + count "; + iadXmlDesc->InterfaceError += iadDesc->bInterfaceCount; + iadXmlDesc->InterfaceError += " = "; + iadXmlDesc->InterfaceError += (iadDesc->bFirstInterface + iadDesc->bInterfaceCount); + iadXmlDesc->InterfaceError += " )"; + } + if (iadDesc->bFunctionClass == 0) + { + iadXmlDesc->FunctionClassError = gcnew String("ERROR: bFunctionClass contains an illegal value 0"); + } + + iadXmlDesc->FunctionDetails = XmlGetDeviceClass( + iadDesc->bFunctionClass, + iadDesc->bFunctionSubClass, + iadDesc->bFunctionProtocol); + + // Protocol check + if (iadDesc->bFunctionClass == USB_DEVICE_CLASS_VIDEO) + { + if (iadDesc->bFunctionProtocol != PC_PROTOCOL_UNDEFINED) + { + iadXmlDesc->Protocol= gcnew String("WARNING: Protocol must be set to PC_PROTOCOL_UNDEFINED"); + iadXmlDesc->Protocol+= " for this class but is set to: "; + iadXmlDesc->Protocol+= iadDesc->bFunctionProtocol; + } + else + { + iadXmlDesc->Protocol = gcnew String("PC_PROTOCOL_UNDEFINED protocol"); + } + } + + if (iadDesc->iFunction) + { + // Add String descriptor + iadXmlDesc->StringDesc = XmlGetStringDescriptor( + iadDesc->iFunction, + stringDesc, + false); + } + + return; +} + +/***************************************************************************** + + XmlAddOTGDescriptor() + + This routine adds usb OTG descriptor + *****************************************************************************/ +void XmlAddOTGDescriptor( + UsbDeviceOTGDescriptorType ^ otgXmlDesc, + PUSB_OTG_DESCRIPTOR otgDesc) +{ + if (NULL == otgDesc) + { + return; + } + + otgXmlDesc->BLength = otgDesc->bLength; + otgXmlDesc->BDescriptorType = otgDesc->bDescriptorType; + otgXmlDesc->BmAttributes = otgDesc->bmAttributes; + + // Add descriptive fields + switch (otgDesc->bmAttributes) + { + case 0: + break; + case 1: + otgXmlDesc->AttributesString = gcnew String("SRP support"); + break; + case 2: + otgXmlDesc->AttributesString = gcnew String("HNP support"); + break; + case 3: + otgXmlDesc->AttributesString = gcnew String("SRP and HNP support"); + break; + default: + otgXmlDesc->AttributesString = gcnew String("ERROR: bmAttributes bits 2-7 are reserved should be 0)"); + break; + } + return; +} + +/***************************************************************************** + + XmlAddHidDescriptor() + + This routine adds usb HID descriptor + *****************************************************************************/ +void XmlAddHidDescriptor( + UsbDeviceHidDescriptorType ^ hidXmlDesc, + PUSB_HID_DESCRIPTOR hidDesc + ) +{ + int i = 0; + + if (NULL == hidDesc) + { + return; + } + + hidXmlDesc->BLength = hidDesc->bLength; + hidXmlDesc->BDescriptorType = hidDesc->bDescriptorType; + hidXmlDesc->BcdHID = hidDesc->bcdHID; + hidXmlDesc->BCountryCode = hidDesc->bCountryCode; + hidXmlDesc->BNumDescriptors = hidDesc->bNumDescriptors; + + // Add optional descriptors + if (hidDesc->bNumDescriptors > 0) + { + hidXmlDesc->OptionalDescriptor = gcnew array (hidDesc->bNumDescriptors); + for(i=0; i < hidDesc->bNumDescriptors; i++) + { + hidXmlDesc->OptionalDescriptor[i] = gcnew UsbDeviceHidOptionalDescriptorsType(); + hidXmlDesc->OptionalDescriptor[i]->BDescriptorType = hidDesc->OptionalDescriptors[i].bDescriptorType; + hidXmlDesc->OptionalDescriptor[i]->WDescriptorLength = hidDesc->OptionalDescriptors[i].wDescriptorLength; + } + } + return; +} + +/***************************************************************************** + + XmlGetUnknownDescriptor() + + This routine gets a usb unknown descriptor object form unknown descriptor + *****************************************************************************/ +UsbDeviceUnknownDescriptorType ^ XmlGetUnknownDescriptor( + PUSB_COMMON_DESCRIPTOR unknownDesc + ) +{ + int i = 0; + UsbDeviceUnknownDescriptorType ^ unknownXmlDesc = nullptr; + + if (NULL == unknownDesc) + { + return nullptr; + } + + unknownXmlDesc = gcnew UsbDeviceUnknownDescriptorType(); + unknownXmlDesc->BLength = unknownDesc->bLength; + unknownXmlDesc->BDescriptorType = unknownDesc->bDescriptorType; + + // Add optional descriptors + if (unknownDesc->bLength > 0) + { + unknownXmlDesc->UnknownDescriptor = gcnew String("Unknown descriptor->"); + for(i=0; i < unknownDesc->bLength; i++) + { + unknownXmlDesc->UnknownDescriptor += String::Format("0x{0:X} ", ((PUCHAR) unknownDesc)[i]); + } + } + return unknownXmlDesc; +} + +/***************************************************************************** + + XmlAddEndpointDescriptor() + + This routine adds usb endpoint descriptor and verbose fields + *****************************************************************************/ +void XmlAddEndpointDescriptor( + EndpointDescriptorType ^usbXmlEndpointDescriptor, + PUSB_ENDPOINT_DESCRIPTOR endPointDescriptor, + UCHAR connectionSpeed + ) +{ + EndpointDescriptorType ^ue = usbXmlEndpointDescriptor; + ULONG maxBytes = endPointDescriptor->wMaxPacketSize & 0x7FF; + + // Add structure values + ue->Length = endPointDescriptor->bLength; + ue->DescriptorType = endPointDescriptor->bDescriptorType; + ue->EndpointAddress = endPointDescriptor->bEndpointAddress; + ue->Attributes = endPointDescriptor->bmAttributes; + ue->MaxPacketSize = endPointDescriptor->wMaxPacketSize; + + // Add verbose fields + ue->EndpointId = endPointDescriptor->bEndpointAddress & 0x0F; + + // Add endpoint direction + if (USB_ENDPOINT_DIRECTION_OUT(endPointDescriptor->bEndpointAddress)) + { + ue->EndpointDirection = gcnew String("Out"); + } + else if (USB_ENDPOINT_DIRECTION_IN(endPointDescriptor->bEndpointAddress)) + { + ue->EndpointDirection = gcnew String("In"); + } + + // Add endpoint type + switch (endPointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) + { + case USB_ENDPOINT_TYPE_CONTROL: + ue->EndpointType = gcnew String("Control Transfer Type"); + break; + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + switch (endPointDescriptor->bmAttributes & 0x0C) + { + case 0x00: + ue->EndpointType = gcnew String("Ischronous Transfer Type - No Synchronization"); + break; + + case 0x04: + ue->EndpointType = gcnew String("Ischronous Transfer Type - Asynchronous"); + break; + + case 0x08: + ue->EndpointType = gcnew String("Ischronous Transfer Type - Adaptive"); + break; + + case 0x0C: + ue->EndpointType = gcnew String("Ischronous Transfer Type - Synchronous"); + break; + } + break; + case USB_ENDPOINT_TYPE_BULK: + ue->EndpointType = gcnew String("Bulk Transfer Type"); + break; + + case USB_ENDPOINT_TYPE_INTERRUPT: + ue->EndpointType = gcnew String("Interrupt Transfer Type"); + break; + } + + // Add packet info + switch (connectionSpeed) + { + case UsbHighSpeed: + if (endPointDescriptor->bmAttributes & 1) { + ULONG transactions = ((endPointDescriptor->wMaxPacketSize & 0x1800) >> 11) + 1; + // Isoc or Interrupt endpoint + ue->EndpointPacketInfo = gcnew String( + transactions + " transactions per microframe, " + + maxBytes + " max bytes"); + } + else + { + // Bulk endpoint + ue->EndpointPacketInfo = gcnew String(maxBytes + " max bytes"); + } + break; + case UsbFullSpeed: + ue->EndpointPacketInfo = gcnew String(maxBytes + " max bytes"); + break; + default: + // Low or Invalid speed + ue->EndpointPacketInfo = gcnew String("Invalid bus speed"); + break; + } + + // Add validation + if (endPointDescriptor->wMaxPacketSize & 0xE000) + { + ue->EndpointPacketSizeValidation = gcnew String("ERROR: wMaxPacketSize bits 15-13 should be 0"); + } else if (connectionSpeed==UsbHighSpeed) + { + USHORT hsMux; + + hsMux = (endPointDescriptor->wMaxPacketSize >> 11) & 0x03; + + switch (endPointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) + { + case USB_ENDPOINT_TYPE_ISOCHRONOUS: + case USB_ENDPOINT_TYPE_INTERRUPT: + switch (hsMux) { + case 0: + if ((maxBytes < 1) || (maxBytes > 1024)) + { + ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 1 and 1024"); + } + break; + + case 1: + if ((maxBytes < 513) || (maxBytes > 1024)) + { + ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 513 and 1024"); + } + break; + + case 2: + if ((maxBytes < 683) || (maxBytes > 1024)) + { + ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 683 and 1024"); + } + break; + + case 3: + ue->EndpointPacketSizeValidation = gcnew String("ERROR: Bits 12-11 set to reserved value\r\n"); + break; + } + } + } + + // Add interval + if (endPointDescriptor->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) + { + ue->Interval = endPointDescriptor->bInterval; + } + else + { + PUSB_ENDPOINT_DESCRIPTOR2 endpointDesc2 = (PUSB_ENDPOINT_DESCRIPTOR2) endPointDescriptor; + ue->WInterval = endpointDesc2->wInterval; + ue->SyncAddress = endpointDesc2->bSyncAddress; + } + return; +} + +/***************************************************************************** + + XmlAddPipeInformation() + + This routine adds all the pipe information for device + *****************************************************************************/ +void XmlAddPipeInformation( + array< UsbPipeInfoType ^> ^ usbXmlPipeInfoList, + PUSB_PIPE_INFO pipeInfo, + ULONG numPipes, + UCHAR connectionSpeed + ) +{ + ULONG i = 0; + + for(i = 0; i< numPipes; i++) + { + // Add all pipe in the list + usbXmlPipeInfoList[i] = gcnew UsbPipeInfoType(); + usbXmlPipeInfoList[i]->EndpointDescriptor = gcnew EndpointDescriptorType(); + XmlAddEndpointDescriptor( + usbXmlPipeInfoList[i]->EndpointDescriptor, + &pipeInfo[i].EndpointDescriptor, + connectionSpeed); + usbXmlPipeInfoList[i]->ScheduleOffset = pipeInfo->ScheduleOffset; + } + return; +} + +/***************************************************************************** + + XmlAddUsbDeviceDescriptor() + + This routine adds usb device descriptor + *****************************************************************************/ +void XmlAddUsbDeviceDescriptor( + UsbDeviceDescriptorType ^usbXmlDeviceDescriptor, + PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor) +{ + UsbDeviceDescriptorType ^ud = usbXmlDeviceDescriptor; + + // Map all fields explicitly + + ud->Length = usbDeviceDescriptor->bLength; + ud->DescriptorType = usbDeviceDescriptor->bDescriptorType; + ud->CdUSB= usbDeviceDescriptor->bcdUSB; + ud->DeviceClass = usbDeviceDescriptor->bDeviceClass; + ud->DeviceSubclass = usbDeviceDescriptor->bDeviceSubClass; + ud->DeviceProtocol = usbDeviceDescriptor->bDeviceProtocol; + ud->MaxPacketSize0 = usbDeviceDescriptor->bMaxPacketSize0; + ud->IdVendor = usbDeviceDescriptor->idVendor; + ud->IdProduct = usbDeviceDescriptor->idProduct ; + ud->CdDevice = usbDeviceDescriptor->bcdDevice; + ud->IManufacturer = usbDeviceDescriptor->iManufacturer; + ud->IProduct = usbDeviceDescriptor->iProduct; + ud->ISerialNumber = usbDeviceDescriptor->iSerialNumber; + ud->NumConfigurations = usbDeviceDescriptor->bNumConfigurations; + return; +} + +/***************************************************************************** + + XmlAddConfigurationDescriptor() + + This routine adds the configuration descriptor + *****************************************************************************/ +void XmlAddConfigurationDescriptor( + UsbConfigurationDescriptorType ^ confXmlDesc, + PUSBDEVICEINFO deviceInfo, + PUSB_CONFIGURATION_DESCRIPTOR configDesc, + PSTRING_DESCRIPTOR_NODE stringDesc + ) + +{ + UINT uCount = 0; + BOOL isSuperSpeed = FALSE; + + if (NULL == configDesc || NULL == deviceInfo) + { + return; + } + + if(deviceInfo->ConnectionInfoV2 && + (deviceInfo->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher || + deviceInfo->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher)) + { + isSuperSpeed = TRUE; + } + + confXmlDesc->BLength = configDesc->bLength; + confXmlDesc->BDescriptorType = configDesc->bDescriptorType; + confXmlDesc->WTotalLength = configDesc->wTotalLength; + confXmlDesc->BNumInterfaces = configDesc->bNumInterfaces; + confXmlDesc->BConfigurationValue = configDesc->bConfigurationValue; + confXmlDesc->IConfiguration = configDesc->iConfiguration; + confXmlDesc->BmAttributes = configDesc->bmAttributes; + confXmlDesc->MaxPower = configDesc->MaxPower; + + uCount = GetConfigurationSize(deviceInfo); + + if (uCount != configDesc->wTotalLength) + { + confXmlDesc->ConfigDescError = gcnew String("ERROR: Invalid total configuration size " + + configDesc->wTotalLength + ", should be " + uCount); + } + + if (configDesc->bConfigurationValue != 1) + { + confXmlDesc->ConfValueError = gcnew String("CAUTION: Most host controllers will only work with one configuration per speed"); + } + + if (configDesc->iConfiguration) + { + confXmlDesc->ConfStringDesc = XmlGetStringDescriptor( + configDesc->iConfiguration, + stringDesc, + false); + } + + if (configDesc->bmAttributes & USB_CONFIG_BUS_POWERED) + { + confXmlDesc->AttributesStr = gcnew String("Bus Powered"); + } + else if (configDesc->bmAttributes & USB_CONFIG_SELF_POWERED) + { + confXmlDesc->AttributesStr = gcnew String("Self Powered"); + } + else if (configDesc->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) + { + confXmlDesc->AttributesStr = gcnew String("Remote Wakeup"); + } + else + { + confXmlDesc->AttributesStr = gcnew String("WARNING: bmAttributes is using reserved space"); + } + + confXmlDesc->MaxCurrent = gcnew String(""); + confXmlDesc->MaxCurrent += (isSuperSpeed?configDesc->MaxPower * 8:configDesc->MaxPower * 2); + confXmlDesc->MaxCurrent += " mA"; + + return; +} + +/***************************************************************************** + + XmlGetDeviceClass() + + This routine returns the interface class and subclass for given interface descriptor + *****************************************************************************/ +UsbDeviceClassType ^ XmlGetDeviceClass(UCHAR bInterfaceClass, UCHAR bInterfaceSubclass, UCHAR bInterfaceProtocol) +{ + String ^ deviceClass = nullptr; + String ^ deviceSubclass = nullptr; + UsbDeviceClassType ^ deviceDetails = gcnew UsbDeviceClassType(); + + switch (bInterfaceClass) + { + case USB_DEVICE_CLASS_AUDIO: + deviceClass = gcnew String("Audio Interface"); + + switch (bInterfaceSubclass) + { + case USB_AUDIO_SUBCLASS_AUDIOCONTROL: + deviceSubclass = gcnew String("Audio Control Interface"); + break; + + case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: + deviceSubclass = gcnew String("Audio Streaming Interface"); + break; + + case USB_AUDIO_SUBCLASS_MIDISTREAMING: + deviceSubclass = gcnew String("MIDI Streaming Interface"); + break; + + default: + deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : "); + deviceSubclass += bInterfaceSubclass; + break; + } + break; + + case USB_DEVICE_CLASS_VIDEO: + deviceClass = gcnew String("Video Interface"); + + switch(bInterfaceSubclass) + { + case VIDEO_SUBCLASS_CONTROL: + deviceSubclass = gcnew String("Video Control"); + break; + + case VIDEO_SUBCLASS_STREAMING: + deviceSubclass = gcnew String("Video Streaming"); + break; + + default: + deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : "); + deviceSubclass += bInterfaceSubclass; + break; + } + break; + + case USB_DEVICE_CLASS_VENDOR_SPECIFIC: + deviceClass = gcnew String("Vendor Specific Device"); + break; + + case USB_DEVICE_CLASS_HUMAN_INTERFACE: + + deviceClass = gcnew String("HID Interface"); + break; + + case USB_DEVICE_CLASS_HUB: + deviceClass = gcnew String("HUB Interface"); + break; + + case USB_DEVICE_CLASS_RESERVED: + deviceClass = gcnew String("CAUTION: Reserved USB Device Interface Class"); + break; + + case USB_DEVICE_CLASS_COMMUNICATIONS: + deviceClass = gcnew String("Communications (CDC Control) USB Device\r\n"); + break; + + case USB_DEVICE_CLASS_MONITOR: + deviceClass = gcnew String("Monitor USB Device Interface Class*** (This may be obsolete)"); + break; + + case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: + deviceClass = gcnew String("Physical Interface USB Device"); + break; + + case USB_DEVICE_CLASS_POWER: + if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1) + { + deviceClass = gcnew String("Image USB Device"); + } + else + { + deviceClass = gcnew String("Power USB Device (This may be obsolete)"); + } + break; + + case USB_DEVICE_CLASS_PRINTER: + deviceClass = gcnew String("Printer USB Device"); + break; + + case USB_DEVICE_CLASS_STORAGE: + deviceClass = gcnew String("Mass Storage USB Device"); + break; + + case USB_CDC_DATA_INTERFACE: + deviceClass = gcnew String("CDC Data USB Device"); + break; + + case USB_CHIP_SMART_CARD_INTERFACE: + deviceClass = gcnew String("Chip/Smart Card USB Device"); + break; + + case USB_CONTENT_SECURITY_INTERFACE: + deviceClass = gcnew String("Content Security USB Device"); + break; + + case USB_DIAGNOSTIC_DEVICE_INTERFACE: + if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1) + { + deviceClass = gcnew String("Reprogrammable USB2 Compliance Diagnostic Device USB Device"); + } + else + { + deviceClass = gcnew String("CAUTION: This appears to be an invalid device class: "); + deviceClass += bInterfaceClass; + } + break; + + case USB_WIRELESS_CONTROLLER_INTERFACE: + if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1) + { + deviceClass = gcnew String("Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface"); + } + else + { + deviceClass = gcnew String("CAUTION: This appears to be an invalid device class: "); + deviceClass += bInterfaceClass; + } + break; + + case USB_APPLICATION_SPECIFIC_INTERFACE: + deviceClass = gcnew String("Application Specific USB Device"); + + switch(bInterfaceSubclass) + { + case 1: + deviceSubclass = gcnew String("Device Firmware Application Specific USB Device"); + break; + case 2: + deviceSubclass = gcnew String("IrDA Bridge Application Specific USB Device"); + break; + case 3: + deviceSubclass = gcnew String("Test & Measurement Class (USBTMC) Application Specific USB Device"); + break; + default: + deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : "); + deviceSubclass += bInterfaceSubclass; + } + break; + case USB_DEVICE_CLASS_BILLBOARD: + deviceClass = gcnew String("Billboard Class"); + switch (bInterfaceSubclass) + { + case 0: + deviceSubclass = gcnew String("Billboard Subclass"); + break; + default: + deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubClass"); + break; + } + break; + default: + + deviceClass = gcnew String("Interface Class unknown : "); + deviceClass += bInterfaceClass; + break; + } + + // Return class and subclass + + deviceDetails->DeviceClass = deviceClass; + deviceDetails->DeviceSubclass = deviceSubclass; + + return deviceDetails; +} + +/***************************************************************************** + + XmlAddInterfaceDescriptor() + + This routine adds the device interface descriptor + *****************************************************************************/ +void XmlAddDeviceInterfaceDescriptor( + UsbDeviceInterfaceDescriptorType ^ ifXmlDesc, + PUSB_INTERFACE_DESCRIPTOR ifDesc, + PSTRING_DESCRIPTOR_NODE stringDesc) +{ + if (NULL == ifDesc || NULL == stringDesc) + { + return; + } + + // Update structure fields + ifXmlDesc->BLength = ifDesc->bLength; + ifXmlDesc->BDescriptorType = ifDesc->bDescriptorType; + ifXmlDesc->BInterfaceNumber = ifDesc->bInterfaceNumber; + ifXmlDesc->BAlternateSetting = ifDesc->bAlternateSetting; + ifXmlDesc->BNumEndpoints = ifDesc->bNumEndpoints; + ifXmlDesc->BInterfaceClass = ifDesc->bInterfaceClass; + ifXmlDesc->BInterfaceSubclass = ifDesc->bInterfaceSubClass; + ifXmlDesc->BInterfaceProtocol = ifDesc->bInterfaceProtocol; + ifXmlDesc->IInterface = ifDesc->iInterface; + + // Update class and sub class + ifXmlDesc->InterfaceDetails = XmlGetDeviceClass( + ifDesc->bInterfaceClass, + ifDesc->bInterfaceSubClass, + ifDesc->bInterfaceProtocol); + + //This is basically the check for PC_PROTOCOL_UNDEFINED + if ((ifDesc->bInterfaceClass == USB_DEVICE_CLASS_VIDEO) || + (ifDesc->bInterfaceClass == USB_DEVICE_CLASS_AUDIO)) + { + if (ifDesc->bInterfaceProtocol != PC_PROTOCOL_UNDEFINED) + { + ifXmlDesc->ProtocolError = gcnew String("WARNING: Protocol must be set to PC_PROTOCOL_UNDEFINED"); + ifXmlDesc->ProtocolError += " for this class but is set to: "; + ifXmlDesc->ProtocolError += ifDesc->bInterfaceProtocol; + } + } + + if (ifDesc->iInterface) + { + // Add String descriptor + ifXmlDesc->StringDesc = XmlGetStringDescriptor( + ifDesc->iInterface, + stringDesc, + false); + } + + if (ifDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR2)) + { + PUSB_INTERFACE_DESCRIPTOR2 interfaceDesc2; + + interfaceDesc2 = (PUSB_INTERFACE_DESCRIPTOR2)ifDesc; + + ifXmlDesc->WNumClasses = interfaceDesc2->wNumClasses; + } + return; +} + +/***************************************************************************** + + XmlAddDeviceQualDescriptor() + + This routine adds the device qualifier descriptor + *****************************************************************************/ + +void XmlAddDeviceQualDescriptor( + UsbDeviceQualifierDescriptorType ^ qualXmlDesc, + PUSB_DEVICE_QUALIFIER_DESCRIPTOR qualDesc) +{ + if (NULL == qualDesc) + { + return; + } + + // Add structure fields + qualXmlDesc->BLength = qualDesc->bLength; + qualXmlDesc->BDescriptorType = qualDesc->bDescriptorType; + qualXmlDesc->BcdUSB = qualDesc->bcdUSB; + qualXmlDesc->BDeviceClass = qualDesc->bDeviceClass; + qualXmlDesc->BDeviceSubclass = qualDesc->bDeviceSubClass; + qualXmlDesc->BDeviceProtocol = qualDesc->bDeviceProtocol; + qualXmlDesc->BMaxPacketSize0 = qualDesc->bMaxPacketSize0; + qualXmlDesc->NumConfigurations = qualDesc->bNumConfigurations; + + // Get device class string + qualXmlDesc->DeviceClass = XmlGetDeviceClassString(qualDesc->bDeviceClass); + + if (qualDesc->bDeviceSubClass > 0x00 && qualDesc->bDeviceSubClass < 0xFF) + { + qualXmlDesc->DeviceSubclassError = gcnew String("ERROR: bDeviceSubClass is invalid : "); + qualXmlDesc->DeviceSubclassError += qualDesc->bDeviceSubClass; + } + + if (qualDesc->bDeviceProtocol > 0x00 && qualDesc->bDeviceProtocol < 0xFF) + { + qualXmlDesc->DeviceProtocolError = gcnew String("ERROR: bDeviceProtocol is invalid : "); + qualXmlDesc->DeviceProtocolError += qualDesc->bDeviceProtocol; + } + + qualXmlDesc->MaxPacketSizeInBytes = qualDesc->bMaxPacketSize0; + + if (qualDesc->bNumConfigurations != 1) + { + qualXmlDesc->DeviceNumConfigError = gcnew String( + "CAUTION: Most host controllers will only work with one configuration per speed"); + } + + if (qualDesc->bReserved != 0) + { + qualXmlDesc->ReservedError = gcnew String("WARNING: bReserved needs to be set to 0 to be valid - " + + qualDesc->bReserved); + } + + return; +} + +/***************************************************************************** + + XmlAddAddConfigDescriptors() + + This routine adds the all the config descriptors + *****************************************************************************/ +array < UsbDeviceConfigurationType ^> ^ XmlGetConfigDescriptors( + PUSBDEVICEINFO deviceInfo, + PUSB_CONFIGURATION_DESCRIPTOR configDescs, + PSTRING_DESCRIPTOR_NODE stringDesc + ) +{ + array < UsbDeviceConfigurationType ^> ^ confXmlDescs = nullptr; + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + PUCHAR descEnd = NULL; + ArrayList ^confList = gcnew ArrayList; + UsbDeviceConfigurationType ^ deviceConf = nullptr; + + commonDesc = (PUSB_COMMON_DESCRIPTOR) configDescs; + descEnd = (PUCHAR) configDescs + configDescs->wTotalLength; + + while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && + (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) + { + // Add the config descriptor + deviceConf = gcnew UsbDeviceConfigurationType(); + + XmlAddDeviceConfiguration( + deviceConf, + deviceInfo, + (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc, + stringDesc, + configDescs->bNumInterfaces + ); + + confList->Add(deviceConf); + commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); + } + + confXmlDescs = reinterpret_cast^> (confList->ToArray(UsbDeviceConfigurationType::typeid)); + return confXmlDescs; +} + +/***************************************************************************** + + XmlAddDeviceConfiguration() + + This routine adds the device configuration + *****************************************************************************/ +void XmlAddDeviceConfiguration( + UsbDeviceConfigurationType ^ confXmlDesc, + PUSBDEVICEINFO deviceInfo, + PUSB_CONFIGURATION_DESCRIPTOR configDesc, + PSTRING_DESCRIPTOR_NODE stringDesc, + int numInterfaces + ) +{ + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + UCHAR bInterfaceClass = 0; + UCHAR bInterfaceSubclass = 0; + UCHAR bInterfaceProtocol = 0; + BOOL displayUnknown = FALSE; + + if (NULL == deviceInfo || NULL == configDesc || NULL == stringDesc) + { + return; + } + + commonDesc = (PUSB_COMMON_DESCRIPTOR)configDesc; + displayUnknown = FALSE; + + switch (commonDesc->bDescriptorType) + { + case USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) + { + // Validate descriptor + confXmlDesc->DeviceQualifierError = String::Format( + "ERROR: Device Qualifier bLength value incorrect Obtained: {0} Expected {1}", + commonDesc->bLength, + sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)); + displayUnknown = TRUE; + break; + } + // Add device Qual descriptor + confXmlDesc->DeviceQualifierDescriptor = gcnew UsbDeviceQualifierDescriptorType(); + + XmlAddDeviceQualDescriptor( + confXmlDesc->DeviceQualifierDescriptor, + (PUSB_DEVICE_QUALIFIER_DESCRIPTOR) commonDesc); + break; + + case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + // Validate descriptor + confXmlDesc->SpeedConfigurationError = String::Format( + "ERROR: Other speed configuration bLength value incorrect Obtained: {0} Expected {1}", + commonDesc->bLength, + sizeof(USB_CONFIGURATION_DESCRIPTOR)); + displayUnknown = TRUE; + } + + // Add configuration desc + confXmlDesc->ConfigurationDescriptor = gcnew UsbConfigurationDescriptorType(); + + XmlAddConfigurationDescriptor( + confXmlDesc->ConfigurationDescriptor, + deviceInfo, + (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc, + stringDesc); + break; + + case USB_CONFIGURATION_DESCRIPTOR_TYPE: + if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) + { + // Validate descriptor + confXmlDesc->SpeedConfigurationError = String::Format( + "ERROR: Configuration bLength value incorrect Obtained: {0} Expected {1}", + commonDesc->bLength, + sizeof(USB_CONFIGURATION_DESCRIPTOR)); + displayUnknown = TRUE; + break; + } + + // Add configuration desc + confXmlDesc->ConfigurationDescriptor = gcnew UsbConfigurationDescriptorType(); + XmlAddConfigurationDescriptor( + confXmlDesc->ConfigurationDescriptor, + deviceInfo, + (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc, + stringDesc); + break; + + case USB_INTERFACE_DESCRIPTOR_TYPE: + if ((commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR)) && + (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))) + { + // Validate descriptor + confXmlDesc->InterfaceError = String::Format( + "ERROR: Interface bLength value incorrect Obtained: {0} Expected: {1} or {2}", + commonDesc->bLength, + sizeof(USB_INTERFACE_DESCRIPTOR), + sizeof(USB_INTERFACE_DESCRIPTOR2)); + displayUnknown = TRUE; + break; + } + + // Add interface descriptor + bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass; + bInterfaceSubclass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceSubClass; + bInterfaceProtocol = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceProtocol; + + confXmlDesc->InterfaceDescriptor = gcnew UsbDeviceInterfaceDescriptorType(); + XmlAddDeviceInterfaceDescriptor( + confXmlDesc->InterfaceDescriptor, + (PUSB_INTERFACE_DESCRIPTOR) commonDesc, + stringDesc + ); + + case USB_ENDPOINT_DESCRIPTOR_TYPE: + if ((commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR)) && + (commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR2))) + { + // Validate endpoint descriptor + confXmlDesc->EndpointError = String::Format( + "ERROR: Endpoint bLength value incorrect Obtained: {0} Expected: {1} or {2}", + commonDesc->bLength, + sizeof(USB_ENDPOINT_DESCRIPTOR), + sizeof(USB_ENDPOINT_DESCRIPTOR2)); + displayUnknown = TRUE; + break; + } + + confXmlDesc->EndpointDescriptor = gcnew EndpointDescriptorType(); + + if (NULL != deviceInfo->ConnectionInfo) + { + // Add endpoint descriptor + XmlAddEndpointDescriptor( + confXmlDesc->EndpointDescriptor, + (PUSB_ENDPOINT_DESCRIPTOR) commonDesc, + deviceInfo->ConnectionInfo->Speed); + } + + break; + + case USB_HID_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_HID_DESCRIPTOR)) + { + // Validate HID + confXmlDesc->HidError = String::Format( + "ERROR: HID bLength value incorrect Obtained: {0} Expected: {1}", + commonDesc->bLength, + sizeof(USB_HID_DESCRIPTOR)); + displayUnknown = TRUE; + break; + } + + // Add HID descriptor + confXmlDesc->HidDescriptor = gcnew UsbDeviceHidDescriptorType(); + XmlAddHidDescriptor( + confXmlDesc->HidDescriptor, + (PUSB_HID_DESCRIPTOR) commonDesc + ); + break; + + case USB_OTG_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_OTG_DESCRIPTOR)) + { + // Validate length + confXmlDesc->HidError = String::Format( + "ERROR: OTG bLength value incorrect Obtained: {0} Expected: {1}", + commonDesc->bLength, + sizeof(USB_OTG_DESCRIPTOR)); + displayUnknown = TRUE; + break; + } + + // Add OTG descriptor + confXmlDesc->OtgDescriptor = gcnew UsbDeviceOTGDescriptorType(); + XmlAddOTGDescriptor( + confXmlDesc->OtgDescriptor, + (PUSB_OTG_DESCRIPTOR) commonDesc + ); + break; + + case USB_IAD_DESCRIPTOR_TYPE: + if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR)) + { + // Validate length + confXmlDesc->IadError = String::Format( + "ERROR: IAD bLength value incorrect", + commonDesc->bLength, + sizeof(USB_OTG_DESCRIPTOR)); + displayUnknown = TRUE; + } + + // Add IAD descriptor + confXmlDesc->IadDescriptor = gcnew UsbDeviceIADDescriptorType(); + XmlAddIADDescriptor( + confXmlDesc->IadDescriptor, + (PUSB_IAD_DESCRIPTOR) commonDesc, + stringDesc, + numInterfaces + ); + break; + + default: + // Interface class device (?) + confXmlDesc->DeviceDetails = XmlGetDeviceClass( + ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceClass, + ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceSubClass, + ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceProtocol + ); + break; + } + + if (displayUnknown) + { + // Add unknown descriptor + confXmlDesc->UnknownDescriptor = XmlGetUnknownDescriptor(commonDesc); + } + return; +} + +/***************************************************************************** + + XmlAddConnectionInfoSt() + + This routine adds connection information structures for the device + *****************************************************************************/ +void XmlAddConnectionInfoSt( + NodeConnectionInfoExStructType ^xmlConnectionInfoSt, + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, + PDEVICE_INFO_NODE pNode) +{ + NodeConnectionInfoExStructType ^nS = xmlConnectionInfoSt; + + nS->ConnectionIndex = connectionInfo->ConnectionIndex; + + nS->DeviceDescriptor = gcnew UsbDeviceDescriptorType(); + + XmlAddUsbDeviceDescriptor(nS->DeviceDescriptor, &(connectionInfo->DeviceDescriptor)); + + nS->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue; + nS->Speed = connectionInfo->Speed; + nS->SpeedStr = static_cast (connectionInfo->Speed); + nS->DeviceIsHub = connectionInfo->DeviceIsHub? true: false; + nS->NumOfOpenPipes = connectionInfo->NumberOfOpenPipes; + nS->UsbConnectionStatus = static_cast (connectionInfo->ConnectionStatus); + + if(NULL != pNode) + { + nS->DevicePowerState = static_cast(pNode->LatestDevicePowerState); + } + else + { + nS->DevicePowerState = static_cast(PowerDeviceUnspecified); + } + + // Add the pipe list + if (connectionInfo->NumberOfOpenPipes > 0) + { + nS->Pipe = gcnew array (connectionInfo->NumberOfOpenPipes); + XmlAddPipeInformation( + nS->Pipe, + connectionInfo->PipeList, + connectionInfo->NumberOfOpenPipes, + connectionInfo->Speed + ); + } + + return; +} + +/***************************************************************************** + + XmlGetLangIdString() + + Obtains the language string for given string descriptor index + *****************************************************************************/ +String ^ XmlGetLangIdString(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc) +{ + String ^langIdStr = nullptr; + bool foundDescriptor = false; + + while(stringDesc) + { + if (stringDesc->DescriptorIndex == index) + { + langIdStr = PACHAR_TO_STRING(GetLangIDString(stringDesc->LanguageID)); + + if (langIdStr == nullptr) + { + langIdStr = gcnew String("WARNING: Invalid language ID: " + stringDesc->LanguageID); + } + foundDescriptor = true; + break; + } + stringDesc = stringDesc->Next; + } + + if (foundDescriptor == false) + { + // If no descriptor was found, return error message in field + langIdStr = gcnew String("ERROR: No String descriptor for index " + index); + } + + return langIdStr; +} + +/***************************************************************************** + + XmlGetStringDescriptor() + + Obtains the string descriptor for given string descriptor index + *****************************************************************************/ + +String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly) +{ + ULONG nBytes = 0; + + CHAR pString[MAX_STRING_DESCRIPTOR_LENGTH]; + String ^desc = nullptr; + bool foundDescriptor = false; + bool foundNonEnglishDescriptor = false; + + ZeroMemory(pString, MAX_STRING_DESCRIPTOR_LENGTH); + + while(stringDesc) + { + if (stringDesc->DescriptorIndex == index) + { + if (enOnly && stringDesc->LanguageID != STRING_DESCRIPTOR_EN_LANGUAGE_ID) + { + // If we are required to return only english descriptor, continue + foundNonEnglishDescriptor = true; + continue; + } + + nBytes = WideCharToMultiByte( + CP_ACP, + WC_NO_BEST_FIT_CHARS, + stringDesc->StringDescriptor->bString, + (stringDesc->StringDescriptor->bLength -2)/2, + pString, + MAX_STRING_DESCRIPTOR_LENGTH, + NULL, + NULL + ); + + if (nBytes) + { + foundDescriptor = true; + desc = PACHAR_TO_STRING(pString); + } + break; + } + stringDesc = stringDesc->Next; + } + + if ((foundDescriptor == false) && (foundNonEnglishDescriptor == false)) + { + // If no descriptor was found, return error message in field + desc = gcnew String("ERROR: No String descriptor for index " + + index); + } + else if ((foundDescriptor == false) && (foundNonEnglishDescriptor == true) && (enOnly)) + { + desc = gcnew String("ERROR: The index " + index + " does not support English(US)"); + } + + return desc; +} + +/***************************************************************************** + + XmlGetDeviceClassString() + + Returns the device class string for given device class ID + *****************************************************************************/ + +String ^ XmlGetDeviceClassString(UCHAR deviceClass) +{ + String ^ deviceClassStr = nullptr; + + // Not an IAD device + switch (deviceClass) + { + case USB_INTERFACE_CLASS_DEVICE: + deviceClassStr = gcnew String("Interface Class Defined Device"); + break; + + case USB_COMMUNICATION_DEVICE: + deviceClassStr = gcnew String("Communication Device"); + break; + + case USB_HUB_DEVICE: + deviceClassStr = gcnew String("Hub Device"); + break; + + case USB_DIAGNOSTIC_DEVICE: + deviceClassStr = gcnew String("Diagnostic Device"); + break; + + case USB_WIRELESS_CONTROLLER_DEVICE: + deviceClassStr = gcnew String("Wireless Controller(Bluetooth) Device"); + break; + + case USB_VENDOR_SPECIFIC_DEVICE: + deviceClassStr = gcnew String("Vendor specific device"); + break; + + case USB_DEVICE_CLASS_BILLBOARD: + deviceClassStr = gcnew String("Billboard class device"); + break; + + default: + deviceClassStr= gcnew String("ERROR: unknown bDeviceClass" + deviceClass); + break; + } + return deviceClassStr; +} + + +/***************************************************************************** + + XmlAddDeviceClassDetails() + + This routine adds device class details + *****************************************************************************/ +bool XmlAddDeviceClassDetails( + UsbDeviceClassDetailsType ^ deviceDetails, + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, + PUSBDEVICEINFO deviceInfo) +{ + UINT uIADcount = 0; + bool tog = true; + + uIADcount = IsIADDevice((PUSBDEVICEINFO) deviceInfo); + + if (uIADcount) + { + // IAD device, check validity of device class + if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE) + { + tog = false; + deviceDetails->DeviceType = gcnew String("Multi-interface Function Code Device"); + } + else { + deviceDetails->DeviceTypeError = gcnew String("ERROR: device class should be Multi-interface Function " + + USB_MISCELLANEOUS_DEVICE + + "is used"); + } + deviceDetails->UvcVersion = IsUVCDevice((PUSBDEVICEINFO) deviceInfo); + + // This device configuration has 1 or more IAD descriptors + if (connectionInfo->DeviceDescriptor.bDeviceSubClass == USB_COMMON_SUB_CLASS) + { + deviceDetails->SubclassType = gcnew String("Common Class Sub Class"); + } + else + { + deviceDetails->SubclassTypeError = gcnew String("ERROR: device SubClass should be USB Common Sub Class" + + USB_COMMON_SUB_CLASS + + " when IAD descriptor is used"); + } + + // Check device protocol + if (connectionInfo->DeviceDescriptor.bDeviceProtocol == USB_IAD_PROTOCOL) + { + deviceDetails->DeviceProtocol = gcnew String("Interface Association Descriptor protocol"); + } + else + { + deviceDetails->DeviceProtocolError = gcnew String("ERROR: device Protocol should be USB IAD Protocol " + + USB_IAD_PROTOCOL + + " when IAD descriptor is used"); + } + + } + else + { + deviceDetails->DeviceType = XmlGetDeviceClassString(connectionInfo->DeviceDescriptor.bDeviceClass); + + if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_BILLBOARD && + (connectionInfo->DeviceDescriptor.bDeviceSubClass != 0x0 || + connectionInfo->DeviceDescriptor.bDeviceProtocol != 0x0)) + { + deviceDetails->DeviceTypeError = gcnew String("ERROR: Billboard device has invalid bDeviceSubclass/bDeviceProtocol"); + } + + if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE) + { + deviceDetails->DeviceTypeError = gcnew String("ERROR: Multi-interface Function code " + + connectionInfo->DeviceDescriptor.bDeviceClass + + " used for device with no IAD descriptors"); + } + + if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_COMMUNICATION_DEVICE || + connectionInfo->DeviceDescriptor.bDeviceClass == USB_HUB_DEVICE || + connectionInfo->DeviceDescriptor.bDeviceClass == USB_DIAGNOSTIC_DEVICE || + connectionInfo->DeviceDescriptor.bDeviceClass == USB_WIRELESS_CONTROLLER_DEVICE || + connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE || + connectionInfo->DeviceDescriptor.bDeviceClass == USB_VENDOR_SPECIFIC_DEVICE) + { + tog = false; + } + + // Not an IAD device, so all subclass values are invalid + if (connectionInfo->DeviceDescriptor.bDeviceSubClass > 0x00 && + connectionInfo->DeviceDescriptor.bDeviceSubClass < 0xFF) + { + deviceDetails->SubclassTypeError = gcnew String("ERROR: bDeviceSubClass is invalid - " + + connectionInfo->DeviceDescriptor.bDeviceSubClass); + } + + // Not an IAD device, so all subclass values are invalid, check protocol + if (connectionInfo->DeviceDescriptor.bDeviceProtocol > 0x00 && + connectionInfo->DeviceDescriptor.bDeviceProtocol < 0xFF && tog==1) + { + deviceDetails->DeviceProtocolError = gcnew String("ERROR: bDeviceProtocol is invalid - " + + connectionInfo->DeviceDescriptor.bDeviceProtocol); + } + } + + return tog; +} + +/***************************************************************************** + + XmlAddConnectionInfo() + + This routine adds connection information for the device + *****************************************************************************/ +void XmlAddConnectionInfo( + NodeConnectionInfoExType ^xmlConnectionInfo, + PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, + PUSBDEVICEINFO deviceInfo, + PSTRING_DESCRIPTOR_NODE stringDesc, + PDEVICE_INFO_NODE pNode) +{ + NodeConnectionInfoExType ^ nc = xmlConnectionInfo; + bool tog = true; + nc->ConnectionInfoStruct = gcnew NodeConnectionInfoExStructType(); + + // Update the structure + XmlAddConnectionInfoSt(nc->ConnectionInfoStruct, connectionInfo, pNode); + + // Add verbose fields + if (connectionInfo->ConnectionStatus == NoDeviceConnected) + { + // No device connected, nothing to do + return; + } + + if (connectionInfo->DeviceDescriptor.iProduct) + { + // Add EN version of string descriptor + + nc->IProductStringDescEn = XmlGetStringDescriptor( + connectionInfo->DeviceDescriptor.iProduct, + stringDesc, + true); + } + + // Check open pipes count + if (connectionInfo->NumberOfOpenPipes == 0) + { + nc->PipeInfoError = gcnew String("ERROR: No open pipes"); + } + + // Check device descriptor length + if (connectionInfo->DeviceDescriptor.bLength != DEVICE_DESCRIPTOR_LENGTH) + { + nc->LengthError = gcnew String("ERROR: bLength " + + connectionInfo->DeviceDescriptor.bLength + + " incorrect, should be " + + DEVICE_DESCRIPTOR_LENGTH + ); + } + + // Check for device error + if ((connectionInfo->ConnectionStatus == DeviceFailedEnumeration) || + (connectionInfo->ConnectionStatus == DeviceGeneralFailure)) + { + nc->DeviceError = gcnew String("ERROR: Device enumeration failure"); + } + else + { + nc->DeviceClassDetails = gcnew UsbDeviceClassDetailsType(); + + // Add device class details + tog = XmlAddDeviceClassDetails( + nc->DeviceClassDetails, + connectionInfo, + deviceInfo); + + nc->MaxPacketSizeInBytes = connectionInfo->DeviceDescriptor.bMaxPacketSize0; + + // Validate speed + switch (connectionInfo->Speed) + { + case UsbLowSpeed: + if (connectionInfo->DeviceDescriptor.bMaxPacketSize0 != 8) + { + nc->PacketSizeError = gcnew String("ERROR: Low Speed Devices require bMaxPacketSize0 = 8"); + } + break; + case UsbFullSpeed: + if (!(connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 8 || + connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 16 || + connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 32 || + connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 64)) + { + nc->PacketSizeError = gcnew String("ERROR: Full Speed Devices require bMaxPacketSize0 = 8, 16, 32, or 64"); + } + break; + case UsbHighSpeed: + if (connectionInfo->DeviceDescriptor.bMaxPacketSize0 != 64) + { + nc->PacketSizeError = gcnew String("ERROR: High Speed Devices require bMaxPacketSize0 = 64"); + } + break; + } + + // Get string descriptors + nc->VendorString = PACHAR_TO_STRING(GetVendorString(connectionInfo->DeviceDescriptor.idVendor)); + + nc->ManufacturerString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iManufacturer, stringDesc, false); + nc->ProductString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iProduct, stringDesc, false); + nc->LangIdString = XmlGetLangIdString(connectionInfo->DeviceDescriptor.iProduct, stringDesc); + nc->SerialString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iSerialNumber, stringDesc, false); + + // Validate configuration + if (connectionInfo->DeviceDescriptor.bNumConfigurations != 1) + { + nc->ConfigurationCountError = gcnew String("WARNING: Most host controllers will only work with "\ + "one configuration per speed"); + } + } + return; +} + + +/***************************************************************************** + + XmlAddExternalHub() + + Add a external to the parent Host Controller or hub. This is determined by the + last object pushed on the stack + *****************************************************************************/ +HRESULT XmlAddExternalHub(PSTR ehName, PUSBEXTERNALHUBINFO ehInfo) +{ + HRESULT hr = S_OK; + Object ^ parent = gXmlStack->Peek(); + ExternalHubType ^exHub = nullptr; + + UNREFERENCED_PARAMETER(ehName); + + if (NULL == ehInfo) + { + return E_FAIL; + } + + exHub = AddExternalHub(parent); + + if (exHub != nullptr) + { + exHub->HubName = PACHAR_TO_STRING(ehInfo->HubName); + + if (NULL != ehInfo->UsbDeviceProperties) + { + exHub->HwId = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->HwId); + exHub->DeviceId = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceId); + exHub->ServiceName = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->Service); + exHub->DeviceName = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceDesc); + exHub->DeviceClass = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceClass); + } + + exHub->HubNodeInformation = gcnew HubNodeInformationType(); + XmlAddHubNodeInformation(exHub->HubNodeInformation, ehInfo->HubInfo); + + exHub->HubInformationEx = gcnew HubInformationExType(); + XmlAddHubInformationEx(exHub->HubInformationEx, ehInfo->HubInfoEx); + + exHub->HubCapabilityEx = gcnew HubCapabilitiesExType(); + XmlAddHubCapabilitiesEx(exHub->HubCapabilityEx, ehInfo->HubCapabilityEx); + + exHub->ConnectionInfo = gcnew NodeConnectionInfoExType(); + + // Update protocol + if (NULL != ehInfo->ConnectionInfo) + { + switch(ehInfo->ConnectionInfo->Speed) + { + case UsbLowSpeed: + case UsbFullSpeed: + exHub->UsbProtocol = gcnew String(USB_1_1); + break; + case UsbHighSpeed: + exHub->UsbProtocol = gcnew String(USB_2_0); + break; + case UsbSuperSpeed: + exHub->UsbProtocol = gcnew String(USB_3_0); + break; + } + } + + // Add connection info + XmlAddConnectionInfo( + exHub->ConnectionInfo, + ehInfo->ConnectionInfo, + (PUSBDEVICEINFO) ehInfo, + ehInfo->StringDescs, + ehInfo->DeviceInfoNode + ); + + // Add port connectors + if (NULL != ehInfo->PortConnectorProps) + { + exHub->PortConnector = gcnew PortConnectorType(); + + XmlAddPortConnectorProps( + exHub->PortConnector, + ehInfo->PortConnectorProps + ); + } + // Add connection info V2 + exHub->ConnectionInfoV2 = gcnew NodeConnectionInfoExV2Type(); + + XmlAddConnectionInfoV2( + exHub->ConnectionInfoV2, + ehInfo->ConnectionInfoV2 + ); + + // Add configuration descriptor + if (NULL != ehInfo->ConfigDesc) + { + exHub->DeviceConfiguration = XmlGetConfigDescriptors( + (PUSBDEVICEINFO) ehInfo, + (PUSB_CONFIGURATION_DESCRIPTOR) (ehInfo->ConfigDesc + 1), + ehInfo->StringDescs + ); + } + + // Add BOS descriptor + if (NULL != ehInfo->BosDesc) + { + exHub->BosDescriptor = XmlGetBosDescriptor((PUSB_BOS_DESCRIPTOR) (ehInfo->BosDesc + 1), ehInfo->StringDescs); + } + + gXmlStack->Push(exHub); + } + else + { + hr = E_FAIL; + } + return hr; +} + +/***************************************************************************** + + XmlGetBosDescriptor() + + Gets the Bos descriptor object for given BOS descriptor + *****************************************************************************/ +UsbBosDescriptorType ^ XmlGetBosDescriptor( + PUSB_BOS_DESCRIPTOR bosDesc, + PSTRING_DESCRIPTOR_NODE stringDesc + ) +{ + PUSB_COMMON_DESCRIPTOR commonDesc = NULL; + PUSB_DEVICE_CAPABILITY_DESCRIPTOR capDesc = NULL; + UsbBosDescriptorType ^ bosXmlDesc = nullptr; + ArrayList ^usb20CapExtDescList = gcnew ArrayList(); + ArrayList ^usbSuperSpeedExtDescList = gcnew ArrayList(); + ArrayList ^usbContIdCapExtDescList = gcnew ArrayList(); + ArrayList ^usbUnknownDescList = gcnew ArrayList(); + ArrayList ^usbBillboardDescList = gcnew ArrayList(); + + if(NULL == bosDesc) + { + return nullptr; + } + + // Initialize attributes + bosXmlDesc = gcnew UsbBosDescriptorType(); + bosXmlDesc->BLength = bosDesc->bLength; + bosXmlDesc->BDescriptorType = bosDesc->bDescriptorType; + bosXmlDesc->WTotalLength = bosDesc->wTotalLength; + bosXmlDesc->BNumDeviceCaps = bosDesc->bNumDeviceCaps; + + commonDesc = (PUSB_COMMON_DESCRIPTOR) bosDesc; + + while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR) bosDesc, + bosDesc->wTotalLength, + commonDesc, + -1)) != NULL) + { + switch (commonDesc->bDescriptorType) + { + case USB_DEVICE_CAPABILITY_DESCRIPTOR_TYPE: + capDesc = (PUSB_DEVICE_CAPABILITY_DESCRIPTOR)commonDesc; + switch (capDesc->bDevCapabilityType) + { + case USB_DEVICE_CAPABILITY_USB20_EXTENSION: + usb20CapExtDescList->Add( + XmlGetUsb20CapabilityExtensionDescriptor( + (PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR)capDesc + ) + ); + break; + case USB_DEVICE_CAPABILITY_SUPERSPEED_USB: + usbSuperSpeedExtDescList->Add( + XmlGetSuperSpeedCapabilityExtensionDescriptor( + (PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR)capDesc + ) + ); + break; + case USB_DEVICE_CAPABILITY_CONTAINER_ID: + usbContIdCapExtDescList->Add( + XmlGetContainerIdCapabilityExtensionDescriptor( + (PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR)capDesc + ) + ); + break; + case USB_DEVICE_CAPABILITY_BILLBOARD: + usbBillboardDescList->Add( + XmlGetBillboardCapabilityDescriptor( + (PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) capDesc, + stringDesc + ) + ); + break; + default: + usbUnknownDescList->Add( + XmlGetUnknownDescriptor( + (PUSB_COMMON_DESCRIPTOR) capDesc + ) + ); + break; + } + break; + default: + usbUnknownDescList->Add(XmlGetUnknownDescriptor(commonDesc)); + break; + } + } + + // Convert lists to arrays for and add to Bos Descriptor + bosXmlDesc->UnknownDescriptor = reinterpret_cast^> ( + usbUnknownDescList->ToArray(UsbDeviceUnknownDescriptorType::typeid) + ); + bosXmlDesc->UsbSuperSpeedExtensionDescriptor = reinterpret_cast^> ( + usbSuperSpeedExtDescList->ToArray(UsbSuperSpeedExtensionDescriptorType::typeid) + ); + bosXmlDesc->UsbUsb20ExtensionDescriptor = reinterpret_cast^> ( + usb20CapExtDescList->ToArray(UsbUsb20ExtensionDescriptorType::typeid) + ); + bosXmlDesc->UsbDispContIdCapExtDescriptor = reinterpret_cast^> ( + usbContIdCapExtDescList->ToArray(UsbDispContIdCapExtDescriptorType::typeid) + ); + bosXmlDesc->UsbBillboardCapabilityDescriptor = reinterpret_cast^> ( + usbBillboardDescList->ToArray(UsbBillboardCapabilityDescriptorType::typeid) + ); + + return bosXmlDesc; +} + + +/***************************************************************************** + + XmlGetUsb20CapabilityExtensionDescriptor() + + Gets a Usb20Capability extension descriptor object from the given descriptor + *****************************************************************************/ +UsbUsb20ExtensionDescriptorType ^ XmlGetUsb20CapabilityExtensionDescriptor( + PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR capDesc + ) +{ + UsbUsb20ExtensionDescriptorType ^ capXmlDesc = nullptr; + + if(NULL == capDesc) + { + return nullptr; + } + + capXmlDesc = gcnew UsbUsb20ExtensionDescriptorType(); + + capXmlDesc->BLength = capDesc->bLength; + capXmlDesc->BDescriptorType = capDesc->bDescriptorType; + capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; + capXmlDesc->BmAttributes = capDesc->bmAttributes.AsUlong; + + if (capDesc->bmAttributes.AsUlong & USB_DEVICE_CAPABILITY_USB20_EXTENSION_BMATTRIBUTES_RESERVED_MASK) + { + capXmlDesc->ReservedBitError = gcnew String("ERROR: bits 31..2 and bit 0 are reserved and must be 0"); + } + if (capDesc->bmAttributes.LPMCapable == 1) + { + capXmlDesc->SupportsLinkPowerManagement = true; + } + + return capXmlDesc; +} + +/***************************************************************************** + + XmlGetSuperSpeedCapabilityExtensionDescriptor() + + Gets a Super speed capability extension descriptor object from the given descriptor + *****************************************************************************/ +UsbSuperSpeedExtensionDescriptorType ^ XmlGetSuperSpeedCapabilityExtensionDescriptor( + PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR capDesc + ) +{ + UsbSuperSpeedExtensionDescriptorType ^ capXmlDesc = nullptr; + + if(NULL == capDesc) + { + return nullptr; + } + + capXmlDesc = gcnew UsbSuperSpeedExtensionDescriptorType(); + + capXmlDesc->BLength = capDesc->bLength; + capXmlDesc->BDescriptorType = capDesc->bDescriptorType; + capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; + capXmlDesc->BmAttributes = capDesc->bmAttributes; + capXmlDesc->BU1DevExitLat = capDesc->bU1DevExitLat; + capXmlDesc->WSpeedsSupported = capDesc->wSpeedsSupported; + capXmlDesc->WU2DevExitLat = capDesc->wU2DevExitLat; + capXmlDesc->BFunctionalitySupport = capDesc->bFunctionalitySupport; + + // Add descriptive fields + if (capDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_RESERVED_MASK) + { + capXmlDesc->ReservedAttributesBitError = gcnew String("ERROR: bits 7:2 and bit 0 are reserved"); + } + if (capDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_LTM_CAPABLE) + { + capXmlDesc->LatencyToleranceMsgCapable = true; + } + if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_LOW) + { + capXmlDesc->SupportsLowSpeed = true; + } + if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_FULL) + { + capXmlDesc->SupportsFullSpeed = true; + } + if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_HIGH) + { + capXmlDesc->SupportsHighSpeed = true; + } + if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_SUPER) + { + capXmlDesc->SupportsSuperSpeed = true; + } + if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_RESERVED_MASK) + { + capXmlDesc->ReservedSpeedError = gcnew String("ERROR: bits 15:4 are reserved"); + } + + + switch (capDesc->bFunctionalitySupport) + { + case UsbLowSpeed: + capXmlDesc->LowestSpeed = gcnew String("low-speed"); + break; + case UsbFullSpeed: + capXmlDesc->LowestSpeed = gcnew String("full-speed"); + break; + case UsbHighSpeed: + capXmlDesc->LowestSpeed = gcnew String("high-speed"); + break; + case UsbSuperSpeed: + capXmlDesc->LowestSpeed = gcnew String("SuperSpeed"); + break; + default: + capXmlDesc->LowestSpeed = gcnew String("ERROR: Invalid value"); + break; + } + + if (capDesc->bU1DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U1_DEVICE_EXIT_MAX_VALUE) + { + capXmlDesc->U1DevExitLatencyString = String::Format("Less than {0} micro-seconds", capDesc->bU1DevExitLat); + } + else + { + capXmlDesc->U1DevExitLatencyString = gcnew String("ERROR: Invalid value"); + } + + if (capDesc->wU2DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U2_DEVICE_EXIT_MAX_VALUE) + { + capXmlDesc->U2DevExitLatencyString = String::Format("Less than {0} micro-seconds", capDesc->wU2DevExitLat); + } + else + { + capXmlDesc->U2DevExitLatencyString = gcnew String("ERROR: Invalid value"); + } + + return capXmlDesc; +} + +/***************************************************************************** + + XmlGetContainerIdCapabilityExtensionDescriptor() + + Gets a Usb20Capability extension descriptor object from the given descriptor + *****************************************************************************/ +UsbDispContIdCapExtDescriptorType ^ XmlGetContainerIdCapabilityExtensionDescriptor( + PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR capDesc + ) +{ + UsbDispContIdCapExtDescriptorType ^ capXmlDesc = nullptr; + LPGUID pGuid = NULL; + + if(NULL == capDesc) + { + return nullptr; + } + + capXmlDesc = gcnew UsbDispContIdCapExtDescriptorType(); + + capXmlDesc->BLength = capDesc->bLength; + capXmlDesc->BDescriptorType = capDesc->bDescriptorType; + capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; + capXmlDesc->BReserved = capDesc->bReserved; + + if (capDesc->bReserved != 0) + { + capXmlDesc->ReservedBitError = gcnew String("ERROR: field is reserved and should be zero"); + } + + pGuid = (LPGUID) capDesc->ContainerID; + + capXmlDesc->ContainerIdStr = String::Format("{0:X}-{1:X}-{2:X}-{3:X}{4:X}-{5:X}{6:X}{7:X}{8:X}{9:X}{10:X}", + pGuid->Data1, + pGuid->Data2, + pGuid->Data3, + pGuid->Data4[0], + pGuid->Data4[1], + pGuid->Data4[2], + pGuid->Data4[3], + pGuid->Data4[4], + pGuid->Data4[5], + pGuid->Data4[6], + pGuid->Data4[7]); + + return capXmlDesc; +} + + +/***************************************************************************** + +XmlGetBillboardCapabilityDescriptor() + +Gets a billboard capability descriptor from a given descriptor +*****************************************************************************/ +UsbBillboardCapabilityDescriptorType ^ XmlGetBillboardCapabilityDescriptor( + PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR capDesc, + PSTRING_DESCRIPTOR_NODE stringDesc + ) +{ + UCHAR i = 0; + UCHAR bNumAlternateModes = 0; + UCHAR alternateModeConfiguration = 0; + UsbBillboardCapabilityDescriptorType ^ capXmlDesc = nullptr; + UsbBillboardSVIDType ^ svidXmlDesc = nullptr; + ArrayList ^ usbSVIDDescList = gcnew ArrayList(); + + + if (NULL == capDesc) + { + return nullptr; + } + + capXmlDesc = gcnew UsbBillboardCapabilityDescriptorType(); + + + capXmlDesc->BLength = capDesc->bLength; + capXmlDesc->BDescriptorType = capDesc->bDescriptorType; + capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; + capXmlDesc->IAddtionalInfoURL = capDesc->iAddtionalInfoURL; + capXmlDesc->BNumberOfAlternateModes = capDesc->bNumberOfAlternateModes; + capXmlDesc->BPreferredAlternateMode = capDesc->bPreferredAlternateMode; + capXmlDesc->CalculatedBLength = sizeof(USB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) + + sizeof(capDesc->AlternateMode[0]) * (capDesc->bNumberOfAlternateModes - 1); + capXmlDesc->BillboardDescriptorErrors = gcnew String(""); + capXmlDesc->AddtionalInfoURL = XmlGetStringDescriptor( + capDesc->iAddtionalInfoURL, + stringDesc, + false + ); + + if (capDesc->VconnPower.NoVconnPowerRequired) + { + capXmlDesc->VConnPower = gcnew String("The adapter does not require Vconn Power. Bits 2..0 ignored"); + } + else + { + switch (capDesc->VconnPower.VConnPowerNeededForFullFunctionality) + { + case 0: + capXmlDesc->VConnPower = gcnew String("1W needed by adapter for full functionality"); + break; + case 1: + capXmlDesc->VConnPower = gcnew String("1.5W needed by adapter for full functionality"); + break; + case 7: + capXmlDesc->BillboardDescriptorErrors += "ERROR: VConnPowerNeededForFullFunctionality - Reserved value being used"; + break; + default: + capXmlDesc->VConnPower = gcnew String(String::Format("{0} W needed by adapter for full functionality", capDesc->VconnPower.VConnPowerNeededForFullFunctionality)); + } + } + + if (capDesc->bNumberOfAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) + { + capXmlDesc->BillboardDescriptorErrors += "ERROR: Invalid bNumberofAlternateModes; "; + } + if (capDesc->VconnPower.Reserved) + { + capXmlDesc->BillboardDescriptorErrors += "ERROR: Reserved bits in VCONN Power being used; "; + } + if (capDesc->bReserved) + { + capXmlDesc->BillboardDescriptorErrors += "ERROR: bReserved being used; "; + } + + bNumAlternateModes = capDesc->bNumberOfAlternateModes; + if (bNumAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) + { + bNumAlternateModes = BILLBOARD_MAX_NUM_ALT_MODE; + } + for (i = 0; i < bNumAlternateModes; i++) + { + svidXmlDesc = gcnew UsbBillboardSVIDType(); + alternateModeConfiguration = ((capDesc->bmConfigured[i / 4]) >> ((i % 4) * 2)) & 0x3; + svidXmlDesc->WSVID = capDesc->AlternateMode[i].wSVID; + svidXmlDesc->BAlternateMode = capDesc->AlternateMode[i].bAlternateMode; + svidXmlDesc->IAlternateModeString = capDesc->AlternateMode[i].iAlternateModeSetting; + svidXmlDesc->AlternateModeString = XmlGetStringDescriptor( + capDesc->AlternateMode[i].iAlternateModeSetting, + stringDesc, + false + ); + + switch (alternateModeConfiguration) + { + case 0: + svidXmlDesc->Description = gcnew String("Unspecified Error"); + break; + case 1: + svidXmlDesc->Description = gcnew String("Alternate Mode configuration not attempted"); + break; + case 2: + svidXmlDesc->Description = gcnew String("Alternate Mode configuration attempted but unsuccessful"); + break; + case 3: + svidXmlDesc->Description = gcnew String("Alternate Mode configuration successful"); + break; + } + usbSVIDDescList->Add(svidXmlDesc); + } + capXmlDesc->UsbBillboardSVID = reinterpret_cast^> ( + usbSVIDDescList->ToArray(UsbBillboardSVIDType::typeid)); + + return capXmlDesc; +} + +/***************************************************************************** + + XmlAddUsbDevice() + + Add a external to the parent Host Controller or hub. This is determined by the + last object pushed on the stack + *****************************************************************************/ +HRESULT XmlAddUsbDevice(PSTR devName, PUSBDEVICEINFO deviceInfo) +{ + HRESULT hr = S_OK; + Object ^ parent = gXmlStack->Peek(); + UsbDeviceType ^usbDevice = nullptr; + NoDeviceType ^noDevice = nullptr; + + if (NULL == deviceInfo) + { + return E_FAIL; + } + + if (deviceInfo->ConfigDesc == NULL) + { + // There is no USB device on this port, add a NoDevice type here instead of USB device + noDevice = AddDisconnectedPort(parent); + + if (nullptr != noDevice) + { + noDevice->UsbPortNumber = gcnew String(""); + noDevice->UsbPortNumber += deviceInfo->ConnectionInfo->ConnectionIndex; + noDevice->Name = PACHAR_TO_STRING(devName); + } + else + { + hr = E_FAIL; + } + } + + else + { + usbDevice = AddUsbDevice(parent); + + if (nullptr != usbDevice) + { + // Update device information + if (NULL != deviceInfo->UsbDeviceProperties) + { + usbDevice->HwId = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->HwId); + usbDevice->DeviceId = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceId); + usbDevice->ServiceName = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->Service); + usbDevice->DeviceName = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceDesc); + usbDevice->DeviceClass = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceClass); + } + + // Update port number + usbDevice->UsbPortNumber = gcnew String(""); + usbDevice->UsbPortNumber += deviceInfo->ConnectionInfo->ConnectionIndex; + usbDevice->ConnectionInfo = gcnew NodeConnectionInfoExType(); + + // Update protocol + if (NULL != deviceInfo->ConnectionInfo) + { + switch(deviceInfo->ConnectionInfo->Speed) + { + case UsbLowSpeed: + case UsbFullSpeed: + usbDevice->UsbProtocol = gcnew String(USB_1_1); + break; + case UsbHighSpeed: + usbDevice->UsbProtocol = gcnew String(USB_2_0); + break; + case UsbSuperSpeed: + usbDevice->UsbProtocol = gcnew String(USB_3_0); + break; + } + } + + // Add connection info + XmlAddConnectionInfo( + usbDevice->ConnectionInfo, + deviceInfo->ConnectionInfo, + (PUSBDEVICEINFO) deviceInfo, + deviceInfo->StringDescs, + deviceInfo->DeviceInfoNode + ); + + // Add port connector + if (NULL != deviceInfo->PortConnectorProps) + { + usbDevice->PortConnector = gcnew PortConnectorType(); + + XmlAddPortConnectorProps( + usbDevice->PortConnector, + deviceInfo->PortConnectorProps + ); + } + + // Add connectiontion info V2 + if (NULL != deviceInfo->ConnectionInfoV2) + { + usbDevice->ConnectionInfoV2 = gcnew NodeConnectionInfoExV2Type(); + XmlAddConnectionInfoV2( + usbDevice->ConnectionInfoV2, + deviceInfo->ConnectionInfoV2 + ); + } + + // Add configuration descriptor + if (NULL != deviceInfo->ConfigDesc) + { + // The device configuration is allocated by XmlGetConfigDescriptors() + usbDevice->DeviceConfiguration = XmlGetConfigDescriptors( + (PUSBDEVICEINFO) deviceInfo, + (PUSB_CONFIGURATION_DESCRIPTOR) (deviceInfo->ConfigDesc + 1), + deviceInfo->StringDescs + ); + } + + // Add BOS descriptor + if (NULL != deviceInfo->BosDesc) + { + usbDevice->BosDescriptor = XmlGetBosDescriptor( + (PUSB_BOS_DESCRIPTOR) (deviceInfo->BosDesc + 1), + deviceInfo->StringDescs + ); + } + } + else + { + hr = E_FAIL; + } + } + return hr; +} + +/***************************************************************************** + + XmlAddRootHub() + + Add a root hub to the parent Host Controller + *****************************************************************************/ +HRESULT XmlAddRootHub(PSTR rhName, PUSBROOTHUBINFO rhInfo) +{ + HRESULT hr = S_OK; + Object ^ parent = gXmlStack->Peek(); + HostControllerType ^ hcParent = nullptr; + PSTR rootHubName = rhInfo->HubName; + + UNREFERENCED_PARAMETER(rhName); + + hcParent = dynamic_cast (parent); + + if (hcParent != nullptr) + { + RootHubType ^ rh = nullptr; + hcParent = (HostControllerType ^) parent; + hcParent->RootHub = gcnew RootHubType(); + + rh = hcParent->RootHub; + rh->HubName = PACHAR_TO_STRING(rootHubName); + + if (NULL != rhInfo->UsbDeviceProperties) + { + rh->HwId = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->HwId); + rh->DeviceId = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceId); + rh->ServiceName = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->Service); + rh->DeviceName = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceDesc); + rh->DeviceClass = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceClass); + + // Roothub protocol is same as HC protocol + rh->UsbProtocol = hcParent->UsbProtocol; + } + + rh->HubNodeInformation = gcnew HubNodeInformationType(); + XmlAddHubNodeInformation(rh->HubNodeInformation, rhInfo->HubInfo); + + rh->HubInformationEx = gcnew HubInformationExType(); + XmlAddHubInformationEx(rh->HubInformationEx, rhInfo->HubInfoEx); + + rh->HubCapabilityEx = gcnew HubCapabilitiesExType(); + XmlAddHubCapabilitiesEx(rh->HubCapabilityEx, rhInfo->HubCapabilityEx); + + // Push root hub on to stack + gXmlStack->Push(rh); + } + else + { + // Root hub should be connected to a host controller + hr = E_FAIL; + } + return S_OK; +} + +/***************************************************************************** + + XmlSetVersion() + + Set version information in XML tree + *****************************************************************************/ +VOID XmlSetVersion( + UCHAR uvcMajorVersion, + UCHAR uvcMinorVersion, + UCHAR uvcMajorSpecVersion, + UCHAR uvcMinorSpecVersion + ) +{ + MachineInfoType ^ mInfo; + gXmlView->MachineInfo = gcnew MachineInfoType(); + + mInfo = gXmlView->MachineInfo; + + mInfo->UvcMajorVersion = uvcMajorVersion; + mInfo->UvcMinorVersion = uvcMinorVersion; + mInfo->UvcMajorSpecVersion = uvcMajorSpecVersion; + mInfo->UvcMinorSpecVersion = uvcMinorSpecVersion; + +} + +/***************************************************************************** + + InitXmlHelper() + + Initialize XML helper + *****************************************************************************/ +HRESULT InitXmlHelper() +{ + HRESULT hr = S_OK; + + (XmlGlobal::Instance())->ViewAll = gcnew UvcViewAll(); + (XmlGlobal::Instance())->ViewAll->UvcView = gcnew UvcViewType(); + + // + // Initialize fields to null so we can check against them for allocation + // + (XmlGlobal::Instance())->ViewAll->UvcView->MachineInfo = nullptr; + (XmlGlobal::Instance())->ViewAll->UvcView->UsbTree = nullptr; + + XmlSetVersion( + UVC_SPEC_MAJOR_VERSION, + UVC_SPEC_MINOR_VERSION, + USBVIEW_MAJOR_VERSION, + USBVIEW_MINOR_VERSION + ); + + gXmlStack->Push(gXmlView); + + gXmlViewInitialized = TRUE; + + return hr; +} + +/***************************************************************************** + + SaveXml() + + Saves the inmemory USB view as XML file + *****************************************************************************/ +HRESULT SaveXml(LPTSTR szfileName, DWORD dwCreationDisposition) +{ + HRESULT hr = S_OK; + + if (gXmlViewInitialized) + { + try + { + String ^fileName = PACHAR_TO_STRING(szfileName); + XmlSerializer ^ serializer = gcnew XmlSerializer(UvcViewAll::typeid); + TextWriter ^ writer = nullptr; + + if (dwCreationDisposition != CREATE_ALWAYS) + { + // Check if file exits and return failure if it does + if (File::Exists(fileName)) + { + hr = HRESULT_FROM_WIN32(ERROR_FILE_EXISTS); + } + } + + // Check if file name is NULL + if (String::IsNullOrEmpty(fileName)) + { + hr = E_INVALIDARG; + } + + if (SUCCEEDED(hr)) + { + writer = gcnew StreamWriter(fileName); + serializer->Serialize(writer, (XmlGlobal::Instance())->ViewAll); + writer->Close(); + } + + // Release and reinit XML View for next iteration if requested + ReleaseXmlWriter(); + InitXmlHelper(); + + } + catch(Exception ^ ex) + { + hr = (HRESULT) Marshal::GetHRForException(ex); + } + } + else + { + hr = E_FAIL; + } + + return hr; +} + + +/***************************************************************************** + + ReleaseXmlWriter() + + *****************************************************************************/ +HRESULT ReleaseXmlWriter() +{ + HRESULT hr = S_OK; + + if (gXmlViewInitialized) + { + gXmlViewInitialized = FALSE; + delete XmlGlobal::Instance(); + } + + return hr; +} + diff --git a/tests/projects/windows/winsdk/usbview/xmlhelper.h b/tests/projects/windows/winsdk/usbview/xmlhelper.h new file mode 100644 index 000000000..1da37d97b --- /dev/null +++ b/tests/projects/windows/winsdk/usbview/xmlhelper.h @@ -0,0 +1,41 @@ +/*++ + +Copyright (c) 1997-2011 Microsoft Corporation + +Module Name: + + XMLHELPER.H + +Abstract: + + This helper file declaration for XML helper APIs + +Environment: + + user mode + +Revision History: + + 05-05-11 : created + +--*/ + +#pragma once + +/***************************************************************************** + I N C L U D E S +*****************************************************************************/ +#include "uvcview.h" + +EXTERN_C HRESULT InitXmlHelper(); +EXTERN_C HRESULT ReleaseXmlWriter(); +EXTERN_C HRESULT SaveXml(LPTSTR szfileName, DWORD dwCreationDisposition); +EXTERN_C HRESULT XmlAddHostController( + PSTR hcName, + PUSBHOSTCONTROLLERINFO hcInfo + ); +EXTERN_C HRESULT XmlAddRootHub(PSTR rhName, PUSBROOTHUBINFO rhInfo); +EXTERN_C HRESULT XmlAddExternalHub(PSTR ehName, PUSBEXTERNALHUBINFO ehInfo); +EXTERN_C HRESULT XmlAddUsbDevice(PSTR devName, PUSBDEVICEINFO deviceInfo); +EXTERN_C VOID XmlNotifyEndOfNodeList(PVOID pContext); + diff --git a/tests/projects/windows/winsdk/windemo/main.cpp b/tests/projects/windows/winsdk/windemo/main.cpp new file mode 100644 index 000000000..a8340d936 --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/main.cpp @@ -0,0 +1,190 @@ +// testw.cpp : Defines the entry point for the application. +// + +#include "stdafx.h" +#include "test.h" + +#define MAX_LOADSTRING 100 + +// Global Variables: +HINSTANCE hInst; // current instance +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + +// Forward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_TESTW, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTW)); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int) msg.wParam; +} + + + +// +// FUNCTION: MyRegisterClass() +// +// PURPOSE: Registers the window class. +// +// COMMENTS: +// +// This function and its usage are only necessary if you want this code +// to be compatible with Win32 systems prior to the 'RegisterClassEx' +// function that was added to Windows 95. It is important to call this function +// so that the application will get 'well formed' small icons associated +// with it. +// +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTW)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TESTW); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassEx(&wcex); +} + +// +// FUNCTION: InitInstance(HINSTANCE, int) +// +// PURPOSE: Saves instance handle and creates main window +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hInst = hInstance; // Store instance handle in our global variable + + hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + + if (!hWnd) + { + return FALSE; + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + return TRUE; +} + +// +// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) +// +// PURPOSE: Processes messages for the main window. +// +// WM_COMMAND - process the application menu +// WM_PAINT - Paint the main window +// WM_DESTROY - post a quit message and return +// +// +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + PAINTSTRUCT ps; + HDC hdc; + + switch (message) + { + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDM_ABOUT: + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + break; + case IDM_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + // TODO: Add any drawing code here... + EndPaint(hWnd, &ps); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +// Message handler for about box. +INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(lParam); + switch (message) + { + case WM_INITDIALOG: + return (INT_PTR)TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return (INT_PTR)TRUE; + } + break; + } + return (INT_PTR)FALSE; +} diff --git a/tests/projects/windows/winsdk/windemo/resource.h b/tests/projects/windows/winsdk/windemo/resource.h new file mode 100644 index 000000000..65ba8f31d --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/resource.h @@ -0,0 +1,31 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by test.rc +// + +#define IDS_APP_TITLE 103 + +#define IDR_MAINFRAME 128 +#define IDD_TESTW_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_TESTW 107 +#define IDI_SMALL 108 +#define IDC_TESTW 109 +#define IDC_MYICON 2 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/tests/projects/windows/winsdk/windemo/small.ico b/tests/projects/windows/winsdk/windemo/small.ico new file mode 100644 index 000000000..d551aa3aa Binary files /dev/null and b/tests/projects/windows/winsdk/windemo/small.ico differ diff --git a/tests/projects/windows/winsdk/windemo/stdafx.cpp b/tests/projects/windows/winsdk/windemo/stdafx.cpp new file mode 100644 index 000000000..50daaa27d --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// testw.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/tests/projects/windows/winsdk/windemo/stdafx.h b/tests/projects/windows/winsdk/windemo/stdafx.h new file mode 100644 index 000000000..de0dfa3cd --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/stdafx.h @@ -0,0 +1,21 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + +// C RunTime Header Files +#include +#include +#include +#include + + +// TODO: reference additional headers your program requires here diff --git a/tests/projects/windows/winsdk/windemo/targetver.h b/tests/projects/windows/winsdk/windemo/targetver.h new file mode 100644 index 000000000..f583181df --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/tests/projects/windows/winsdk/windemo/test b/tests/projects/windows/winsdk/windemo/test new file mode 100644 index 000000000..33639f71c --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/test @@ -0,0 +1,150 @@ +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifndef APSTUDIO_INVOKED +#include "targetver.h" +#endif +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(936) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +IDI_TESTW ICON "testw.ico" +IDI_SMALL ICON "small.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_TESTW MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_TESTW ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About testw" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20 + LTEXT "testw, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX + LTEXT "Copyright (C) 2020",IDC_STATIC,42,26,114,8 + DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP +END + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 163 + TOPMARGIN, 7 + BOTTOMMARGIN, 55 + END +END +#endif // APSTUDIO_INVOKED + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDC_TESTW "TESTW" + IDS_APP_TITLE "testw" +END + +#endif +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/tests/projects/windows/winsdk/windemo/test.h b/tests/projects/windows/winsdk/windemo/test.h new file mode 100644 index 000000000..e60f2eb7e --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/test.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/tests/projects/windows/winsdk/windemo/test.ico b/tests/projects/windows/winsdk/windemo/test.ico new file mode 100644 index 000000000..d551aa3aa Binary files /dev/null and b/tests/projects/windows/winsdk/windemo/test.ico differ diff --git a/tests/projects/windows/winsdk/windemo/test.rc b/tests/projects/windows/winsdk/windemo/test.rc new file mode 100644 index 000000000..9ef96ba63 --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/test.rc @@ -0,0 +1,150 @@ +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#ifndef APSTUDIO_INVOKED +#include "targetver.h" +#endif +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(936) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. + +IDI_TESTW ICON "test.ico" +IDI_SMALL ICON "small.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_TESTW MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_TESTW ACCELERATORS +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About testw" +FONT 8, "MS Shell Dlg" +BEGIN + ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20 + LTEXT "testw, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX + LTEXT "Copyright (C) 2020",IDC_STATIC,42,26,114,8 + DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP +END + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ABOUTBOX, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 163 + TOPMARGIN, 7 + BOTTOMMARGIN, 55 + END +END +#endif // APSTUDIO_INVOKED + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""targetver.h""\r\n" + "#endif\r\n" + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDC_TESTW "TESTW" + IDS_APP_TITLE "testw" +END + +#endif +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/tests/projects/windows/winsdk/windemo/xmake.lua b/tests/projects/windows/winsdk/windemo/xmake.lua new file mode 100644 index 000000000..1f492822e --- /dev/null +++ b/tests/projects/windows/winsdk/windemo/xmake.lua @@ -0,0 +1,12 @@ +-- add rules: debug/release +add_rules("mode.debug", "mode.release") + +-- define target +target("test") + + -- set kind + add_rules("win.sdk.application") + + -- add files + add_files("*.rc", "*.cpp") + diff --git a/tests/projects/winsdk/usbview/app.config b/tests/projects/winsdk/usbview/app.config deleted file mode 100644 index fe947d6fd..000000000 --- a/tests/projects/winsdk/usbview/app.config +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/tests/projects/winsdk/usbview/bang.ico b/tests/projects/winsdk/usbview/bang.ico deleted file mode 100644 index 90fe0f220..000000000 Binary files a/tests/projects/winsdk/usbview/bang.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/codeanalysis.h b/tests/projects/winsdk/usbview/codeanalysis.h deleted file mode 100644 index 56fa54a1a..000000000 --- a/tests/projects/winsdk/usbview/codeanalysis.h +++ /dev/null @@ -1,133 +0,0 @@ -/*++ - -Copyright (c) 1997-2011 Microsoft Corporation - -Module Name: - - CODEANALYSIS.H - -Abstract: - - This header file is used for supressing fxcop errors which are not applicable - -Environment: - - user mode - -Revision History: - - 08-11-11 : created - ---*/ - -#pragma once - -#if CODE_ANALYSIS - -/***************************************************************************** - C O D E A N A L Y S I S S U P P R E S S I O N S - *****************************************************************************/ - -using namespace System::Diagnostics::CodeAnalysis; - -namespace Microsoft -{ - namespace Kits - { - namespace Samples - { - namespace Usb - { - // Justification : C++ Compiler cannot enforce ClsCompliant - [module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant")] - - // Justification : The naming of the following types are based on native USB types - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType", MessageId="Bos")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.Hub30DescriptorType.#HubHdrDecLat", MessageId="Hdr")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMajorSpecVersion", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMinorSpecVersion", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMinorVersion", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.MachineInfoType.#UvcMajorVersion", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceClassDetailsType.#UvcVersion", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#BNumDeviceCaps", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbDispContIdCapExtDescriptor", MessageId="Disp")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#BosDescriptor", MessageId="Bos")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExType.#IProductStringDescEn", MessageId="Desc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#OtgDescriptor", MessageId="Otg")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#OtgError", MessageId="Otg")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#IadError", MessageId="Iad")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#IadDescriptor", MessageId="Iad")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceIADDescriptorType.#StringDesc", MessageId="Desc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceInterfaceDescriptorType.#BNumEndpoints", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceInterfaceDescriptorType.#StringDesc", MessageId="Desc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceInterfaceDescriptorType.#WNumClasses", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExStructType.#NumOfOpenPipes", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExStructType.#SpeedStr", MessageId="Str")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#ConfStringDesc", MessageId="Desc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#AttributesStr", MessageId="Str")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#ConfigDescError", MessageId="Desc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#BNumInterfaces", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UvcViewAll", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UvcViewAll.#UvcView", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbDispContIdCapExtDescriptorType", MessageId="Disp")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDispContIdCapExtDescriptorType.#ContainerIdStr", MessageId="Str")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConnectionStatusType.#DeviceCausedOvercurrent", MessageId="Overcurrent")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceQualifierDescriptorType.#NumConfigurations", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceQualifierDescriptorType.#DeviceNumConfigError", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#NumConfigurations", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceType.#BosDescriptor", MessageId="Bos")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UvcViewType", MessageId="Uvc")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceHidDescriptorType.#BNumDescriptors", MessageId="Num")]; - [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#HubInformationEx")]; - [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#HubInformationEx")]; - [module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceConfigurationType.#PreReleaseError", MessageId="PreRelease")]; - [module: SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbHCPowerStateType.#CanWakeUp", MessageId="WakeUp")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbSuperSpeedExtensionDescriptorType.#BmAttributes", MessageId="Bm")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbUsb20ExtensionDescriptorType.#BmAttributes", MessageId="Bm")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubNodeType.#UsbMiParent", MessageId="Mi")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#HwId", MessageId="Hw")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HostControllerType.#HwId", MessageId="Hw")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbDeviceOTGDescriptorType", MessageId="OTG")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceOTGDescriptorType.#BmAttributes", MessageId="Bm")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubNodeInformationType.#MiParentNumberOfInterfaces", MessageId="Mi")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExType.#IProductStringDescEn", MessageId="En")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="type", Target="Microsoft.Kits.Samples.Usb.UsbDeviceIADDescriptorType", MessageId="IAD")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbConfigurationDescriptorType.#BmAttributes", MessageId="Bm")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#HwId", MessageId="Hw")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceQualifierDescriptorType.#BcdUSB", MessageId="USB")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#CdDevice", MessageId="Cd")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#CdUSB", MessageId="USB")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceDescriptorType.#CdUSB", MessageId="Cd")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceType.#HwId", MessageId="Hw")]; - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceHidDescriptorType.#BcdHID", MessageId="HID")]; - [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#HubCapabilityEx")] - [module: SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#HubCapabilityEx")] - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubCapabilitiesExType.#HubIsMultiTt", MessageId="Multi")] - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope="member", Target="Microsoft.Kits.Samples.Usb.HubCapabilitiesExType.#HubIsMultiTtCapable", MessageId="Multi")] - - [module: SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId="usbview")]; - [module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="usbview")]; - - // Justification: The version of XSD which is used to generate the objects does not support Collections. - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbSuperSpeedExtensionDescriptor")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbUsb20ExtensionDescriptor")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UnknownDescriptor")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbBosDescriptorType.#UsbDispContIdCapExtDescriptor")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#UsbDevice")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#DeviceConfiguration")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#NoDevice")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.ExternalHubType.#ExternalHub")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.NodeConnectionInfoExStructType.#Pipe")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbHCPowerStateMappingType.#PowerMap")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#NoDevice")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#ExternalHub")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.RootHubType.#UsbDevice")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceType.#DeviceConfiguration")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UvcViewType.#UsbTree")]; - [module: SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Scope="member", Target="Microsoft.Kits.Samples.Usb.UsbDeviceHidDescriptorType.#OptionalDescriptor")]; - }; - }; - }; -}; - -#endif diff --git a/tests/projects/winsdk/usbview/debug.c b/tests/projects/winsdk/usbview/debug.c deleted file mode 100644 index b73d727d5..000000000 --- a/tests/projects/winsdk/usbview/debug.c +++ /dev/null @@ -1,210 +0,0 @@ -/*++ - -Copyright (c) 1997-2008 Microsoft Corporation - -Module Name: - - DEBUG.C - -Abstract: - - This source file contains debug routines. - -Environment: - - user mode - -Revision History: - - 07-08-97 : created - ---*/ - -/***************************************************************************** - I N C L U D E S -*****************************************************************************/ - -#include "uvcview.h" - -#if DBG - -/***************************************************************************** - T Y P E D E F S -*****************************************************************************/ - -typedef struct _ALLOCHEADER -{ - LIST_ENTRY ListEntry; - - PCHAR File; - - ULONG Line; - -} ALLOCHEADER, *PALLOCHEADER; - - -/***************************************************************************** - G L O B A L S -*****************************************************************************/ - -LIST_ENTRY AllocListHead = -{ - &AllocListHead, - &AllocListHead -}; - - -/***************************************************************************** - - MyAlloc() - -*****************************************************************************/ -_Success_(return != NULL) -_Post_writable_byte_size_(dwBytes) -HGLOBAL -MyAlloc ( - _In_ PCHAR File, - ULONG Line, - DWORD dwBytes -) -{ - PALLOCHEADER header; - DWORD dwRequest = dwBytes; - - if (0 == dwBytes) - { - return NULL; - } - - dwBytes += sizeof(ALLOCHEADER); - // check for integer overflow - if (dwBytes > dwRequest) - { - header = (PALLOCHEADER)GlobalAlloc(GPTR, dwBytes); - - if (header != NULL) - { - InsertTailList(&AllocListHead, &header->ListEntry); - - header->File = File; - header->Line = Line; - - return (HGLOBAL)(header + 1); - } - } - return NULL; -} - -/***************************************************************************** - - MyReAlloc() - -*****************************************************************************/ - -_Success_(return != NULL) -_Post_writable_byte_size_(dwBytes) -HGLOBAL -MyReAlloc ( - HGLOBAL hMem, - DWORD dwBytes -) -{ - PALLOCHEADER header; - PALLOCHEADER headerNew; - - if ((NULL == hMem) || (0 == dwBytes)) - { - return NULL; - } - - header = (PALLOCHEADER)hMem; - header--; - - // Remove the old address from the allocation list - // - RemoveEntryList(&header->ListEntry); - - if (dwBytes < (dwBytes + (DWORD) sizeof(ALLOCHEADER))) - { - dwBytes += sizeof(ALLOCHEADER); - headerNew = GlobalReAlloc((HGLOBAL)header, dwBytes, GMEM_MOVEABLE|GMEM_ZEROINIT); - - if (NULL == headerNew) - { - // If GlobalReAlloc fails, the original memory is not freed, - // and the original handle and pointer are still valid. - // Add the old address back to the allocation list. - // - #pragma prefast(suppress:__WARNING_USING_UNINIT_VAR, "SAL noise") - InsertTailList(&AllocListHead, &header->ListEntry); - } - else - { - // Add the new address to the allocation list - // - InsertTailList(&AllocListHead, &headerNew->ListEntry); - - return (HGLOBAL)(headerNew + 1); - } - } - return NULL; -} - - -/***************************************************************************** - - MyFree() - -*****************************************************************************/ - -HGLOBAL -MyFree ( - HGLOBAL hMem -) -{ - PALLOCHEADER header; - - if (hMem) - { - header = (PALLOCHEADER)hMem; - - header--; - - RemoveEntryList(&header->ListEntry); - - return GlobalFree((HGLOBAL)header); - } - - return GlobalFree(hMem); -} - -/***************************************************************************** - - MyCheckForLeaks() - -*****************************************************************************/ - -VOID -MyCheckForLeaks ( - VOID -) -{ - PALLOCHEADER header; - CHAR buf[128]; - - memset(buf, 0, sizeof(buf)); - - while (!IsListEmpty(&AllocListHead)) - { - header = (PALLOCHEADER)RemoveHeadList(&AllocListHead); - - StringCbPrintf(buf, sizeof(buf), - "File: %s, Line: %d\r\n", - header->File, - header->Line); - - OutputDebugString(buf); - } -} - -#endif diff --git a/tests/projects/winsdk/usbview/devnode.c b/tests/projects/winsdk/usbview/devnode.c deleted file mode 100644 index d9a3b8ecc..000000000 --- a/tests/projects/winsdk/usbview/devnode.c +++ /dev/null @@ -1,336 +0,0 @@ -/*++ - - Copyright (c) 1998-2011 Microsoft Corporation - - Module Name: - - DEVNODE.C - - --*/ - -/***************************************************************************** - I N C L U D E S - *****************************************************************************/ - -#include "uvcview.h" - -/***************************************************************************** - - DriverNameToDeviceInst() - - Finds the Device instance of the DevNode with the matching DriverName. - Returns FALSE if the matching DevNode is not found and TRUE if found - - *****************************************************************************/ -BOOL -DriverNameToDeviceInst( - _In_reads_bytes_(cbDriverName) PCHAR DriverName, - _In_ size_t cbDriverName, - _Out_ HDEVINFO *pDevInfo, - _Out_writes_bytes_(sizeof(SP_DEVINFO_DATA)) PSP_DEVINFO_DATA pDevInfoData - ) -{ - HDEVINFO deviceInfo = INVALID_HANDLE_VALUE; - BOOL status = TRUE; - ULONG deviceIndex; - SP_DEVINFO_DATA deviceInfoData; - BOOL bResult = FALSE; - PCHAR pDriverName = NULL; - PSTR buf = NULL; - BOOL done = FALSE; - - if (pDevInfo == NULL) - { - return FALSE; - } - - if (pDevInfoData == NULL) - { - return FALSE; - } - - memset(pDevInfoData, 0, sizeof(SP_DEVINFO_DATA)); - - *pDevInfo = INVALID_HANDLE_VALUE; - - // Use local string to guarantee zero termination - pDriverName = (PCHAR) ALLOC((DWORD) cbDriverName + 1); - if (NULL == pDriverName) - { - status = FALSE; - goto Done; - } - StringCbCopyN(pDriverName, cbDriverName + 1, DriverName, cbDriverName); - - // - // We cannot walk the device tree with CM_Get_Sibling etc. unless we assume - // the device tree will stabilize. Any devnode removal (even outside of USB) - // would force us to retry. Instead we use Setup API to snapshot all - // devices. - // - - // Examine all present devices to see if any match the given DriverName - // - deviceInfo = SetupDiGetClassDevs(NULL, - NULL, - NULL, - DIGCF_ALLCLASSES | DIGCF_PRESENT); - - if (deviceInfo == INVALID_HANDLE_VALUE) - { - status = FALSE; - goto Done; - } - - deviceIndex = 0; - deviceInfoData.cbSize = sizeof(deviceInfoData); - - while (done == FALSE) - { - // - // Get devinst of the next device - // - - status = SetupDiEnumDeviceInfo(deviceInfo, - deviceIndex, - &deviceInfoData); - - deviceIndex++; - - if (!status) - { - // - // This could be an error, or indication that all devices have been - // processed. Either way the desired device was not found. - // - - done = TRUE; - break; - } - - // - // Get the DriverName value - // - - bResult = GetDeviceProperty(deviceInfo, - &deviceInfoData, - SPDRP_DRIVER, - &buf); - - // If the DriverName value matches, return the DeviceInstance - // - if (bResult == TRUE && buf != NULL && _stricmp(pDriverName, buf) == 0) - { - done = TRUE; - *pDevInfo = deviceInfo; - CopyMemory(pDevInfoData, &deviceInfoData, sizeof(deviceInfoData)); - FREE(buf); - break; - } - - if(buf != NULL) - { - FREE(buf); - buf = NULL; - } - } - -Done: - - if (bResult == FALSE) - { - if (deviceInfo != INVALID_HANDLE_VALUE) - { - SetupDiDestroyDeviceInfoList(deviceInfo); - } - } - - if (pDriverName != NULL) - { - FREE(pDriverName); - } - - return status; -} - -/***************************************************************************** - - DriverNameToDeviceProperties() - - Returns the Device properties of the DevNode with the matching DriverName. - Returns NULL if the matching DevNode is not found. - - The caller should free the returned structure using FREE() macro - - *****************************************************************************/ -PUSB_DEVICE_PNP_STRINGS -DriverNameToDeviceProperties( - _In_reads_bytes_(cbDriverName) PCHAR DriverName, - _In_ size_t cbDriverName - ) -{ - HDEVINFO deviceInfo = INVALID_HANDLE_VALUE; - SP_DEVINFO_DATA deviceInfoData = {0}; - ULONG len; - BOOL status; - PUSB_DEVICE_PNP_STRINGS DevProps = NULL; - DWORD lastError; - - // Allocate device propeties structure - DevProps = (PUSB_DEVICE_PNP_STRINGS) ALLOC(sizeof(USB_DEVICE_PNP_STRINGS)); - - if(NULL == DevProps) - { - status = FALSE; - goto Done; - } - - // Get device instance - status = DriverNameToDeviceInst(DriverName, cbDriverName, &deviceInfo, &deviceInfoData); - if (status == FALSE) - { - goto Done; - } - - len = 0; - status = SetupDiGetDeviceInstanceId(deviceInfo, - &deviceInfoData, - NULL, - 0, - &len); - lastError = GetLastError(); - - - if (status != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER) - { - status = FALSE; - goto Done; - } - - // - // An extra byte is required for the terminating character - // - - len++; - DevProps->DeviceId = ALLOC(len); - - if (DevProps->DeviceId == NULL) - { - status = FALSE; - goto Done; - } - - status = SetupDiGetDeviceInstanceId(deviceInfo, - &deviceInfoData, - DevProps->DeviceId, - len, - &len); - if (status == FALSE) - { - goto Done; - } - - status = GetDeviceProperty(deviceInfo, - &deviceInfoData, - SPDRP_DEVICEDESC, - &DevProps->DeviceDesc); - - if (status == FALSE) - { - goto Done; - } - - - // - // We don't fail if the following registry query fails as these fields are additional information only - // - - GetDeviceProperty(deviceInfo, - &deviceInfoData, - SPDRP_HARDWAREID, - &DevProps->HwId); - - GetDeviceProperty(deviceInfo, - &deviceInfoData, - SPDRP_SERVICE, - &DevProps->Service); - - GetDeviceProperty(deviceInfo, - &deviceInfoData, - SPDRP_CLASS, - &DevProps->DeviceClass); -Done: - - if (deviceInfo != INVALID_HANDLE_VALUE) - { - SetupDiDestroyDeviceInfoList(deviceInfo); - } - - if (status == FALSE) - { - if (DevProps != NULL) - { - FreeDeviceProperties(&DevProps); - } - } - return DevProps; -} - -/***************************************************************************** - - FreeDeviceProperties() - - Free the device properties structure - - *****************************************************************************/ -VOID FreeDeviceProperties(_In_ PUSB_DEVICE_PNP_STRINGS *ppDevProps) -{ - if(ppDevProps == NULL) - { - return; - } - - if(*ppDevProps == NULL) - { - return; - } - - if ((*ppDevProps)->DeviceId != NULL) - { - FREE((*ppDevProps)->DeviceId); - } - - if ((*ppDevProps)->DeviceDesc != NULL) - { - FREE((*ppDevProps)->DeviceDesc); - } - - // - // The following are not necessary, but left in case - // in the future there is a later failure where these - // pointer fields would be allocated. - // - - if ((*ppDevProps)->HwId != NULL) - { - FREE((*ppDevProps)->HwId); - } - - if ((*ppDevProps)->Service != NULL) - { - FREE((*ppDevProps)->Service); - } - - if ((*ppDevProps)->DeviceClass != NULL) - { - FREE((*ppDevProps)->DeviceClass); - } - - if ((*ppDevProps)->PowerState != NULL) - { - FREE((*ppDevProps)->PowerState); - } - - FREE(*ppDevProps); - *ppDevProps = NULL; -} diff --git a/tests/projects/winsdk/usbview/dispaud.c b/tests/projects/winsdk/usbview/dispaud.c deleted file mode 100644 index bbc16a912..000000000 --- a/tests/projects/winsdk/usbview/dispaud.c +++ /dev/null @@ -1,1164 +0,0 @@ -/*++ - -Copyright (c) 1997-2008 Microsoft Corporation - -Module Name: - -DISPAUD.C - -Abstract: - -This source file contains routines which update the edit control -to display information about USB Audio descriptors. - -Environment: - -user mode - -Revision History: - -03-07-1998 : created - ---*/ - -/***************************************************************************** - I N C L U D E S -*****************************************************************************/ - -#include "uvcview.h" - -/***************************************************************************** - G L O B A L S P R I V A T E T O T H I S F I L E -*****************************************************************************/ - -// -// USB Device Class Definition for Terminal Types 0.9 Draft Revision -// -STRINGLIST slAudioTerminalTypes [] = -{ - // - // 2.1 USB Terminal Types - // - {0x0100, "USB Undefined", ""}, - {0x0101, "USB streaming", ""}, - {0x01FF, "USB vendor specific", ""}, - // - // 2.2 Input Terminal Types - // - {0x0200, "Input Undefined", ""}, - {0x0201, "Microphone", ""}, - {0x0202, "Desktop microphone", ""}, - {0x0203, "Personal microphone", ""}, - {0x0204, "Omni-directional microphone", ""}, - {0x0205, "Microphone array", ""}, - {0x0206, "Processing microphone array", ""}, - // - // 2.3 Output Terminal Types - // - {0x0300, "Output Undefined", ""}, - {0x0301, "Speaker", ""}, - {0x0302, "Headphones", ""}, - {0x0303, "Head Mounted Display Audio", ""}, - {0x0304, "Desktop speaker", ""}, - {0x0305, "Room speaker", ""}, - {0x0306, "Communication speaker", ""}, - {0x0307, "Low frequency effects speaker", ""}, - // - // 2.4 Bi-directional Terminal Types - // - {0x0400, "Bi-directional Undefined", ""}, - {0x0401, "Handset", ""}, - {0x0402, "Headset", ""}, - {0x0403, "Speakerphone, no echo reduction", ""}, - {0x0404, "Echo-suppressing speakerphone", ""}, - {0x0405, "Echo-canceling speakerphone", ""}, - // - // 2.5 Telephony Terminal Types - // - {0x0500, "Telephony Undefined", ""}, - {0x0501, "Phone line", ""}, - {0x0502, "Telephone", ""}, - {0x0503, "Down Line Phone", ""}, - // - // 2.6 External Terminal Types - // - {0x0600, "External Undefined", ""}, - {0x0601, "Analog connector", ""}, - {0x0602, "Digital audio interface", ""}, - {0x0603, "Line connector", ""}, - {0x0604, "Legacy audio connector", ""}, - {0x0605, "S/PDIF interface", ""}, - {0x0606, "1394 DA stream", ""}, - {0x0607, "1394 DV stream soundtrack", ""}, - // - // Embedded Function Terminal Types - // - {0x0700, "Embedded Undefined", ""}, - {0x0701, "Level Calibration Noise Source", ""}, - {0x0702, "Equalization Noise", ""}, - {0x0703, "CD player", ""}, - {0x0704, "DAT", ""}, - {0x0705, "DCC", ""}, - {0x0706, "MiniDisk", ""}, - {0x0707, "Analog Tape", ""}, - {0x0708, "Phonograph", ""}, - {0x0709, "VCR Audio", ""}, - {0x070A, "Video Disc Audio", ""}, - {0x070B, "DVD Audio", ""}, - {0x070C, "TV Tuner Audio", ""}, - {0x070D, "Satellite Receiver Audio", ""}, - {0x070E, "Cable Tuner Audio", ""}, - {0x070F, "DSS Audio", ""}, - {0x0710, "Radio Receiver", ""}, - {0x0711, "Radio Transmitter", ""}, - {0x0712, "Multi-track Recorder", ""}, - {0x0713, "Synthesizer", ""}, -}; -STRINGLIST slAudioFormatTypes [] = -{ - // - // A.1.1 Audio Data Format Type I Codes - // - {0x0000, "TYPE_I_UNDEFINED", ""}, - {0x0001, "PCM", ""}, - {0x0002, "PCM8", ""}, - {0x0003, "IEEE_FLOAT", ""}, - {0x0004, "ALAW", ""}, - {0x0005, "MULAW", ""}, - // - // A.1.2 Audio Data Format Type II Codes - // - {0x1000, "TYPE_II_UNDEFINED", ""}, - {0x1001, "MPEG", ""}, - {0x1002, "AC-3", ""}, - // - // A.1.3 Audio Data Format Type III Codes - // - {0x2000, "TYPE_III_UNDEFINED", ""}, - {0x2001, "IEC1937_AC-3", ""}, - {0x2002, "IEC1937_MPEG-1_Layer1", ""}, - {0x2003, "IEC1937_MPEG-1_Layer2/3 or IEC1937_MPEG-2_NOEXT", ""}, - {0x2004, "IEC1937_MPEG-2_EXT", ""}, - {0x2005, "IEC1937_MPEG-2_Layer1_LS", ""}, - {0x2006, "IEC1937_MPEG-2_Layer2/3_LS", ""}, -}; - - - -/***************************************************************************** - L O C A L F U N C T I O N P R O T O T Y P E S -*****************************************************************************/ - -BOOL -DisplayACHeader ( - PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR HeaderDesc -); - -BOOL -DisplayACInputTerminal ( - PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR ITDesc -); - -BOOL -DisplayACOutputTerminal ( - PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR OTDesc -); - -BOOL -DisplayACMixerUnit ( - PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR MixerDesc -); - -BOOL -DisplayACSelectorUnit ( - PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR SelectorDesc -); - -BOOL -DisplayACFeatureUnit ( - PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR FeatureDesc -); - -BOOL -DisplayACProcessingUnit ( - PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR ProcessingDesc -); - -BOOL -DisplayACExtensionUnit ( - PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR ExtensionDesc -); - -BOOL -DisplayASGeneral ( - PUSB_AUDIO_GENERAL_DESCRIPTOR GeneralDesc -); - -BOOL -DisplayCSEndpoint ( - PUSB_AUDIO_ENDPOINT_DESCRIPTOR EndpointDesc -); - -BOOL -DisplayASFormatType ( - PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR FormatDesc -); - -BOOL -DisplayASFormatSpecific ( - PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc -); - -VOID -DisplayBytes ( - PUCHAR Data, - USHORT Len -); - -/***************************************************************************** - L O C A L F U N C T I O N S -*****************************************************************************/ - -/***************************************************************************** - - DisplayAudioDescriptor() - - CommonDesc - An Audio Class Descriptor - - bInterfaceSubClass - The SubClass of the Interface containing the descriptor - -*****************************************************************************/ - -BOOL -DisplayAudioDescriptor ( - PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc, - UCHAR bInterfaceSubClass -) -{ - switch (CommonDesc->bDescriptorType) - { - case USB_AUDIO_CS_INTERFACE: - switch (bInterfaceSubClass) - { - case USB_AUDIO_SUBCLASS_AUDIOCONTROL: - switch (CommonDesc->bDescriptorSubtype) - { - case USB_AUDIO_AC_HEADER: - return DisplayACHeader((PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_INPUT_TERMINAL: - return DisplayACInputTerminal((PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_OUTPUT_TERMINAL: - return DisplayACOutputTerminal((PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_MIXER_UNIT: - return DisplayACMixerUnit((PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_SELECTOR_UNIT: - return DisplayACSelectorUnit((PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_FEATURE_UNIT: - return DisplayACFeatureUnit((PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_PROCESSING_UNIT: - return DisplayACProcessingUnit((PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AC_EXTENSION_UNIT: - return DisplayACExtensionUnit((PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR)CommonDesc); - - default: - break; - } - break; - - case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: - switch (CommonDesc->bDescriptorSubtype) - { - case USB_AUDIO_AS_GENERAL: - return DisplayASGeneral((PUSB_AUDIO_GENERAL_DESCRIPTOR)CommonDesc); - - case USB_AUDIO_AS_FORMAT_TYPE: - return DisplayASFormatType((PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR)CommonDesc); - break; - - case USB_AUDIO_AS_FORMAT_SPECIFIC: - return DisplayASFormatSpecific(CommonDesc); - - default: - break; - } - break; - - default: - break; - } - break; - - case USB_AUDIO_CS_ENDPOINT: - return DisplayCSEndpoint((PUSB_AUDIO_ENDPOINT_DESCRIPTOR)CommonDesc); - - default: - break; - } - - return FALSE; -} - - -/***************************************************************************** - - DisplayACHeader() - -*****************************************************************************/ - -BOOL -DisplayACHeader ( - PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR HeaderDesc -) -{ - UINT i = 0; - - if (HeaderDesc->bLength < sizeof(USB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Interface Header Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - HeaderDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - HeaderDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - HeaderDesc->bDescriptorSubtype); - - AppendTextBuffer("bcdADC: 0x%04X\r\n", - HeaderDesc->bcdADC); - - AppendTextBuffer("wTotalLength: 0x%04X\r\n", - HeaderDesc->wTotalLength); - - AppendTextBuffer("bInCollection: 0x%02X\r\n", - HeaderDesc->bInCollection); - - for (i=0; ibInCollection; i++) - { - AppendTextBuffer("baInterfaceNr[%d]: 0x%02X\r\n", - i+1, - HeaderDesc->baInterfaceNr[i]); - } - - return TRUE; -} - - -/***************************************************************************** - - DisplayACInputTerminal() - -*****************************************************************************/ - -BOOL -DisplayACInputTerminal ( - PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR ITDesc -) -{ - PCHAR pStr = NULL; - - if (ITDesc->bLength != sizeof(USB_AUDIO_INPUT_TERMINAL_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Input Terminal Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - ITDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - ITDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - ITDesc->bDescriptorSubtype); - - AppendTextBuffer("bTerminalID: 0x%02X\r\n", - ITDesc->bTerminalID); - - AppendTextBuffer("wTerminalType: 0x%04X", - ITDesc->wTerminalType); - pStr = GetStringFromList(slAudioTerminalTypes, - sizeof(slAudioTerminalTypes) / sizeof(STRINGLIST), - ITDesc->wTerminalType, - "Invalid AC Input Terminal Type"); - AppendTextBuffer(" (%s)\r\n", pStr); - - AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", - ITDesc->bAssocTerminal); - - AppendTextBuffer("bNrChannels: 0x%02X\r\n", - ITDesc->bNrChannels); - - AppendTextBuffer("wChannelConfig: 0x%04X\r\n", - ITDesc->wChannelConfig); - - AppendTextBuffer("iChannelNames: 0x%02X\r\n", - ITDesc->iChannelNames); - - AppendTextBuffer("iTerminal: 0x%02X\r\n", - ITDesc->iTerminal); - - - return TRUE; -} - - -/***************************************************************************** - - DisplayACOutputTerminal() - -*****************************************************************************/ - -BOOL -DisplayACOutputTerminal ( - PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR OTDesc -) -{ - PCHAR pStr = NULL; - - if (OTDesc->bLength != sizeof(USB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Output Terminal Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - OTDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - OTDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - OTDesc->bDescriptorSubtype); - - AppendTextBuffer("bTerminalID: 0x%02X\r\n", - OTDesc->bTerminalID); - - AppendTextBuffer("wTerminalType: 0x%04X", - OTDesc->wTerminalType); - - pStr = GetStringFromList(slAudioTerminalTypes, - sizeof(slAudioTerminalTypes) / sizeof(STRINGLIST), - OTDesc->wTerminalType, - "Invalid AC Output Terminal Type"); - AppendTextBuffer(" (%s)\r\n", pStr); - - AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", - OTDesc->bAssocTerminal); - - AppendTextBuffer("bSourceID: 0x%02X\r\n", - OTDesc->bSourceID); - - AppendTextBuffer("iTerminal: 0x%02X\r\n", - OTDesc->iTerminal); - - - return TRUE; -} - - -/***************************************************************************** - - DisplayACMixerUnit() - -*****************************************************************************/ - -BOOL -DisplayACMixerUnit ( - PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR MixerDesc -) -{ - UCHAR i = 0; - PUCHAR data = NULL; - - if (MixerDesc->bLength < 10) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Mixer Unit Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - MixerDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - MixerDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - MixerDesc->bDescriptorSubtype); - - AppendTextBuffer("bUnitID: 0x%02X\r\n", - MixerDesc->bUnitID); - - AppendTextBuffer("bNrInPins: 0x%02X\r\n", - MixerDesc->bNrInPins); - - for (i=0; ibNrInPins; i++) - { - AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", - i+1, - MixerDesc->baSourceID[i]); - } - - data = &MixerDesc->baSourceID[MixerDesc->bNrInPins]; - - AppendTextBuffer("bNrChannels: 0x%02X\r\n", - *data++); - - AppendTextBuffer("wChannelConfig: 0x%04X\r\n", - *(PUSHORT)data); - - data = (PUCHAR) ((PUSHORT) data + 1); - - AppendTextBuffer("iChannelNames: 0x%02X\r\n", - *data++); - - AppendTextBuffer("bmControls:\r\n"); - - i = MixerDesc->bLength - 10 - MixerDesc->bNrInPins; - - DisplayBytes(data, i); - - data += i; - - AppendTextBuffer("iMixer: 0x%02X\r\n", - *data); - - return TRUE; -} - - -/***************************************************************************** - - DisplayACSelectorUnit() - -*****************************************************************************/ - -BOOL -DisplayACSelectorUnit ( - PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR SelectorDesc -) -{ - UCHAR i = 0; - PUCHAR data = NULL; - - if (SelectorDesc->bLength < 6) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Selector Unit Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - SelectorDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - SelectorDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - SelectorDesc->bDescriptorSubtype); - - AppendTextBuffer("bUnitID: 0x%02X\r\n", - SelectorDesc->bUnitID); - - AppendTextBuffer("bNrInPins: 0x%02X\r\n", - SelectorDesc->bNrInPins); - - for (i=0; ibNrInPins; i++) - { - AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", - i+1, - SelectorDesc->baSourceID[i]); - } - - data = &SelectorDesc->baSourceID[SelectorDesc->bNrInPins]; - - AppendTextBuffer("iSelector: 0x%02X\r\n", - *data); - - return TRUE; -} - - -/***************************************************************************** - - DisplayACFeatureUnit() - -*****************************************************************************/ - -BOOL -DisplayACFeatureUnit ( - PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR FeatureDesc -) -{ - UCHAR i = 0; - UCHAR n = 0; - UCHAR ch = 0; - PUCHAR data = NULL; - - AppendTextBuffer("\r\n ===>Audio Control Feature Unit Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - FeatureDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - FeatureDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - FeatureDesc->bDescriptorSubtype); - - AppendTextBuffer("bUnitID: 0x%02X\r\n", - FeatureDesc->bUnitID); - - AppendTextBuffer("bSourceID: 0x%02X\r\n", - FeatureDesc->bSourceID); - - AppendTextBuffer("bControlSize: 0x%02X\r\n", - FeatureDesc->bControlSize); - - - if (FeatureDesc->bLength < 7) - { - AppendTextBuffer("*!*WARNING: bLength is invalid (< 7)\r\n"); - OOPS(); - return FALSE; - } - else if(FeatureDesc->bLength == 7) - { - AppendTextBuffer("Audio controls are not available (bLength = 7)\r\n"); - return TRUE; - } - - n = FeatureDesc->bControlSize; - - if(n == 0) - { - AppendTextBuffer("Audio controls are not available (bControlSize = 0)\r\n"); - return TRUE; - } - - ch = ((FeatureDesc->bLength - 7) / n) - 1; - - // Check if there are extra bytes in descriptor based on formula in Spec - if (FeatureDesc->bLength != (7 + (ch + 1) * n)) - { - // The descriptor length is greater than number of bmaControls - AppendTextBuffer("*!*WARNING: bLength is greater than number of bmaControls (bLength > ( 7 + (ch + 1) * n)\r\n"); - } - - data = &FeatureDesc->bmaControls[0]; - - if (ch == (UCHAR) -1) - { - // This should not happen, but this check is put in place so we don't loop for a long time below - AppendTextBuffer("*!*WARNING: Either bLength or bControlSize are invalid. The calculated logical channel count is -1. ((bLength - 7)/ n) - 1\r\n"); - OOPS(); - return FALSE; - } - - for (i=0; i<=ch; i++) - { - AppendTextBuffer("bmaControls[%d]: ", i); - DisplayBytes(data, n); - - data += n; - } - - - AppendTextBuffer("iFeature: 0x%02X\r\n", - *data); - - return TRUE; -} - - -/***************************************************************************** - - DisplayACProcessingUnit() - -*****************************************************************************/ - -BOOL -DisplayACProcessingUnit ( - PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR ProcessingDesc -) -{ - UCHAR i = 0; - PUCHAR data = NULL; - - if (ProcessingDesc->bLength < sizeof(USB_AUDIO_PROCESSING_UNIT_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Processing Unit Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - ProcessingDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - ProcessingDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - ProcessingDesc->bDescriptorSubtype); - - AppendTextBuffer("bUnitID: 0x%02X\r\n", - ProcessingDesc->bUnitID); - - AppendTextBuffer("wProcessType: 0x%04X", - ProcessingDesc->wProcessType); - - switch (ProcessingDesc->wProcessType) - { - case USB_AUDIO_PROCESS_UNDEFINED: - AppendTextBuffer("(Undefined Process)\r\n"); - break; - - case USB_AUDIO_PROCESS_UPDOWNMIX: - AppendTextBuffer("(Up / Down Mix Process)\r\n"); - break; - - case USB_AUDIO_PROCESS_DOLBYPROLOGIC: - AppendTextBuffer("(Dolby Prologic Process)\r\n"); - break; - - case USB_AUDIO_PROCESS_3DSTEREOEXTENDER: - AppendTextBuffer("(3D-Stereo Extender Process)\r\n"); - break; - - case USB_AUDIO_PROCESS_REVERBERATION: - AppendTextBuffer("(Reverberation Process)\r\n"); - break; - - case USB_AUDIO_PROCESS_CHORUS: - AppendTextBuffer("(Chorus Process)\r\n"); - break; - - case USB_AUDIO_PROCESS_DYNRANGECOMP: - AppendTextBuffer("(Dynamic Range Compressor Process)\r\n"); - break; - - default: - AppendTextBuffer("\r\n"); - break; - } - - AppendTextBuffer("bNrInPins: 0x%02X\r\n", - ProcessingDesc->bNrInPins); - - for (i=0; ibNrInPins; i++) - { - AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", - i+1, - ProcessingDesc->baSourceID[i]); - } - - data = &ProcessingDesc->baSourceID[ProcessingDesc->bNrInPins]; - - AppendTextBuffer("bNrChannels: 0x%02X\r\n", - *data++); - - AppendTextBuffer("wChannelConfig: 0x%04X\r\n", - *(PUSHORT)data); - - data = (PUCHAR) ((PUSHORT) data + 1); - - AppendTextBuffer("iChannelNames: 0x%02X\r\n", - *data++); - - i = *data++; - - AppendTextBuffer("bControlSize: 0x%02X\r\n", - i); - - AppendTextBuffer("bmControls:\r\n"); - - DisplayBytes(data, i); - - data += i; - - AppendTextBuffer("iProcessing: 0x%02X\r\n", - *data++); - - - i = ProcessingDesc->bLength - 13 - ProcessingDesc->bNrInPins - i; - - if (i) - { - AppendTextBuffer("Process Specific:\r\n"); - - DisplayBytes(data, i); - } - - return TRUE; -} - - -/***************************************************************************** - - DisplayACExtensionUnit() - -*****************************************************************************/ - -BOOL -DisplayACExtensionUnit ( - PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR ExtensionDesc -) -{ - UCHAR i = 0; - PUCHAR data = NULL; - - if (ExtensionDesc->bLength < 13) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Control Extension Unit Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - ExtensionDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - ExtensionDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - ExtensionDesc->bDescriptorSubtype); - - AppendTextBuffer("bUnitID: 0x%02X\r\n", - ExtensionDesc->bUnitID); - - AppendTextBuffer("wExtensionCode: 0x%04X\r\n", - ExtensionDesc->wExtensionCode); - - - AppendTextBuffer("bNrInPins: 0x%02X\r\n", - ExtensionDesc->bNrInPins); - - for (i=0; ibNrInPins; i++) - { - AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", - i+1, - ExtensionDesc->baSourceID[i]); - } - - data = &ExtensionDesc->baSourceID[ExtensionDesc->bNrInPins]; - - AppendTextBuffer("bNrChannels: 0x%02X\r\n", - *data++); - - AppendTextBuffer("wChannelConfig: 0x%04X\r\n", - *(PUSHORT)data); - - data = (PUCHAR) ((PUSHORT) data + 1); - - AppendTextBuffer("iChannelNames: 0x%02X\r\n", - *data++); - - i = *data++; - - AppendTextBuffer("bControlSize: 0x%02X\r\n", - i); - - AppendTextBuffer("bmControls:\r\n"); - - DisplayBytes(data, i); - - data += i; - - AppendTextBuffer("iExtension: 0x%02X\r\n", - *data); - return TRUE; -} - - -/***************************************************************************** - - DisplayASGeneral() - -*****************************************************************************/ - -BOOL -DisplayASGeneral ( - PUSB_AUDIO_GENERAL_DESCRIPTOR GeneralDesc -) -{ - PCHAR pStr = NULL; - - if (GeneralDesc->bLength != sizeof(USB_AUDIO_GENERAL_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Streaming Class Specific Interface Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - GeneralDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - GeneralDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - GeneralDesc->bDescriptorSubtype); - - AppendTextBuffer("bTerminalLink: 0x%02X\r\n", - GeneralDesc->bTerminalLink); - - AppendTextBuffer("bDelay: 0x%02X\r\n", - GeneralDesc->bDelay); - - AppendTextBuffer("wFormatTag: 0x%04X", - GeneralDesc->wFormatTag); - - pStr = GetStringFromList(slAudioFormatTypes, - sizeof(slAudioFormatTypes) / sizeof(STRINGLIST), - GeneralDesc->wFormatTag, - "Invalid AC Format Type"); - AppendTextBuffer(" (%s)\r\n", pStr); - - return TRUE; -} - - -/***************************************************************************** - - DisplayCSEndpoint() - -*****************************************************************************/ - -BOOL -DisplayCSEndpoint ( - PUSB_AUDIO_ENDPOINT_DESCRIPTOR EndpointDesc -) -{ - if (EndpointDesc->bLength != sizeof(USB_AUDIO_ENDPOINT_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Streaming Class Specific Audio Data Endpoint Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - EndpointDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - EndpointDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - EndpointDesc->bDescriptorSubtype); - - AppendTextBuffer("bmAttributes: 0x%02X\r\n", - EndpointDesc->bmAttributes); - - AppendTextBuffer("bLockDelayUnits: 0x%02X\r\n", - EndpointDesc->bLockDelayUnits); - - AppendTextBuffer("wLockDelay: 0x%04X\r\n", - EndpointDesc->wLockDelay); - - return TRUE; -} - - -/***************************************************************************** - - DisplayASFormatType() - -*****************************************************************************/ - -BOOL -DisplayASFormatType ( - PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR FormatDesc -) -{ - UCHAR i = 0; - UCHAR n = 0; - ULONG freq = 0; - PUCHAR data = NULL; - - if (FormatDesc->bLength < sizeof(USB_AUDIO_COMMON_FORMAT_DESCRIPTOR)) - { - OOPS(); - return FALSE; - } - - AppendTextBuffer("\r\n ===>Audio Streaming Format Type Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - FormatDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - FormatDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - FormatDesc->bDescriptorSubtype); - - AppendTextBuffer("bFormatType: 0x%02X\r\n", - FormatDesc->bFormatType); - - - if (FormatDesc->bFormatType == 0x01 || - FormatDesc->bFormatType == 0x03) - { - PUSB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR FormatI_IIIDesc; - - FormatI_IIIDesc = (PUSB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR)FormatDesc; - - AppendTextBuffer("bNrChannels: 0x%02X\r\n", - FormatI_IIIDesc->bNrChannels); - - AppendTextBuffer("bSubframeSize: 0x%02X\r\n", - FormatI_IIIDesc->bSubframeSize); - - AppendTextBuffer("bBitResolution: 0x%02X\r\n", - FormatI_IIIDesc->bBitResolution); - - AppendTextBuffer("bSamFreqType: 0x%02X\r\n", - FormatI_IIIDesc->bSamFreqType); - - data = (PUCHAR)(FormatI_IIIDesc + 1); - - n = FormatI_IIIDesc->bSamFreqType; - - } - else if (FormatDesc->bFormatType == 0x02) - { - PUSB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR FormatIIDesc; - - FormatIIDesc = (PUSB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR)FormatDesc; - - AppendTextBuffer("wMaxBitRate: 0x%04X\r\n", - FormatIIDesc->wMaxBitRate); - - AppendTextBuffer("wSamplesPerFrame: 0x%04X\r\n", - FormatIIDesc->wSamplesPerFrame); - - AppendTextBuffer("bSamFreqType: 0x%02X\r\n", - FormatIIDesc->bSamFreqType); - - data = (PUCHAR)(FormatIIDesc + 1); - - n = FormatIIDesc->bSamFreqType; - } - else - { - data = NULL; - } - - if (data != NULL) - { - if (n == 0) - { - freq = (data[0]) + (data[1] << 8) + (data[2] << 16); - data += 3; - - AppendTextBuffer("tLowerSamFreq: 0x%06X (%d Hz)\r\n", - freq, - freq); - - freq = (data[0]) + (data[1] << 8) + (data[2] << 16); - data += 3; - - AppendTextBuffer("tUpperSamFreq: 0x%06X (%d Hz)\r\n", - freq, - freq); - } - else - { - for (i=0; iAudio Streaming Format Specific Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - CommonDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - CommonDesc->bDescriptorType); - - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", - CommonDesc->bDescriptorSubtype); - - DisplayBytes((PUCHAR)(CommonDesc + 1), - CommonDesc->bLength); - - return TRUE; -} - -/***************************************************************************** - - DisplayBytes() - -*****************************************************************************/ - -VOID -DisplayBytes ( - PUCHAR Data, - USHORT Len -) -{ - USHORT i; - - for (i = 0; i < Len; i++) - { - AppendTextBuffer("%02X ", Data[i]); - - if (i % 16 == 15) - { - AppendTextBuffer("\r\n"); - } - } - - if (i % 16 != 0) - { - AppendTextBuffer("\r\n"); - } -} - - diff --git a/tests/projects/winsdk/usbview/display.c b/tests/projects/winsdk/usbview/display.c deleted file mode 100644 index beead6d93..000000000 --- a/tests/projects/winsdk/usbview/display.c +++ /dev/null @@ -1,5242 +0,0 @@ -/*++ - -Copyright (c) 1997-2011 Microsoft Corporation - -Module Name: - -DISPLAY.C - -Abstract: - -This source file contains the routines which update the edit control -to display information about the selected USB device. - -Environment: - -user mode - -Revision History: - -04-25-97 : created -03-28-03 : extensive changes to support new USBVCD -03-28-08 : extensive changes to support new USB Video Class 1.1 - ---*/ - -/***************************************************************************** -I N C L U D E S -*****************************************************************************/ - -#include "uvcview.h" -#include "h264.h" -#include - -#include "vndrlist.h" -#include "langidlist.h" - -/***************************************************************************** -D E F I N E S -*****************************************************************************/ - -#define BUFFERALLOCINCREMENT 0x10000 -#define BUFFERMINFREESPACE 0x1000 - -/***************************************************************************** -T Y P E D E F S -*****************************************************************************/ - -// -// Hardcoded information about specific EHCI controllers -// -typedef struct _EHCI_CONTROLLER_DATA -{ - USHORT VendorID; - USHORT DeviceID; - UCHAR DebugPortNumber; -} EHCI_CONTROLLER_DATA, *PEHCI_CONTROLLER_DATA; - - -/***************************************************************************** -G L O B A L S P R I V A T E T O T H I S F I L E -*****************************************************************************/ - -// Workspace for text info which is used to update the edit control -// -CHAR *TextBuffer = NULL; -UINT TextBufferLen = 0; -UINT TextBufferPos = 0; - -STRINGLIST slPowerState [] = -{ - {WdmUsbPowerNotMapped, "S? (unmapped) ", ""}, - - {WdmUsbPowerSystemUnspecified, "S? (unspecified)", ""}, - {WdmUsbPowerSystemWorking, "S0 (working) ", ""}, - {WdmUsbPowerSystemSleeping1, "S1 (sleep) ", ""}, - {WdmUsbPowerSystemSleeping2, "S2 (sleep) ", ""}, - {WdmUsbPowerSystemSleeping3, "S3 (sleep) ", ""}, - {WdmUsbPowerSystemHibernate, "S4 (Hibernate) ", ""}, - {WdmUsbPowerSystemShutdown, "S5 (shutdown) ", ""}, - - {WdmUsbPowerDeviceUnspecified, "D? (unspecified)", ""}, - {WdmUsbPowerDeviceD0, "D0 ", ""}, - {WdmUsbPowerDeviceD1, "D1 ", ""}, - {WdmUsbPowerDeviceD2, "D2 ", ""}, - {WdmUsbPowerDeviceD3, "D3 ", ""}, -}; - -STRINGLIST slControllerFlavor[] = -{ - { USB_HcGeneric, "USB_HcGeneric", "" }, - { OHCI_Generic, "OHCI_Generic", "" }, - { OHCI_Hydra, "OHCI_Hydra", "" }, - { OHCI_NEC, "OHCI_NEC", "" }, - { UHCI_Generic, "UHCI_Generic", "" }, - { UHCI_Piix4, "UHCI_Piix4", "" }, - { UHCI_Piix3, "UHCI_Piix3", "" }, - { UHCI_Ich2, "UHCI_Ich2", "" }, - { UHCI_Reserved204, "UHCI_Reserved204", "" }, - { UHCI_Ich1, "UHCI_Ich1", "" }, - { UHCI_Ich3m, "UHCI_Ich3m", "" }, - { UHCI_Ich4, "UHCI_Ich4", "" }, - { UHCI_Ich5, "UHCI_Ich5", "" }, - { UHCI_Ich6, "UHCI_Ich6", "" }, - { UHCI_Intel, "UHCI_Intel", "" }, - { UHCI_VIA, "UHCI_VIA", "" }, - { UHCI_VIA_x01, "UHCI_VIA_x01", "" }, - { UHCI_VIA_x02, "UHCI_VIA_x02", "" }, - { UHCI_VIA_x03, "UHCI_VIA_x03", "" }, - { UHCI_VIA_x04, "UHCI_VIA_x04", "" }, - { UHCI_VIA_x0E_FIFO, "UHCI_VIA_x0E_FIFO", "" }, - { EHCI_Generic, "EHCI_Generic", "" }, - { EHCI_NEC, "EHCI_NEC", "" }, - { EHCI_Lucent, "EHCI_Lucent", "" }, - { EHCI_NVIDIA_Tegra2, "EHCI_NVIDIA_Tegra2", "" }, - { EHCI_NVIDIA_Tegra3, "EHCI_NVIDIA_Tegra3", "" }, - { EHCI_Intel_Medfield, "EHCI_Intel_Medfield", "" } -}; - -// -// For supporting pre Win8 versions of Windows, a hardcoded list is maintained for determining -// debug port numbers. As usbport.inf is augmented with new host controllers, this list should -// be updated. -// -// The following entries do not have a debug port: -// PCI\VEN_8086&DEV_0806 - "Intel(R) SM35 Express Chipset USB2 Enhanced Host Controller MPH - 0806" -// PCI\VEN_8086&DEV_0811 - "Intel(R) SM35 Express Chipset USB2 Enhanced Host Controller SPM - 0811" -// - -EHCI_CONTROLLER_DATA EhciControllerData[] = -{ - {0x8086, 0x24CD, 1}, // ICH4 - Intel(R) 82801DB/DBM USB 2.0 Enhanced Host Controller - 24CD - {0x8086, 0x24DD, 1}, // ICH5 - Intel(R) 82801EB USB2 Enhanced Host Controller - 24DD - {0x8086, 0x25AD, 1}, // ICH5 - Intel(R) 6300ESB USB2 Enhanced Host Controller - 25AD - {0x8086, 0x265C, 1}, // ICH6 - Intel(R) 82801FB/FBM USB2 Enhanced Host Controller - 265C - {0x8086, 0x268C, 1}, // Intel(R) 631xESB/6321ESB/3100 Chipset USB2 Enhanced Host Controller - 268C - {0x8086, 0x27CC, 1}, // ICH7 - Intel(R) 82801G (ICH7 Family) USB2 Enhanced Host Controller - 27CC - {0x8086, 0x2836, 1}, // ICH8 - Intel(R) ICH8 Family USB2 Enhanced Host Controller - 2836 - {0x8086, 0x283A, 1}, // ICH8 - Intel(R) ICH8 Family USB2 Enhanced Host Controller - 283A - {0x8086, 0x293A, 1}, // ICH9 - Intel(R) ICH9 Family USB2 Enhanced Host Controller - 293A - {0x8086, 0x293C, 1}, // ICH9 - Intel(R) ICH9 Family USB2 Enhanced Host Controller - 293C - {0x8086, 0x3A3A, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A3A - {0x8086, 0x3A3C, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A3C - {0x8086, 0x3A6A, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A6A - {0x8086, 0x3A6C, 1}, // ICH10 - Intel(R) ICH10 Family USB Enhanced Host Controller - 3A6C - {0x8086, 0x3B34, 2}, // 5 series - Intel(R) 5 Series/3400 Series Chipset Family USB Enhanced Host Controller - 3B34 - {0x8086, 0x3B36, 2}, // 5 series - Intel(R) 5 Series/3400 Series Chipset Family USB Universal Host Controller - 3B36 - {0x8086, 0x1C26, 2}, // 6 series - Intel(R) 6 Series/C200 Series Chipset Family USB Enhanced Host Controller - 1C26 - {0x8086, 0x1C2D, 2}, // 6 series - Intel(R) 6 Series/C200 Series Chipset Family USB Enhanced Host Controller - 1C2D - {0x8086, 0x1D26, 2}, // Intel(R) C600/X79 series chipset USB2 Enhanced Host Controller #1 - 1D26 - {0x8086, 0x1D2D, 2}, // Intel(R) C600/X79 series chipset USB2 Enhanced Host Controller #2 - 1D2D - {0x8086, 0x268C, 1}, // Intel(R) 631xESB/6321ESB/3100 Chipset USB2 Enhanced Host Controller - 268C - {0x10DE, 0x00D8, 1}, - {0,0,0}, -}; - - -/***************************************************************************** -L O C A L F U N C T I O N P R O T O T Y P E S -*****************************************************************************/ - -VOID -DisplayPortConnectorProperties ( - _In_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 - ); - -void -DisplayDevicePowerState ( - _In_ PDEVICE_INFO_NODE DeviceInfoNode - ); - -VOID -DisplayHubInfo ( - PUSB_HUB_INFORMATION HubInfo, - BOOL DisplayDescriptor - ); - -VOID -DisplayHubInfoEx ( - PUSB_HUB_INFORMATION_EX HubInfoEx - ); - -VOID -DisplayHubCapabilityEx ( - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx - ); - -VOID -DisplayPowerState( - PUSB_POWER_INFO pUPI - ); - -VOID -DisplayConnectionInfo ( - _In_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, - _In_ PUSBDEVICEINFO info, - _In_ PSTRING_DESCRIPTOR_NODE StringDescs, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 - ); - -VOID -DisplayPipeInfo ( - ULONG NumPipes, - USB_PIPE_INFO *PipeInfo - ); - -VOID -DisplayConfigDesc ( - PUSBDEVICEINFO info, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ); - -VOID -DisplayBosDescriptor ( - PUSBDEVICEINFO info, - PUSB_BOS_DESCRIPTOR BosDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ); - -VOID -DisplayBillboardCapabilityDescriptor ( - PUSBDEVICEINFO info, - PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR billboardCapDesc, - PSTRING_DESCRIPTOR_NODE StringDescs -); - -VOID -DisplayDeviceQualifierDescriptor ( - PUSB_DEVICE_QUALIFIER_DESCRIPTOR DevQualDesc - ); - -VOID -DisplayConfigurationDescriptor ( - PUSBDEVICEINFO info, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ); - -VOID -DisplayInterfaceDescriptor ( - PUSB_INTERFACE_DESCRIPTOR InterfaceDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -VOID -DisplayEndpointDescriptor ( - _In_ PUSB_ENDPOINT_DESCRIPTOR - EndpointDesc, - _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR - EpCompDesc, - _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR - SspIsochCompDesc, - _In_ UCHAR InterfaceClass, - _In_ BOOLEAN EpCompDescAvail - ); - -VOID -DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor( - _In_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR SspIsochEpCompDesc - ); - -VOID -DisplayEndointCompanionDescriptor ( - _In_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR EpCompDesc, - _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR - SspIsochEpCompDesc, - _In_ UCHAR DescType - ); - - -VOID -DisplayHidDescriptor ( - PUSB_HID_DESCRIPTOR HidDesc - ); - -VOID -DisplayOTGDescriptor ( - PUSB_OTG_DESCRIPTOR OTGDesc - ); - -void -InitializePerDeviceSettings ( - PUSBDEVICEINFO info - ); - -UINT -IsUVCDevice ( - PUSBDEVICEINFO info - ); - -VOID -DisplayIADDescriptor ( - PUSB_IAD_DESCRIPTOR IADDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - int nInterfaces, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -VOID -DisplayUSEnglishStringDescriptor ( - UCHAR Index, - PSTRING_DESCRIPTOR_NODE USStringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -VOID -DisplayUnknownDescriptor ( - PUSB_COMMON_DESCRIPTOR CommonDesc - ); - -VOID -DisplayRemainingUnknownDescriptor( - PUCHAR DescriptorData, - ULONG Start, - ULONG Stop - ); - -PCHAR -GetVendorString ( - USHORT idVendor - ); - -PCHAR -GetLangIDString ( - USHORT idLang - ); - -UINT -GetConfigurationSize ( - PUSBDEVICEINFO info - ); - -UINT -GetInterfaceCount ( - PUSBDEVICEINFO info - ); - - -/***************************************************************************** -L O C A L F U N C T I O N S -*****************************************************************************/ - -/***************************************************************************** - -NextDescriptor() - -*****************************************************************************/ -//__forceinline -PUSB_COMMON_DESCRIPTOR -NextDescriptor( - _In_ PUSB_COMMON_DESCRIPTOR Descriptor - ) -{ - if (Descriptor->bLength == 0) - { - return NULL; - } - return (PUSB_COMMON_DESCRIPTOR)((PUCHAR)Descriptor + Descriptor->bLength); -} - -/***************************************************************************** - -GetNextDescriptor() - -*****************************************************************************/ -PUSB_COMMON_DESCRIPTOR -GetNextDescriptor( - _In_reads_bytes_(TotalLength) - PUSB_COMMON_DESCRIPTOR FirstDescriptor, - _In_ - ULONG TotalLength, - _In_ - PUSB_COMMON_DESCRIPTOR StartDescriptor, - _In_ long - DescriptorType - ) -{ - PUSB_COMMON_DESCRIPTOR currentDescriptor = NULL; - PUSB_COMMON_DESCRIPTOR endDescriptor = NULL; - - endDescriptor = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)FirstDescriptor + TotalLength); - - if (StartDescriptor >= endDescriptor || - NextDescriptor(StartDescriptor)>= endDescriptor) - { - return NULL; - } - - if (DescriptorType == -1) // -1 means any type - { - return NextDescriptor(StartDescriptor); - } - - currentDescriptor = StartDescriptor; - - while (((currentDescriptor = NextDescriptor(currentDescriptor)) < endDescriptor) - && currentDescriptor != NULL) - { - if (currentDescriptor->bDescriptorType == (UCHAR)DescriptorType) - { - return currentDescriptor; - } - } - return NULL; -} - - - -/***************************************************************************** - -CreateTextBuffer() - -*****************************************************************************/ - -BOOL -CreateTextBuffer ( - ) -{ - // Allocate the buffer - // - TextBuffer = ALLOC(BUFFERALLOCINCREMENT); - - if (TextBuffer == NULL) - { - OOPS(); - - return FALSE; - } - - TextBufferLen = BUFFERALLOCINCREMENT; - - // Reset the buffer position and terminate the buffer - // - memset(TextBuffer, 0, BUFFERALLOCINCREMENT); - TextBufferPos = 0; - - return TRUE; -} - - -/***************************************************************************** - -DestroyTextBuffer() - -*****************************************************************************/ - -VOID -DestroyTextBuffer ( - ) -{ - if (TextBuffer != NULL) - { - FREE(TextBuffer); - - TextBuffer = NULL; - } -} - - -/***************************************************************************** - -ResetTextBuffer() - -*****************************************************************************/ - -BOOL -ResetTextBuffer ( - ) -{ - // Fail if the text buffer has not been allocated - // - if (TextBuffer == NULL) - { - OOPS(); - - return FALSE; - } - - // Reset the buffer position and terminate the buffer - // - *TextBuffer = 0; - TextBufferPos = 0; - - return TRUE; -} - - -/***************************************************************************** - -GetTextBufferPos() - -*****************************************************************************/ - -UINT -GetTextBufferPos ( - ) -{ - return TextBufferPos; -} - - -/***************************************************************************** - -AppendTextBuffer() - -*****************************************************************************/ - -VOID __cdecl -AppendTextBuffer ( - LPCTSTR lpFormat, - ... - ) -{ - va_list arglist; - HRESULT hr = S_OK; - int nPos = TextBufferPos; - char LocalTextBuffer[512]; - - va_start(arglist, lpFormat); - - // Make sure we have a healthy amount of space free in the buffer, - // reallocating the buffer if necessary. - // - - if (TextBufferLen - TextBufferPos < BUFFERMINFREESPACE) - { - CHAR *TextBufferTmp; - UINT uNewTextBufferLen = 0; - hr = UIntAdd(TextBufferLen, BUFFERALLOCINCREMENT, &uNewTextBufferLen); - - if (hr != S_OK) - { - // we've exceeded DWORD length of (2^32)-1 for buffer - OOPS(); - - return; - } - - TextBufferTmp = REALLOC(TextBuffer, uNewTextBufferLen); - - if (TextBufferTmp != NULL) - { - TextBuffer = TextBufferTmp; - TextBufferLen += BUFFERALLOCINCREMENT; // update TextBufferLen to reflect the new, bigger size of the text buffer - } - else - { - // If GlobalReAlloc fails, the original memory is not freed, - // and the original handle and pointer are still valid. - // - - OOPS(); - - return; - } - } - - // Add the text to the end of the buffer - // - hr = StringCchVPrintf(LocalTextBuffer, sizeof(LocalTextBuffer), lpFormat, arglist); - if (SUCCEEDED(hr)) - { - size_t cbMax = 512; - size_t pcb = 0; - - // Ensure TextBuffer is zero terminated - // The text buffer size is specified by TextBufferLen. - // the text buffer size will be bigger than BUFFERALLOCINCREMENT if the buffer has been reallocated more than - // once (which would happen if it had to be made bigger to hold more text) - hr = StringCbLength((LPCTSTR) TextBuffer, - TextBufferLen, // the maximum number of bytes allowed in TextBuffer. - &pcb); - - if (FAILED(hr)) // buffer is not null-terminated, go ahead and do that - { - TextBuffer[TextBufferLen-1] = 0; - } - hr = StringCbLength((LPCTSTR) LocalTextBuffer, cbMax, &pcb); - if (SUCCEEDED(hr)) - { - StringCbCatN(TextBuffer, TextBufferLen, LocalTextBuffer, pcb); - - // Increment the text position by the number of charcters we just added to it. - TextBufferPos += (UINT) pcb; - } - - // If DebugLog flag set, send output to the debugger - // - if (gLogDebug) - { - OutputDebugString(TextBuffer + nPos); // print the string just added to the text buffer - } - } -} - -//***************************************************************************** -// -// GetTextBuffer -// -// Returns the display text buffer -// -//***************************************************************************** -PCHAR GetTextBuffer(void) -{ - return (TextBuffer); -} - - -//***************************************************************************** -// -// GetEhciDebugPort -// -// Returns debug port value if present for EHCI controller. 0 if its not present -// -//***************************************************************************** -ULONG GetEhciDebugPort(ULONG vendorId, ULONG deviceId) -{ - int i = 0; - ULONG debugPort = 0; - - for (i = 0; EhciControllerData[i].VendorID != 0; i++) - { - if (vendorId == EhciControllerData[i].VendorID && - deviceId == EhciControllerData[i].DeviceID) - { - debugPort = EhciControllerData[i].DebugPortNumber; - break; - } - } - - return debugPort; -} - -//***************************************************************************** -// -// UpdateTreeItemDeviceInfo -// -// hTreeItem - Handle of selected TreeView item for which information should -// be added to the TextBuffer global -// -// The functions returns error status if AppendTextBuffer() used in Display*() functions -// fails. The display text would be missing or truncated in such cases. -//***************************************************************************** -HRESULT -UpdateTreeItemDeviceInfo( - HWND hTreeWnd, - HTREEITEM hTreeItem - ) -{ - TV_ITEM tvi; - PVOID info; - ULONG i; - HRESULT hr = S_OK; - PCHAR tviName = NULL; - - SetLastError(0); - -#ifndef H264_SUPPORT - UNREFERENCED_PARAMETER(bShowVersion) -#endif - -#ifdef H264_SUPPORT - ResetErrorCounts(); -#endif - - tviName = ALLOC(256); - - if(NULL == tviName) - { - OOPS(); - hr = E_OUTOFMEMORY; - return hr; - } - - // - // Get the name of the TreeView item, along with the a pointer to the - // info we stored about the item in the item's lParam. - // - - tvi.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM; - tvi.hItem = hTreeItem; - tvi.pszText = (LPSTR) tviName; - tvi.cchTextMax = 256; - - TreeView_GetItem(hTreeWnd, - &tvi); - - info = (PVOID)tvi.lParam; - - AppendTextBuffer(tviName); - AppendTextBuffer("\r\n"); - - // - // If we didn't store any info for the item, just display the item's - // name, else display the info we stored for the item. - // - if (NULL != info) - { - PUSB_NODE_INFORMATION HubInfo = NULL; - PCHAR HubName = NULL; - PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo = NULL; - PUSB_DESCRIPTOR_REQUEST ConfigDesc = NULL; - PSTRING_DESCRIPTOR_NODE StringDescs = NULL; - PUSB_HUB_INFORMATION_EX HubInfoEx = NULL; - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx = NULL; - PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps = NULL; - PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 = NULL; - PUSB_DESCRIPTOR_REQUEST BosDesc = NULL; - PDEVICE_INFO_NODE DeviceInfoNode = NULL; - - // The TextBuffer has the TreeView name; add 2 lines for display - AppendTextBuffer("\r\n\r\n"); - - switch (*(PUSBDEVICEINFOTYPE)info) - { - case HostControllerInfo: - { - HTREEITEM rootHubItem = NULL; - BOOL dbgPortFound = FALSE; - - AppendTextBuffer("DriverKey: %s\r\n", - ((PUSBHOSTCONTROLLERINFO)info)->DriverKey); - - AppendTextBuffer("VendorID: %04X\r\n", - ((PUSBHOSTCONTROLLERINFO)info)->VendorID); - - AppendTextBuffer("DeviceID: %04X\r\n", - ((PUSBHOSTCONTROLLERINFO)info)->DeviceID); - - AppendTextBuffer("SubSysID: %08X\r\n", - ((PUSBHOSTCONTROLLERINFO)info)->SubSysID); - - AppendTextBuffer("Revision: %02X\r\n", - ((PUSBHOSTCONTROLLERINFO)info)->Revision); - - // - // Search for the debug port number. If running on Win8 or later, - // the USB_PORT_CONNECTOR_PROPERTIES structure will contain the - // port number. If that fails, the list of known host controllers - // with debug ports will be searched. - // - - AppendTextBuffer("\r\nDebug Port Number: "); - - rootHubItem = TreeView_GetChild(hTreeWnd, hTreeItem); - - if (rootHubItem != NULL) - { - HTREEITEM portItem = NULL; - PVOID portInfo; - - portItem = TreeView_GetChild(hTreeWnd, rootHubItem); - - while (portItem != NULL) - { - tvi.mask = TVIF_PARAM; - tvi.hItem = portItem; - tvi.pszText = NULL; - tvi.cchTextMax = 0; - - TreeView_GetItem(hTreeWnd, &tvi); - - portInfo = (PVOID)tvi.lParam; - - // - // Note that an empty port is a port without a device attached - // is still a DeviceInfo instance. - // - - if ((*(PUSBDEVICEINFOTYPE)portInfo) == DeviceInfo) - { - ConnectionInfo = ((PUSBDEVICEINFO)portInfo)->ConnectionInfo; - PortConnectorProps = ((PUSBDEVICEINFO)portInfo)->PortConnectorProps; - } - else if ((*(PUSBDEVICEINFOTYPE)portInfo) == ExternalHubInfo) - { - ConnectionInfo = ((PUSBEXTERNALHUBINFO)portInfo)->ConnectionInfo; - PortConnectorProps = ((PUSBEXTERNALHUBINFO)portInfo)->PortConnectorProps; - - } - - if (ConnectionInfo != NULL && - PortConnectorProps != NULL && - PortConnectorProps->UsbPortProperties.PortIsDebugCapable) - { - dbgPortFound = TRUE; - AppendTextBuffer("%d\r\n", ((PUSBDEVICEINFO)portInfo)->ConnectionInfo->ConnectionIndex); - break; - } - portItem = TreeView_GetNextSibling(hTreeWnd, portItem); - } - - // - // Resetting ConnectionInfo and PortConnectorProps to NULL so that they won't be erroneously - // be displayed below. - // - - ConnectionInfo = NULL; - PortConnectorProps = NULL; - } - if (dbgPortFound == FALSE) - { - for (i = 0; EhciControllerData[i].VendorID; i++) - { - if (((PUSBHOSTCONTROLLERINFO)info)->VendorID == - EhciControllerData[i].VendorID && - ((PUSBHOSTCONTROLLERINFO)info)->DeviceID == - EhciControllerData[i].DeviceID) - { - dbgPortFound = TRUE; - AppendTextBuffer("%d\r\n", EhciControllerData[i].DebugPortNumber); - break; - } - } - } - if (dbgPortFound == FALSE) - { - AppendTextBuffer("None\r\n"); - } - - // - // Display bus/device/function to help with setting debug - // settings. - // - if (((PUSBHOSTCONTROLLERINFO)info)->BusDeviceFunctionValid) - { - AppendTextBuffer("Bus.Device.Function (in decimal): %d.%d.%d\r\n", - ((PUSBHOSTCONTROLLERINFO)info)->BusNumber, - ((PUSBHOSTCONTROLLERINFO)info)->BusDevice, - ((PUSBHOSTCONTROLLERINFO)info)->BusFunction); - } - - // Display the USB Host Controller Power State Info - { - PUSB_POWER_INFO pUPI = (PUSB_POWER_INFO) &((PUSBHOSTCONTROLLERINFO)info)->USBPowerInfo[0]; - int nIndex = 0; - int nPowerState = WdmUsbPowerSystemWorking; - - AppendTextBuffer("\r\nHost Controller Power State Mappings\r\n"); - AppendTextBuffer("System State\t\tHost Controller\t\tRoot Hub\tUSB wakeup\tPowered\r\n"); - for ( ; nPowerState < WdmUsbPowerSystemShutdown; nIndex++, nPowerState++, pUPI++) - { - DisplayPowerState(pUPI); - } - - AppendTextBuffer("%s\t%s\r\n", - "Last Sleep State", - GetPowerStateString(pUPI->LastSystemSleepState) - ); - } - - break; - } - - case RootHubInfo: - HubInfo = ((PUSBROOTHUBINFO)info)->HubInfo; - HubName = ((PUSBROOTHUBINFO)info)->HubName; - HubCapabilityEx = ((PUSBROOTHUBINFO)info)->HubCapabilityEx; - - AppendTextBuffer("Root Hub: %s\r\n", - HubName); - - break; - - case ExternalHubInfo: - HubInfo = ((PUSBEXTERNALHUBINFO)info)->HubInfo; - HubName = ((PUSBEXTERNALHUBINFO)info)->HubName; - HubInfoEx = ((PUSBEXTERNALHUBINFO)info)->HubInfoEx; - HubCapabilityEx = ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx; - ConnectionInfo = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo; - ConnectionInfoV2 = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2; - PortConnectorProps = ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps; - ConfigDesc = ((PUSBEXTERNALHUBINFO)info)->ConfigDesc; - StringDescs = ((PUSBEXTERNALHUBINFO)info)->StringDescs; - BosDesc = ((PUSBEXTERNALHUBINFO)info)->BosDesc; - DeviceInfoNode = ((PUSBEXTERNALHUBINFO)info)->DeviceInfoNode; - - AppendTextBuffer("External Hub: %s\r\n", - HubName); - break; - - case DeviceInfo: - ConnectionInfo = ((PUSBDEVICEINFO)info)->ConnectionInfo; - ConnectionInfoV2 = ((PUSBDEVICEINFO)info)->ConnectionInfoV2; - PortConnectorProps = ((PUSBDEVICEINFO)info)->PortConnectorProps; - ConfigDesc = ((PUSBDEVICEINFO)info)->ConfigDesc; - StringDescs = ((PUSBDEVICEINFO)info)->StringDescs; - BosDesc = ((PUSBDEVICEINFO)info)->BosDesc; - DeviceInfoNode = ((PUSBDEVICEINFO)info)->DeviceInfoNode; - break; - } - - if (PortConnectorProps) - { - DisplayPortConnectorProperties(PortConnectorProps, ConnectionInfoV2); - } - - if (DeviceInfoNode) - { - DisplayDevicePowerState(DeviceInfoNode); - } - - if (HubInfo) - { - DisplayHubInfo(&HubInfo->u.HubInformation, - (HubInfoEx == NULL)); - } - - if (HubInfoEx) - { - DisplayHubInfoEx(HubInfoEx); - } - - if(HubCapabilityEx) - { - DisplayHubCapabilityEx(HubCapabilityEx); - } - - if (ConnectionInfo) - { - DisplayConnectionInfo(ConnectionInfo, - (PUSBDEVICEINFO)info, - StringDescs, - ConnectionInfoV2); - } - - if (ConfigDesc) - { - DisplayConfigDesc((PUSBDEVICEINFO)info, - (PUSB_CONFIGURATION_DESCRIPTOR)(ConfigDesc + 1), - StringDescs); - } - - if (BosDesc) - { - DisplayBosDescriptor((PUSBDEVICEINFO) info, - (PUSB_BOS_DESCRIPTOR) (BosDesc + 1), - StringDescs); - } - } - - if(tviName != NULL) - { - FREE(tviName); - } - - // AppendTextBuffer() which is used in Display*() functions uses GlobalRealloc() which can fail if realloc fails. - // Obtain last error code from GetLastError() and propagate the error to caller. - hr = HRESULT_FROM_WIN32(GetLastError()); - - return hr; -} - -//***************************************************************************** -// -// UpdateEditControl() -// -// hTreeItem - Handle of selected TreeView item for which information should -// be displayed in the edit control. -// -//***************************************************************************** - -VOID -UpdateEditControl ( - HWND hEditWnd, - HWND hTreeWnd, - HTREEITEM hTreeItem -) -{ - HRESULT hr = S_OK; - - // Start with an empty text buffer. - // - if (!ResetTextBuffer()) - { - return; - } - - // Get the item information in global TextBuffer - hr = UpdateTreeItemDeviceInfo(hTreeWnd, hTreeItem); - - if(FAILED(hr)) - { - OOPS(); - } - - // All done formatting text buffer with info, now update the edit - // control with the contents of the text buffer - // - SetWindowText(hEditWnd, TextBuffer); - -} - -/***************************************************************************** - -DisplayPortConnectorProperties() - -PortConnectorProps - Info about the port connector properties. - -*****************************************************************************/ - -void -DisplayPortConnectorProperties ( - _In_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 - ) -{ - AppendTextBuffer("Is Port User Connectable: %s\r\n", - PortConnectorProps->UsbPortProperties.PortIsUserConnectable - ? "yes" : "no"); - - AppendTextBuffer("Is Port Debug Capable: %s\r\n", - PortConnectorProps->UsbPortProperties.PortIsDebugCapable - ? "yes" : "no"); - AppendTextBuffer("Companion Port Number: %d\r\n", - PortConnectorProps->CompanionPortNumber); - AppendTextBuffer("Companion Hub Symbolic Link Name: %ws\r\n", - PortConnectorProps->CompanionHubSymbolicLinkName); - if (ConnectionInfoV2 != NULL) - { - AppendTextBuffer("Protocols Supported:\r\n"); - AppendTextBuffer(" USB 1.1: %s\r\n", - ConnectionInfoV2->SupportedUsbProtocols.Usb110 - ? "yes" : "no"); - AppendTextBuffer(" USB 2.0: %s\r\n", - ConnectionInfoV2->SupportedUsbProtocols.Usb200 - ? "yes" : "no"); - AppendTextBuffer(" USB 3.0: %s\r\n", - ConnectionInfoV2->SupportedUsbProtocols.Usb300 - ? "yes" : "no"); - } - - AppendTextBuffer("\r\n"); -} - -/***************************************************************************** - -DisplayDevicePowerState() - -DeviceInfoNode - Structure containing info used to acquire device state - -*****************************************************************************/ - -void -DisplayDevicePowerState ( - _In_ PDEVICE_INFO_NODE DeviceInfoNode - ) -{ - - DEVICE_POWER_STATE powerState; - - powerState = AcquireDevicePowerState(DeviceInfoNode); - - AppendTextBuffer("Device Power State: "); - if (powerState >= PowerDeviceD0 && powerState <= PowerDeviceD3) - { - AppendTextBuffer("PowerDeviceD%d\r\n", powerState-1); - } - else - { - AppendTextBuffer("Invalid Device Power State Value %d\r\n", powerState); - } - - AppendTextBuffer("\r\n"); -} - - -/***************************************************************************** - -DisplayHubDescriptorBase() - -HubDescriptor - hub descriptor, could also be PUSB_30_HUB_DESCRIPTOR which has - these field in common at the beginning of the data structure: - - - UCHAR bLength; - - UCHAR bDescriptorType; - - UCHAR bNumberOfPorts; - - USHORT wHubCharacteristics; - - UCHAR bPowerOnToPowerGood; - - UCHAR bHubControlCurrent; - -*****************************************************************************/ -VOID -DisplayHubDescriptorBase( - PUSB_HUB_DESCRIPTOR HubDescriptor - ) -{ - USHORT wHubChar = 0; - - AppendTextBuffer("Number of Ports: %d\r\n", - HubDescriptor->bNumberOfPorts); - - wHubChar = HubDescriptor->wHubCharacteristics; - - switch (wHubChar & 0x0003) - { - case 0x0000: - AppendTextBuffer("Power switching: Ganged\r\n"); - break; - - case 0x0001: - AppendTextBuffer("Power switching: Individual\r\n"); - break; - - case 0x0002: - case 0x0003: - AppendTextBuffer("Power switching: None\r\n"); - break; - } - - switch (wHubChar & 0x0004) - { - case 0x0000: - AppendTextBuffer("Compound device: No\r\n"); - break; - - case 0x0004: - AppendTextBuffer("Compound device: Yes\r\n"); - break; - } - - switch (wHubChar & 0x0018) - { - case 0x0000: - AppendTextBuffer("Over-current Protection: Global\r\n"); - break; - - case 0x0008: - AppendTextBuffer("Over-current Protection: Individual\r\n"); - break; - - case 0x0010: - case 0x0018: - AppendTextBuffer("No Over-current Protection (Bus Power Only)\r\n"); - break; - } -} - - - -/***************************************************************************** - -DisplayHubInfo() - -HubInfo - Info about the hub. - -*****************************************************************************/ - -VOID -DisplayHubInfo ( - PUSB_HUB_INFORMATION HubInfo, - BOOL DisplayDescriptor - ) -{ - AppendTextBuffer("Hub Power: %s\r\n", - HubInfo->HubIsBusPowered ? - "Bus Power" : "Self Power"); - - if (DisplayDescriptor == TRUE) - { - DisplayHubDescriptorBase(&HubInfo->HubDescriptor); - } -} - -/***************************************************************************** - -DisplayHubInfoEx() - -HubInfo - Extended info about the hub. - -*****************************************************************************/ - - -VOID -DisplayHubInfoEx ( - PUSB_HUB_INFORMATION_EX HubInfoEx - ) -{ - AppendTextBuffer("Hub type: "); - - switch (HubInfoEx->HubType) { - - case UsbRootHub: - AppendTextBuffer("USB Root Hub\r\n"); - break; - - case Usb20Hub: - AppendTextBuffer("USB 2.0 Hub\r\n"); - DisplayHubDescriptorBase((PUSB_HUB_DESCRIPTOR)&HubInfoEx->u.UsbHubDescriptor); - break; - - case Usb30Hub: - AppendTextBuffer("USB 3.0 Hub\r\n"); - - // - // Note that the DisplayHubDescriptorBase will display the fields of either - // the legacy hub descriptor and the USB 3.0 descriptor which have the same - // offset - // - - DisplayHubDescriptorBase((PUSB_HUB_DESCRIPTOR)&HubInfoEx->u.UsbHubDescriptor); - AppendTextBuffer("Packet Header Decode Latency: 0x%x\r\n", HubInfoEx->u.Usb30HubDescriptor.bHubHdrDecLat); - AppendTextBuffer("Delay: 0x%x ns\r\n", HubInfoEx->u.Usb30HubDescriptor.wHubDelay); - - break; - - default: - AppendTextBuffer("ERROR: Unknown hub type %d\r\n", HubInfoEx->HubType); - break; - } - - AppendTextBuffer("\r\n"); -} - - - -/***************************************************************************** - -DisplayHubCapabilityEx() - -HubCapabilityInfo - Hub capability information - -*****************************************************************************/ - -VOID -DisplayHubCapabilityEx ( - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx - ) -{ - if(HubCapabilityEx != NULL) - { - AppendTextBuffer("High speed capable: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsHighSpeedCapable - ? "Yes" : "No"); - AppendTextBuffer("High speed: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsHighSpeed - ? "Yes" : "No"); - AppendTextBuffer("Multiple transaction translations capable: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsMultiTtCapable - ? "Yes" : "No"); - AppendTextBuffer("Performs multiple transaction translations simultaneously: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsMultiTt - ? "Yes" : "No"); - AppendTextBuffer("Hub wakes when device is connected: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsArmedWakeOnConnect - ? "Yes" : "No"); - AppendTextBuffer("Hub is bus powered: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsBusPowered - ? "Yes" : "No"); - AppendTextBuffer("Hub is root: %s\r\n", - HubCapabilityEx->CapabilityFlags.HubIsRoot - ? "Yes" : "No"); - } -} - -/***************************************************************************** - -DisplayConnectionInfo() - -ConnectInfo - Info about the connection. - -PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, -PSTRING_DESCRIPTOR_NODE StringDescs - -DisplayConnectionInfo(info->ConnectionInfo, -info->StringDescs); - -DisplayConnectionInfo ( -PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, -PSTRING_DESCRIPTOR_NODE StringDescs -) - -*****************************************************************************/ - -VOID -DisplayConnectionInfo ( - _In_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectInfo, - _In_ PUSBDEVICEINFO info, - _In_ PSTRING_DESCRIPTOR_NODE StringDescs, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 -) -{ - - //@@DisplayConnectionInfo - Device Information - PCHAR VendorString = NULL; - UINT tog = 1; - UINT uIADcount = 0; - - // No device connected - if (ConnectInfo->ConnectionStatus == NoDeviceConnected) - { - AppendTextBuffer("ConnectionStatus: NoDeviceConnected\r\n"); - return; - } - - // This is the entry point to the device display functions. - // First, save this device's PUSBDEVICEINFO address - // In a future version of this test, we will keep track of the the - // descriptor that we're parsing (# of bytes from beginning of info->configuration descriptor) - // Then we can linked descriptors by reading forward through the remaining descriptors - // while still keeping our place in this main DisplayConnectionInfo() and called - // functions. - // - // We also initialize some global flags in uvcview.h that are used to - // verify items in MJPEG, Uncompressed and Vendor Frame descriptors - // - InitializePerDeviceSettings(info); - - if(gDoAnnotation) - { - - AppendTextBuffer(" ---===>Device Information<===---\r\n"); - - if (ConnectInfo->DeviceDescriptor.iProduct) - { - DisplayUSEnglishStringDescriptor(ConnectInfo->DeviceDescriptor.iProduct, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - } - - AppendTextBuffer("\r\nConnectionStatus: %s\r\n", - ConnectionStatuses[ConnectInfo->ConnectionStatus]); - - AppendTextBuffer("Current Config Value: 0x%02X", - ConnectInfo->CurrentConfigurationValue); - } - - switch (ConnectInfo->Speed){ - case UsbLowSpeed: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Device Bus Speed: Low\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - gDeviceSpeed = UsbLowSpeed; - break; - - case UsbFullSpeed: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Device Bus Speed: Full"); - if (ConnectionInfoV2 != NULL) - { - if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedPlusCapableOrHigher) - { - AppendTextBuffer(" (is SuperSpeedPlus or higher capable)\r\n"); - } - else if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedCapableOrHigher) - { - AppendTextBuffer(" (is SuperSpeed or higher capable)\r\n"); - } - else - { - AppendTextBuffer(" (is not SuperSpeed or higher capable)\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - gDeviceSpeed = UsbFullSpeed; - break; - case UsbHighSpeed: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Device Bus Speed: High"); - if (ConnectionInfoV2 != NULL) - { - if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedPlusCapableOrHigher) - { - AppendTextBuffer(" (is SuperSpeedPlus or higher capable)\r\n"); - } - else if (ConnectionInfoV2->Flags.DeviceIsSuperSpeedCapableOrHigher) - { - AppendTextBuffer(" (is SuperSpeed or higher capable)\r\n"); - } - else - { - AppendTextBuffer(" (is not SuperSpeed or higher capable)\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - gDeviceSpeed = UsbHighSpeed; - break; - - case UsbSuperSpeed: - if(gDoAnnotation) - { - if (ConnectionInfoV2 != NULL) - { - AppendTextBuffer(" -> Device Bus Speed: Super%s\r\n", - ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher - ? "SpeedPlus" - : "Speed"); - } - else - { - AppendTextBuffer(" -> Device Bus Speed: Super Speed\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - gDeviceSpeed = UsbSuperSpeed; - break; - - default: - if(gDoAnnotation){AppendTextBuffer(" -> Device Bus Speed: Unknown\r\n");} - else {AppendTextBuffer("\r\n");} - } - - if(gDoAnnotation){ - AppendTextBuffer("Device Address: 0x%02X\r\n", - ConnectInfo->DeviceAddress); - - AppendTextBuffer("Open Pipes: %2d\r\n", - ConnectInfo->NumberOfOpenPipes); - } - - // No open pipes means the USB stack has not loaded the device - if (ConnectInfo->NumberOfOpenPipes == 0) - { - AppendTextBuffer("*!*ERROR: No open pipes!\r\n"); - } - - AppendTextBuffer("\r\n ===>Device Descriptor<===\r\n"); - //@@DisplayConnectionInfo - Device Descriptor - - if (ConnectInfo->DeviceDescriptor.bLength != 18) - { - //@@TestCase A1.1 - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@ required length in the USB Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - ConnectInfo->DeviceDescriptor.bLength, - 18); - OOPS(); - } - - AppendTextBuffer("bLength: 0x%02X\r\n", - ConnectInfo->DeviceDescriptor.bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - ConnectInfo->DeviceDescriptor.bDescriptorType); - - //@@TestCase A1.2 - //@@Not implemented - Priority 1 - //@@Descriptor Field - bcdUSB - //@@Need to check that any UVC device is set to 0x0200 or later. - AppendTextBuffer("bcdUSB: 0x%04X\r\n", - ConnectInfo->DeviceDescriptor.bcdUSB); - - AppendTextBuffer("bDeviceClass: 0x%02X", - ConnectInfo->DeviceDescriptor.bDeviceClass); - - // Quit on these device failures - if ((ConnectInfo->ConnectionStatus == DeviceFailedEnumeration) || - (ConnectInfo->ConnectionStatus == DeviceGeneralFailure)) - { - AppendTextBuffer("\r\n*!*ERROR: Device enumeration failure\r\n"); - return; - } - - // Is this an IAD device? - uIADcount = IsIADDevice((PUSBDEVICEINFO) info); - - if (uIADcount) - { - // this device configuration has 1 or more IAD descriptors - if (ConnectInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE) - { - tog = 0; - if (gDoAnnotation) - { - AppendTextBuffer(" -> This is a Multi-interface Function Code Device\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - } else { - AppendTextBuffer("\r\n*!*ERROR: device class should be Multi-interface Function 0x%02X\r\n"\ - " When IAD descriptor is used\r\n", - USB_MISCELLANEOUS_DEVICE); - } - // Is this a UVC device? - g_chUVCversion = IsUVCDevice((PUSBDEVICEINFO) info); - } - else - { - // this is not an IAD device - switch (ConnectInfo->DeviceDescriptor.bDeviceClass) - { - case USB_INTERFACE_CLASS_DEVICE: - if(gDoAnnotation) - {AppendTextBuffer(" -> This is an Interface Class Defined Device\r\n");} - else {AppendTextBuffer("\r\n");} - break; - - case USB_COMMUNICATION_DEVICE: - tog = 0; - if(gDoAnnotation) - {AppendTextBuffer(" -> This is a Communication Device\r\n");} - else {AppendTextBuffer("\r\n");} - break; - - case USB_HUB_DEVICE: - tog = 0; - if(gDoAnnotation) - {AppendTextBuffer(" -> This is a HUB Device\r\n");} - else {AppendTextBuffer("\r\n");} - break; - - case USB_DIAGNOSTIC_DEVICE: - tog = 0; - if(gDoAnnotation) - {AppendTextBuffer(" -> This is a Diagnostic Device\r\n");} - else {AppendTextBuffer("\r\n");} - break; - - case USB_WIRELESS_CONTROLLER_DEVICE: - tog = 0; - if(gDoAnnotation) - {AppendTextBuffer(" -> This is a Wireless Controller(Bluetooth) Device\r\n");} - else {AppendTextBuffer("\r\n");} - break; - - case USB_VENDOR_SPECIFIC_DEVICE: - tog = 0; - if(gDoAnnotation) - {AppendTextBuffer(" -> This is a Vendor Specific Device\r\n");} - else {AppendTextBuffer("\r\n");} - break; - - case USB_DEVICE_CLASS_BILLBOARD: - tog = 0; - if (gDoAnnotation) - { - AppendTextBuffer(" -> This is a billboard class device\r\n"); - } - else { AppendTextBuffer("\r\n"); } - break; - - case USB_MISCELLANEOUS_DEVICE: - tog = 0; - //@@TestCase A1.3 - //@@ERROR - //@@Descriptor Field - bDeviceClass - //@@Multi-interface Function code used for non-IAD device - AppendTextBuffer("\r\n*!*ERROR: Multi-interface Function code %d used for "\ - "device with no IAD descriptors\r\n", - ConnectInfo->DeviceDescriptor.bDeviceClass); - break; - - default: - //@@TestCase A1.4 - //@@ERROR - //@@Descriptor Field - bDeviceClass - //@@An unknown device class has been defined - AppendTextBuffer("\r\n*!*ERROR: unknown bDeviceClass %d\r\n", - ConnectInfo->DeviceDescriptor.bDeviceClass); - OOPS(); - break; - } - } - - AppendTextBuffer("bDeviceSubClass: 0x%02X", - ConnectInfo->DeviceDescriptor.bDeviceSubClass); - - // check the subclass - if (uIADcount) - { - // this device configuration has 1 or more IAD descriptors - if (ConnectInfo->DeviceDescriptor.bDeviceSubClass == USB_COMMON_SUB_CLASS) - { - if (gDoAnnotation) - { - AppendTextBuffer(" -> This is the Common Class Sub Class\r\n"); - } else - { - AppendTextBuffer("\r\n"); - } - } - else - { - //@@TestCase A1.5 - //@@ERROR - //@@Descriptor Field - bDeviceSubClass - //@@An invalid device sub class used for Multi-interface Function (IAD) device - AppendTextBuffer("\r\n*!*ERROR: device SubClass should be USB Common Sub Class %d\r\n"\ - " When IAD descriptor is used\r\n", - USB_COMMON_SUB_CLASS); - OOPS(); - } - } - else - { - // Not an IAD device, so all subclass values are invalid - if(ConnectInfo->DeviceDescriptor.bDeviceSubClass > 0x00 && - ConnectInfo->DeviceDescriptor.bDeviceSubClass < 0xFF) - { - //@@TestCase A1.6 - //@@ERROR - //@@Descriptor Field - bDeviceSubClass - //@@An invalid device sub class has been defined - AppendTextBuffer("\r\n*!*ERROR: bDeviceSubClass of %d is invalid\r\n", - ConnectInfo->DeviceDescriptor.bDeviceSubClass); - OOPS(); - } else - { - AppendTextBuffer("\r\n"); - } - } - - AppendTextBuffer("bDeviceProtocol: 0x%02X", - ConnectInfo->DeviceDescriptor.bDeviceProtocol); - - // check the protocol - if (uIADcount) - { - // this device configuration has 1 or more IAD descriptors - if (ConnectInfo->DeviceDescriptor.bDeviceProtocol == USB_IAD_PROTOCOL) - { - if (gDoAnnotation) - { - AppendTextBuffer(" -> This is the Interface Association Descriptor protocol\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - } - else - { - //@@TestCase A1.7 - //@@ERROR - //@@Descriptor Field - bDeviceSubClass - //@@An invalid device sub class used for Multi-interface Function (IAD) device - AppendTextBuffer("\r\n*!*ERROR: device Protocol should be USB IAD Protocol %d\r\n"\ - " When IAD descriptor is used\r\n", - USB_IAD_PROTOCOL); - OOPS(); - } - } - else - { - // Not an IAD device, so all subclass values are invalid - if(ConnectInfo->DeviceDescriptor.bDeviceProtocol > 0x00 && - ConnectInfo->DeviceDescriptor.bDeviceProtocol < 0xFF && tog==1) - { - //@@TestCase A1.8 - //@@ERROR - //@@Descriptor Field - bDeviceProtocol - //@@An invalid device protocol has been defined - AppendTextBuffer("\r\n*!*ERROR: bDeviceProtocol of %d is invalid\r\n", - ConnectInfo->DeviceDescriptor.bDeviceProtocol); - OOPS(); - } - else - { - AppendTextBuffer("\r\n"); - } - } - - AppendTextBuffer("bMaxPacketSize0: 0x%02X", - ConnectInfo->DeviceDescriptor.bMaxPacketSize0); - - if(gDoAnnotation) - { - AppendTextBuffer(" = (%d) Bytes\r\n", - ConnectInfo->DeviceDescriptor.bMaxPacketSize0); - } - else - { - AppendTextBuffer("\r\n"); - } - - switch (gDeviceSpeed){ - case UsbLowSpeed: - if(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 != 8) - { - //@@TestCase A1.9 - //@@ERROR - //@@Descriptor Field - bMaxPacketSize0 - //@@An invalid bMaxPacketSize0 has been defined for a low speed device - AppendTextBuffer("*!*ERROR: Low Speed Devices require bMaxPacketSize0 = 8\r\n"); - OOPS(); - } - break; - case UsbFullSpeed: - if(!(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 8 || - ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 16 || - ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 32 || - ConnectInfo->DeviceDescriptor.bMaxPacketSize0 == 64)) - { - //@@TestCase A1.10 - //@@ERROR - //@@Descriptor Field - bMaxPacketSize0 - //@@An invalid bMaxPacketSize0 has been defined for a full speed device - AppendTextBuffer("*!*ERROR: Full Speed Devices require bMaxPacketSize0 = 8, 16, 32, or 64\r\n"); - OOPS(); - } - break; - case UsbHighSpeed: - if(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 != 64) - { - //@@TestCase A1.11 - //@@ERROR - //@@Descriptor Field - bMaxPacketSize0 - //@@An invalid bMaxPacketSize0 has been defined for a high speed device - AppendTextBuffer("*!*ERROR: High Speed Devices require bMaxPacketSize0 = 64\r\n"); - OOPS(); - } - break; - case UsbSuperSpeed: - if(ConnectInfo->DeviceDescriptor.bMaxPacketSize0 != 9) - { - AppendTextBuffer("*!*ERROR: SuperSpeed Devices require bMaxPacketSize0 = 9 (512)\r\n"); - OOPS(); - } - break; - } - - AppendTextBuffer("idVendor: 0x%04X", - ConnectInfo->DeviceDescriptor.idVendor); - - if (gDoAnnotation) - { - VendorString = GetVendorString(ConnectInfo->DeviceDescriptor.idVendor); - if (VendorString != NULL) - { - AppendTextBuffer(" = %s\r\n", - VendorString); - } - } - else {AppendTextBuffer("\r\n");} - - AppendTextBuffer("idProduct: 0x%04X\r\n", - ConnectInfo->DeviceDescriptor.idProduct); - - AppendTextBuffer("bcdDevice: 0x%04X\r\n", - ConnectInfo->DeviceDescriptor.bcdDevice); - - AppendTextBuffer("iManufacturer: 0x%02X\r\n", - ConnectInfo->DeviceDescriptor.iManufacturer); - - if (ConnectInfo->DeviceDescriptor.iManufacturer && gDoAnnotation) - { - DisplayStringDescriptor(ConnectInfo->DeviceDescriptor.iManufacturer, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - } - - AppendTextBuffer("iProduct: 0x%02X\r\n", - ConnectInfo->DeviceDescriptor.iProduct); - - if (ConnectInfo->DeviceDescriptor.iProduct && gDoAnnotation) - { - DisplayStringDescriptor(ConnectInfo->DeviceDescriptor.iProduct, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - } - - AppendTextBuffer("iSerialNumber: 0x%02X\r\n", - ConnectInfo->DeviceDescriptor.iSerialNumber); - - if (ConnectInfo->DeviceDescriptor.iSerialNumber && gDoAnnotation) - { - DisplayStringDescriptor(ConnectInfo->DeviceDescriptor.iSerialNumber, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - } - - AppendTextBuffer("bNumConfigurations: 0x%02X\r\n", - ConnectInfo->DeviceDescriptor.bNumConfigurations); - - if(ConnectInfo->DeviceDescriptor.bNumConfigurations != 1) - { - //@@TestCase A1.12 - //@@CAUTION - //@@Descriptor Field - bNumConfigurations - //@@Most host controllers do not handle more than one configuration - AppendTextBuffer("*!*CAUTION: Most host controllers will only work with "\ - "one configuration per speed\r\n"); - OOPS(); - } - - if (ConnectInfo->NumberOfOpenPipes) - { - AppendTextBuffer("\r\n ---===>Open Pipes<===---\r\n"); - DisplayPipeInfo(ConnectInfo->NumberOfOpenPipes, - ConnectInfo->PipeList); - } - - return; -} - -/***************************************************************************** - -DisplayPipeInfo() - -NumPipes - Number of pipe for we info should be displayed. - -PipeInfo - Info about the pipes. - -*****************************************************************************/ - -VOID -DisplayPipeInfo ( - ULONG NumPipes, - USB_PIPE_INFO *PipeInfo - ) -{ - ULONG i = 0; - - for (i = 0; i < NumPipes; i++) - { - DisplayEndpointDescriptor(&PipeInfo[i].EndpointDescriptor, NULL, NULL, 0, FALSE); - } - -} - -/***************************************************************************** - -GetControllerFlavorString() - -Returns the text for given controller flavor - -*****************************************************************************/ -PCHAR GetControllerFlavorString(USB_CONTROLLER_FLAVOR flavor) -{ - return(GetStringFromList(slControllerFlavor, - sizeof(slControllerFlavor) / sizeof(STRINGLIST), - flavor, - STR_UNKNOWN_CONTROLLER_FLAVOR)); -} - - - -/***************************************************************************** - -GetPowerStateString() - -Returns the descriptive string for given power state - -*****************************************************************************/ -PCHAR GetPowerStateString(WDMUSB_POWER_STATE powerState) -{ - return(GetStringFromList(slPowerState, - sizeof(slPowerState) / sizeof(STRINGLIST), - powerState, - STR_INVALID_POWER_STATE)); -} - -/***************************************************************************** - -DisplayPowerState() - -PUSB_POWER_INFO pUPI - USBUSER.H USB_Power_Info data - -*****************************************************************************/ - -VOID -DisplayPowerState( - PUSB_POWER_INFO pUPI - ) -{ - AppendTextBuffer("%s\t%s\t%s%s\t\t%s\r\n", - GetPowerStateString(pUPI->SystemState), - GetPowerStateString(pUPI->HcDevicePowerState), - GetPowerStateString(pUPI->RhDevicePowerState), - pUPI->CanWakeup ? "Yes" : "", - pUPI->IsPowered ? "Yes" : "" - ); - return; -} - - - -/***************************************************************************** - -ValidateDescAddress() - -Given a descriptor address and the Configuration Descriptor length - (saved in DisplayConfigDesc(), and initialized for each new device) -return TRUE if the descriptor is within the Configuration length -else FALSE - -*****************************************************************************/ - -BOOL -ValidateDescAddress ( - PUSB_COMMON_DESCRIPTOR commonDesc - ) -{ - if ((PUCHAR) commonDesc + commonDesc->bLength <= g_descEnd) - { - return TRUE; - } - return FALSE; -} - -/***************************************************************************** - -DisplayConfigDesc() - -ConfigDesc - The Configuration Descriptor, and associated Interface and -Endpoint Descriptors - -*****************************************************************************/ - -VOID -DisplayConfigDesc ( - PUSBDEVICEINFO info, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ) -{ - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - UCHAR bInterfaceClass = 0; - UCHAR bInterfaceSubClass = 0; - UCHAR bInterfaceProtocol = 0; - BOOL displayUnknown = FALSE; - - BOOL isSS; - - isSS = info->ConnectionInfoV2 - && info->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher - ? TRUE - : FALSE; - - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - - // initialize global Configuration start/end address and string desc address - g_pConfigDesc = ConfigDesc; - g_pStringDescs = StringDescs; - g_descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - - AppendTextBuffer("\r\n ---===>Full Configuration Descriptor<===---\r\n"); - - do - { - displayUnknown = FALSE; - - switch (commonDesc->bDescriptorType) - { - case USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE: - //@@DisplayConfigDesc - Device Qualifier Descriptor - if (commonDesc->bLength != sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) - { - //@@TestCase A2.1 - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@ required length in the USB Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d for Device Qualifier incorrect, "\ - "should be %d\r\n", - commonDesc->bLength, - sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)); - OOPS(); - displayUnknown = TRUE; - break; - } - DisplayDeviceQualifierDescriptor((PUSB_DEVICE_QUALIFIER_DESCRIPTOR)commonDesc); - break; - - case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE: - //@@DisplayConfigDesc - Other Speed Configuration Descriptor - if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - //@@TestCase A2.2 - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@ required length in the USB Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d for Other Speed Configuration "\ - "incorrect, should be %d\r\n", - commonDesc->bLength, - sizeof(USB_CONFIGURATION_DESCRIPTOR)); - OOPS(); - displayUnknown = TRUE; - } - DisplayConfigurationDescriptor( - (PUSBDEVICEINFO) info, - (PUSB_CONFIGURATION_DESCRIPTOR)commonDesc, - StringDescs); - break; - - case USB_CONFIGURATION_DESCRIPTOR_TYPE: - //@@DisplayConfigDesc - Configuration Descriptor - if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - //@@TestCase A2.3 - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@required length in the USB Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d for Configuration incorrect, "\ - "should be %d\r\n", - commonDesc->bLength, - sizeof(USB_CONFIGURATION_DESCRIPTOR)); - OOPS(); - displayUnknown = TRUE; - break; - } - DisplayConfigurationDescriptor((PUSBDEVICEINFO)info, - (PUSB_CONFIGURATION_DESCRIPTOR)commonDesc, - StringDescs); - break; - - case USB_INTERFACE_DESCRIPTOR_TYPE: - //@@DisplayConfigDesc - Interface Descriptor - if ((commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR)) && - (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))) - { - //@@TestCase A2.4 - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@required length in the USB Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d for Interface incorrect, "\ - "should be %d or %d\r\n", - commonDesc->bLength, - sizeof(USB_INTERFACE_DESCRIPTOR), - sizeof(USB_INTERFACE_DESCRIPTOR2)); - OOPS(); - displayUnknown = TRUE; - break; - } - bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass; - bInterfaceSubClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceSubClass; - bInterfaceProtocol = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceProtocol; - - DisplayInterfaceDescriptor( - (PUSB_INTERFACE_DESCRIPTOR)commonDesc, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - - break; - - case USB_ENDPOINT_DESCRIPTOR_TYPE: - { - PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR epCompDesc = NULL; - PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR - sspIsochCompDesc = NULL; - - - //@@DisplayConfigDesc - Endpoint Descriptor - if ((commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR)) && - (commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR2))) - { - //@@TestCase A2.5 - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to - //@@ the required length in the USB Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d for Endpoint incorrect, "\ - "should be %d or %d\r\n", - commonDesc->bLength, - sizeof(USB_ENDPOINT_DESCRIPTOR), - sizeof(USB_ENDPOINT_DESCRIPTOR2)); - OOPS(); - displayUnknown = TRUE; - break; - } - - if (isSS) - { - epCompDesc = (PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR) - GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)ConfigDesc, ConfigDesc->wTotalLength, commonDesc, -1); - } - - if (epCompDesc != NULL && - epCompDesc->bmAttributes.Isochronous.SspCompanion == 1) - { - sspIsochCompDesc = (PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR) - GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)ConfigDesc, - ConfigDesc->wTotalLength, - (PUSB_COMMON_DESCRIPTOR)epCompDesc, - -1); - } - - DisplayEndpointDescriptor((PUSB_ENDPOINT_DESCRIPTOR)commonDesc, - epCompDesc, - sspIsochCompDesc, - bInterfaceClass, - TRUE); - - if (sspIsochCompDesc != NULL) - { - commonDesc = (PUSB_COMMON_DESCRIPTOR)sspIsochCompDesc; - } - else if (epCompDesc != NULL) - { - commonDesc = (PUSB_COMMON_DESCRIPTOR)epCompDesc; - } - } - - break; - - case USB_HID_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_HID_DESCRIPTOR)) - { - OOPS(); - displayUnknown = TRUE; - break; - } - DisplayHidDescriptor((PUSB_HID_DESCRIPTOR)commonDesc); - break; - - case USB_OTG_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_OTG_DESCRIPTOR)) - { - OOPS(); - displayUnknown = TRUE; - break; - } - DisplayOTGDescriptor((PUSB_OTG_DESCRIPTOR)commonDesc); - break; - - case USB_IAD_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR)) - { - OOPS(); - displayUnknown = TRUE; - break; - } - DisplayIADDescriptor((PUSB_IAD_DESCRIPTOR)commonDesc, StringDescs, - ConfigDesc->bNumInterfaces, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - break; - - default: - //@@DisplayConfigDesc - Interface Class Device - // TODO: BUG: bInterfaceClass is initialized before this code - switch (bInterfaceClass) - { - case USB_DEVICE_CLASS_AUDIO: - displayUnknown = ! DisplayAudioDescriptor( - (PUSB_AUDIO_COMMON_DESCRIPTOR)commonDesc, - bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_VIDEO: - displayUnknown = ! DisplayVideoDescriptor( - (PVIDEO_SPECIFIC)commonDesc, - bInterfaceSubClass, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - break; - - case USB_DEVICE_CLASS_RESERVED: - //@@TestCase A2.6 - //@@ERROR - //@@Descriptor Field - bInterfaceClass - //@@An unknown interface class has been defined - AppendTextBuffer("*!*ERROR: %d is a Reserved USB Device Interface Class\r\n", - USB_DEVICE_CLASS_RESERVED); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_COMMUNICATIONS: - AppendTextBuffer(" -> This is a Communications (CDC Control) USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_HUMAN_INTERFACE: - AppendTextBuffer(" -> This is a HID USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_MONITOR: - AppendTextBuffer(" -> This is a Monitor USB Device Interface Class (This may be obsolete)\r\n"); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: - AppendTextBuffer(" -> This is a Physical Interface USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_POWER: - if(bInterfaceSubClass == 1 && bInterfaceProtocol == 1) - { - AppendTextBuffer(" -> This is an Image USB Device Interface Class\r\n"); - } - else - { - AppendTextBuffer(" -> This is a Power USB Device Interface Class (This may be obsolete)\r\n"); - } - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_PRINTER: - AppendTextBuffer(" -> This is a Printer USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_STORAGE: - AppendTextBuffer(" -> This is a Mass Storage USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_DEVICE_CLASS_HUB: - AppendTextBuffer(" -> This is a HUB USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_CDC_DATA_INTERFACE: - AppendTextBuffer(" -> This is a CDC Data USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_CHIP_SMART_CARD_INTERFACE: - AppendTextBuffer(" -> This is a Chip/Smart Card USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_CONTENT_SECURITY_INTERFACE: - AppendTextBuffer(" -> This is a Content Security USB Device Interface Class\r\n"); - displayUnknown = TRUE; - break; - - case USB_DIAGNOSTIC_DEVICE_INTERFACE: - if(bInterfaceSubClass == 1 && bInterfaceProtocol == 1) - { - AppendTextBuffer(" -> This is a Reprogrammable USB2 Compliance Diagnostic Device USB Device\r\n"); - } - else - { - //@@TestCase A2.7 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@An unknown diagnostic interface class device has been defined - AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - displayUnknown = TRUE; - break; - - case USB_WIRELESS_CONTROLLER_INTERFACE: - if(bInterfaceSubClass == 1 && bInterfaceProtocol == 1) - { - AppendTextBuffer(" -> This is a Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface\r\n"); - } - else - { - //@@TestCase A2.8 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@An unknown wireless controller interface class device has been defined - AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - displayUnknown = TRUE; - break; - - case USB_APPLICATION_SPECIFIC_INTERFACE: - AppendTextBuffer(" -> This is an Application Specific USB Device Interface Class\r\n"); - - switch(bInterfaceSubClass) - { - case 1: - AppendTextBuffer(" -> This is a Device Firmware Application Specific USB Device Interface Class\r\n"); - break; - case 2: - AppendTextBuffer(" -> This is an IrDA Bridge Application Specific USB Device Interface Class\r\n"); - break; - case 3: - AppendTextBuffer(" -> This is a Test & Measurement Class (USBTMC) Application Specific USB Device Interface Class\r\n"); - break; - default: - //@@TestCase A2.9 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@A possibly invalid interface class has been defined - AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - displayUnknown = TRUE; - break; - - default: - if (bInterfaceClass == USB_DEVICE_CLASS_VENDOR_SPECIFIC) - { - AppendTextBuffer(" -> This is a Vendor Specific USB Device Interface Class\r\n"); - } - else - { - //@@TestCase A2.10 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@An unknown interface class has been defined - AppendTextBuffer("*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - displayUnknown = TRUE; - break; - } - break; - } - - if (displayUnknown) - { - DisplayUnknownDescriptor(commonDesc); - } - } while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)ConfigDesc, - ConfigDesc->wTotalLength, - commonDesc, - -1)) != NULL); - -#ifdef H264_SUPPORT - DoAdditionalErrorChecks(); -#endif -} - - -/***************************************************************************** - -DisplayDeviceQualifierDescriptor() - -*****************************************************************************/ - -VOID -DisplayDeviceQualifierDescriptor ( - PUSB_DEVICE_QUALIFIER_DESCRIPTOR DevQualDesc - ) -{ - //@@DisplayDeviceQualifierDescriptor - Device Qualifier Descriptor - - AppendTextBuffer("\r\n ===>Device Qualifier Descriptor<===\r\n"); - - //length checked in DisplayConfigDesc() - - AppendTextBuffer("bLength: 0x%02X\r\n", - DevQualDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - DevQualDesc->bDescriptorType); - - AppendTextBuffer("bcdUSB: 0x%04X\r\n", - DevQualDesc->bcdUSB); - - AppendTextBuffer("bDeviceClass: 0x%02X", - DevQualDesc->bDeviceClass); - - switch (DevQualDesc->bDeviceClass) - { - case USB_INTERFACE_CLASS_DEVICE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> This is an Interface Class Defined Device\r\n"); - } - break; - - case USB_COMMUNICATION_DEVICE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> This is a Communication Device\r\n"); - } - break; - - case USB_HUB_DEVICE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> This is a HUB Device\r\n"); - } - break; - - case USB_DIAGNOSTIC_DEVICE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> This is a Diagnostic Device\r\n"); - } - break; - - case USB_WIRELESS_CONTROLLER_DEVICE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> This is a Wireless Controller(Bluetooth) Device\r\n"); - } - break; - - case USB_VENDOR_SPECIFIC_DEVICE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> This is a Vendor Specific Device\r\n"); - } - break; - case USB_DEVICE_CLASS_BILLBOARD: - if (gDoAnnotation) - { - AppendTextBuffer(" -> This is a billboard class device\r\n"); - } - break; - default: - //@@TestCase A3.1 - //@@ERROR - //@@Descriptor Field - bDeviceClass - //@@An unknown device class has been defined - AppendTextBuffer("*!*ERROR: bDeviceClass of %d is invalid\r\n", - DevQualDesc->bDeviceClass); - OOPS(); - break; - } - - AppendTextBuffer("bDeviceSubClass: 0x%02X\r\n", - DevQualDesc->bDeviceSubClass); - - if(DevQualDesc->bDeviceSubClass > 0x00 && DevQualDesc->bDeviceSubClass < 0xFF) - { - //@@TestCase A3.2 - //@@ERROR - //@@Descriptor Field - bDeviceSubClass - //@@An unknown device sub class has been defined - AppendTextBuffer("*!*ERROR: bDeviceSubClass of %d is invalid\r\n", - DevQualDesc->bDeviceSubClass); - OOPS(); - } - - AppendTextBuffer("bDeviceProtocol: 0x%02X\r\n", - DevQualDesc->bDeviceProtocol); - - if(DevQualDesc->bDeviceProtocol > 0x00 && DevQualDesc->bDeviceProtocol < 0xFF) - { - //@@TestCase A3.4 - //@@ERROR - //@@Descriptor Field - bDeviceProtocol - //@@An invalid device protocol has been defined - AppendTextBuffer("*!*ERROR: bDeviceProtocol of %d is invalid", - DevQualDesc->bDeviceProtocol); - OOPS(); - } - - //@@TestCase A3.5 - //@@Priority 1 - //@@Descriptor Field - bcdDevice - //@@We should test to verify a valid bMaxPacketSize0 based on speed - AppendTextBuffer("bMaxPacketSize0: 0x%02X", - DevQualDesc->bMaxPacketSize0); - - if(gDoAnnotation) - { - AppendTextBuffer(" = (%d) Bytes\r\n", - DevQualDesc->bMaxPacketSize0); - } - else {AppendTextBuffer("\r\n");} - - AppendTextBuffer("bNumConfigurations: 0x%02X\r\n", - DevQualDesc->bNumConfigurations); - - if(DevQualDesc->bNumConfigurations != 1) - { - //@@TestCase A3.6 - //@@CAUTION - //@@Descriptor Field - bNumConfigurations - //@@Most host controllers do not handle more than one configuration - AppendTextBuffer("*!*CAUTION: Most host controllers will only work with one configuration per speed\r\n"); - OOPS(); - } - - AppendTextBuffer("bReserved: 0x%02X\r\n", - DevQualDesc->bReserved); - - if(DevQualDesc->bReserved != 0) - { - AppendTextBuffer("*!*WARNING: bReserved needs to be set to 0 to be valid\r\n"); - OOPS(); - } - - -} - -VOID -DisplayUsb20ExtensionCapabilityDescriptor ( - PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR extCapDesc - ) -{ - AppendTextBuffer("\r\n ===>USB 2.0 Extension Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - extCapDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - extCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - extCapDesc->bDevCapabilityType); - AppendTextBuffer("bmAttributes: 0x%08X", - extCapDesc->bmAttributes); - if (extCapDesc->bmAttributes.AsUlong & USB_DEVICE_CAPABILITY_USB20_EXTENSION_BMATTRIBUTES_RESERVED_MASK) - { - if(gDoAnnotation) - { - AppendTextBuffer("\r\n*!*ERROR: bits 31..2 and bit 0 are reserved and must be 0\r\n"); - } - } - if (extCapDesc->bmAttributes.LPMCapable == 1) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Supports Link Power Management protocol\r\n"); - } - } - if (extCapDesc->bmAttributes.AsUlong == 0) - { - AppendTextBuffer("\r\n"); - } -} - -VOID -DisplaySuperSpeedCapabilityDescriptor ( - PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR ssCapDesc - ) -{ - AppendTextBuffer("\r\n ===>SuperSpeed USB Device Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - ssCapDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - ssCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - ssCapDesc->bDevCapabilityType); - AppendTextBuffer("bmAttributes: 0x%02X\r\n", - ssCapDesc->bmAttributes); - if (ssCapDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_RESERVED_MASK) - { - if(gDoAnnotation) - { - AppendTextBuffer("\r\n*!*ERROR: bits 7:2 and bit 0 are reserved\r\n"); - } - } - if (ssCapDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_LTM_CAPABLE) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> capable of generating Latency Tolerance Messages\r\n"); - } - } - AppendTextBuffer("wSpeedsSupported: 0x%02X\r\n", - ssCapDesc->wSpeedsSupported); - - if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_LOW) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Supports low-speed operation\r\n"); - } - } - if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_FULL) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Supports full-speed operation\r\n"); - } - } - if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_HIGH) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Supports high-speed operation\r\n"); - } - } - if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_SUPER) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Supports SuperSpeed operation\r\n"); - } - } - if (ssCapDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_RESERVED_MASK) - { - if(gDoAnnotation) - { - AppendTextBuffer("\r\n*!*ERROR: bits 15:4 are reserved\r\n"); - } - } - if (!gDoAnnotation) - { - AppendTextBuffer("\r\n"); - } - AppendTextBuffer("bFunctionalitySupport: 0x%02X", - ssCapDesc->bFunctionalitySupport); - if(gDoAnnotation) - { - switch (ssCapDesc->bFunctionalitySupport) - { - case UsbLowSpeed: - AppendTextBuffer(" -> lowest speed = low-speed\r\n"); - break; - case UsbFullSpeed: - AppendTextBuffer(" -> lowest speed = full-speed\r\n"); - break; - case UsbHighSpeed: - AppendTextBuffer(" -> lowest speed = high-speed\r\n"); - break; - case UsbSuperSpeed: - AppendTextBuffer(" -> lowest speed = SuperSpeed\r\n"); - break; - default: - AppendTextBuffer("\r\n*!*ERROR: Invalid value\r\n"); - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - - AppendTextBuffer("bU1DevExitLat: 0x%02X", - ssCapDesc->bU1DevExitLat); - if(gDoAnnotation) - { - if (ssCapDesc->bU1DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U1_DEVICE_EXIT_MAX_VALUE) - { - AppendTextBuffer(" -> less than %d micro-seconds\r\n", - ssCapDesc->bU1DevExitLat); - } - else - { - AppendTextBuffer("\r\n*!*ERROR: Invalid value\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - - AppendTextBuffer("wU2DevExitLat: 0x%04X", - ssCapDesc->wU2DevExitLat); - if(gDoAnnotation) - { - if (ssCapDesc->wU2DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U2_DEVICE_EXIT_MAX_VALUE) - { - AppendTextBuffer(" -> less than %d micro-seconds\r\n", - ssCapDesc->wU2DevExitLat); - } - else - { - AppendTextBuffer("\r\n*!*ERROR: Invalid value\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } -} - - -VOID -DisplaySuperSpeedPlusCapabilityDescriptor ( - PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_USB_DESCRIPTOR sspCapDesc - ) -{ - UCHAR i; - - AppendTextBuffer("\r\n ===>SuperSpeed USB Device Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - sspCapDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - sspCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - sspCapDesc->bDevCapabilityType); - AppendTextBuffer("bReserved: 0x%02X\r\n", - sspCapDesc->bReserved); - if (sspCapDesc->bReserved != 0) - { - if(gDoAnnotation) - { - AppendTextBuffer("*!*ERROR: field is reserved\r\n"); - } - } - - AppendTextBuffer("bmAttributes: 0x%08X\r\n", - sspCapDesc->bmAttributes.AsUlong); - AppendTextBuffer(" SublinkSpeedAttrCount: 0x%02X\r\n", - sspCapDesc->bmAttributes.SublinkSpeedAttrCount); - AppendTextBuffer(" SublinkSpeedIDCount: 0x%02X\r\n", - sspCapDesc->bmAttributes.SublinkSpeedIDCount); - - AppendTextBuffer("wFunctionalitySupport: 0x%04X\r\n", - sspCapDesc->wFunctionalitySupport.AsUshort); - AppendTextBuffer(" SublinkSpeedAttrID: 0x%02X\r\n", - sspCapDesc->wFunctionalitySupport.SublinkSpeedAttrID); - AppendTextBuffer(" Reserved: 0x%02X\r\n", - sspCapDesc->wFunctionalitySupport.Reserved); - if (sspCapDesc->wFunctionalitySupport.Reserved != 0) - { - if(gDoAnnotation) - { - AppendTextBuffer("*!*ERROR: field is reserved\r\n"); - } - } - AppendTextBuffer(" MinRxLaneCount: 0x%02X\r\n", - sspCapDesc->wFunctionalitySupport.MinRxLaneCount); - AppendTextBuffer(" MinTxLaneCount: 0x%02X\r\n", - sspCapDesc->wFunctionalitySupport.MinTxLaneCount); - - AppendTextBuffer("wReserved: 0x%04X\r\n", - sspCapDesc->wReserved); - if (sspCapDesc->wReserved != 0) - { - if(gDoAnnotation) - { - AppendTextBuffer("*!*ERROR: field is reserved\r\n"); - } - } - - // The array size = SublinkSpeedAttrCount + 1 - for (i = 0; i <= sspCapDesc->bmAttributes.SublinkSpeedAttrCount; i++) - { - PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED speed = &sspCapDesc->bmSublinkSpeedAttr[i]; - - AppendTextBuffer("bmSublinkSpeedAttr #: 0x%02X\r\n", - i); - AppendTextBuffer(" SublinkSpeedAttrID: 0x%02X\r\n", - speed->SublinkSpeedAttrID); - AppendTextBuffer(" LaneSpeedExponent: 0x%02X", - speed->LaneSpeedExponent); - if(gDoAnnotation) - { - switch (speed->LaneSpeedExponent) - { - case 0: - AppendTextBuffer(" -> Bits per second\r\n"); - break; - case 1: - AppendTextBuffer(" -> Kb/s\r\n"); - break; - case 2: - AppendTextBuffer(" -> Mb/s\r\n"); - break; - case 3: - AppendTextBuffer(" -> Gb/s\r\n"); - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - AppendTextBuffer(" SublinkTypeMode: 0x%02X", - speed->SublinkTypeMode); - if(gDoAnnotation) - { - switch (speed->SublinkTypeMode) - { - case 0: - AppendTextBuffer(" -> Symmetric\r\n"); - break; - case 1: - AppendTextBuffer(" -> Asymmetric\r\n"); - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - AppendTextBuffer(" SublinkTypeDir: 0x%02X", - speed->SublinkTypeDir); - if(gDoAnnotation) - { - switch (speed->SublinkTypeDir) - { - case 0: - AppendTextBuffer(" -> Receive mode\r\n"); - break; - case 1: - AppendTextBuffer(" -> Transmit mode\r\n"); - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - AppendTextBuffer(" Reserved: 0x%02X\r\n", - speed->Reserved); - AppendTextBuffer(" LinkProtocol: 0x%02X", - speed->LinkProtocol); - if(gDoAnnotation) - { - switch (speed->LinkProtocol) - { - case 0: - AppendTextBuffer(" -> SuperSpeed\r\n"); - break; - case 1: - AppendTextBuffer(" -> SuperSpeedPlus\r\n"); - break; - default: - AppendTextBuffer(" -> Reserved\r\n"); - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - AppendTextBuffer(" LaneSpeedMantissa: 0x%04X\r\n", - speed->LaneSpeedMantissa); - } -} - - -VOID -DisplayPlatformCapabilityDescriptor ( - PUSB_DEVICE_CAPABILITY_PLATFORM_DESCRIPTOR platformCapDesc - ) -{ - LPGUID pGuid; - - AppendTextBuffer("\r\n ===>Platform Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - platformCapDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - platformCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - platformCapDesc->bDevCapabilityType); - - AppendTextBuffer("bReserved: 0x%02X\r\n", - platformCapDesc->bReserved); - if (platformCapDesc->bReserved != 0) - { - if(gDoAnnotation) - { - AppendTextBuffer("*!*ERROR: field is reserved\r\n"); - } - } - - pGuid = (LPGUID)&platformCapDesc->PlatformCapabilityUuid; - AppendTextBuffer("Platform Capability UUID: "); - AppendTextBuffer("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\r\n", - pGuid->Data1, - pGuid->Data2, - pGuid->Data3, - pGuid->Data4[0], - pGuid->Data4[1], - pGuid->Data4[2], - pGuid->Data4[3], - pGuid->Data4[4], - pGuid->Data4[5], - pGuid->Data4[6], - pGuid->Data4[7]); - - DisplayRemainingUnknownDescriptor((PUCHAR)platformCapDesc, - (ULONG)offsetof(USB_DEVICE_CAPABILITY_PLATFORM_DESCRIPTOR, CapabililityData), - platformCapDesc->bLength); -} - - -VOID -DisplayContainerIdCapabilityDescriptor ( - PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR containerIdCapDesc - ) -{ - LPGUID pGuid; - - AppendTextBuffer("\r\n ===>Container ID Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - containerIdCapDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - containerIdCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - containerIdCapDesc->bDevCapabilityType); - AppendTextBuffer("bReserved: 0x%02X\r\n", - containerIdCapDesc->bReserved); - if (containerIdCapDesc->bReserved != 0) - { - if(gDoAnnotation) - { - AppendTextBuffer("*!*ERROR: field is reserved\r\n"); - } - } - - pGuid = (LPGUID)containerIdCapDesc->ContainerID; - AppendTextBuffer("Container ID: "); - AppendTextBuffer("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\r\n", - pGuid->Data1, - pGuid->Data2, - pGuid->Data3, - pGuid->Data4[0], - pGuid->Data4[1], - pGuid->Data4[2], - pGuid->Data4[3], - pGuid->Data4[4], - pGuid->Data4[5], - pGuid->Data4[6], - pGuid->Data4[7]); -} - -VOID -DisplayBillboardCapabilityDescriptor ( - PUSBDEVICEINFO info, - PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR billboardCapDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ) -{ - UCHAR i = 0; - UCHAR bNumAlternateModes = 0; - UCHAR alternateModeConfiguration = 0; - UCHAR adjustedBLength = 0; - - AppendTextBuffer("\r\n ===>Billboard Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X", - billboardCapDesc->bLength); - - adjustedBLength = sizeof(USB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) + - sizeof(billboardCapDesc->AlternateMode[0]) * (billboardCapDesc->bNumberOfAlternateModes - 1); - AppendTextBuffer(" -> Actual Length: 0x%02X\r\n", adjustedBLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - billboardCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X -> Billboard capability\r\n", - billboardCapDesc->bDevCapabilityType); - AppendTextBuffer("iAdditionalInfoURL: 0x%02X ->", - billboardCapDesc->iAddtionalInfoURL); - if (billboardCapDesc->iAddtionalInfoURL && gDoAnnotation) { - DisplayStringDescriptor(billboardCapDesc->iAddtionalInfoURL, - StringDescs, - info->DeviceInfoNode != NULL ? info->DeviceInfoNode->LatestDevicePowerState : PowerDeviceUnspecified); - } - AppendTextBuffer("bNumberOfAlternateModes: 0x%02X\r\n", - billboardCapDesc->bNumberOfAlternateModes); - - if (billboardCapDesc->bNumberOfAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) - { - AppendTextBuffer("*!*ERROR: Invalid bNumberofAlternateModes\r\n"); - } - AppendTextBuffer("bPreferredAlternateMode: 0x%02X\r\n", - billboardCapDesc->bPreferredAlternateMode); - - AppendTextBuffer("VCONN Power: 0x%04X", - billboardCapDesc->VconnPower); - - if (billboardCapDesc->VconnPower.NoVconnPowerRequired) - { - AppendTextBuffer(" -> The adapter does not require Vconn Power. Bits 2..0 ignored\r\n"); - } - else - { - switch (billboardCapDesc->VconnPower.VConnPowerNeededForFullFunctionality) - { - case 0: - AppendTextBuffer(" -> 1W needed by adapter for full functionality\r\n"); - break; - case 1: - AppendTextBuffer(" -> 1.5W needed by adapter for full functionality\r\n"); - break; - case 7: - AppendTextBuffer(" -> *!*ERROR: VConnPowerNeededForFullFunctionality - Reserved value being used\r\n"); - break; - default: - AppendTextBuffer(" -> %2XW needed by adapter for full functionality\r\n", billboardCapDesc->VconnPower.VConnPowerNeededForFullFunctionality); - } - } - - if (billboardCapDesc->VconnPower.Reserved) - { - AppendTextBuffer("*!*ERROR: Reserved bits in VCONN Power being used\r\n"); - } - if (billboardCapDesc->bReserved) - { - AppendTextBuffer("*!*ERROR: bReserved being used\r\n"); - } - - - bNumAlternateModes = billboardCapDesc->bNumberOfAlternateModes; - if (bNumAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) - { - bNumAlternateModes = BILLBOARD_MAX_NUM_ALT_MODE; - } - if (bNumAlternateModes > 0) - { - AppendTextBuffer("\r\nAlternate Modes Identified:\r\n"); - } - for (i = 0; i < bNumAlternateModes; i++) - { - alternateModeConfiguration = ((billboardCapDesc->bmConfigured[i / 4]) >> ((i % 4) * 2)) & 0x3; - AppendTextBuffer("wSVID - 0x%04X bAlternateMode - 0x%02X ->", - billboardCapDesc->AlternateMode[i].wSVID, - billboardCapDesc->AlternateMode[i].bAlternateMode, - billboardCapDesc->AlternateMode[i].iAlternateModeSetting); - - switch (alternateModeConfiguration) - { - case 0: - AppendTextBuffer("Unspecified Error\r\n"); - break; - case 1: - AppendTextBuffer("Alternate Mode configuration not attempted\r\n"); - break; - case 2: - AppendTextBuffer("Alternate Mode configuration attempted but unsuccessful\r\n"); - break; - case 3: - AppendTextBuffer("Alternate Mode configuration successful\r\n"); - break; - } - AppendTextBuffer("iAlternateModeString - 0x%02X ", billboardCapDesc->AlternateMode[i].iAlternateModeSetting); - if (billboardCapDesc->AlternateMode[i].iAlternateModeSetting && gDoAnnotation) - { - DisplayStringDescriptor(billboardCapDesc->AlternateMode[i].iAlternateModeSetting, - StringDescs, - info->DeviceInfoNode != NULL ? info->DeviceInfoNode->LatestDevicePowerState : PowerDeviceUnspecified); - } - else - { - AppendTextBuffer("\r\n"); - } - AppendTextBuffer("\r\n"); - } -} - - -#ifdef USB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY - -VOID -DisplayConfigurationSummaryCapabilityDescriptor ( - PUSB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY_DESCRIPTOR configSummaryCapDesc - ) -{ - UCHAR i; - AppendTextBuffer("\r\n ===>Configuration Summary Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - configSummaryCapDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - configSummaryCapDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - configSummaryCapDesc->bDevCapabilityType); - - AppendTextBuffer("bcdVersion: 0x%04X\r\n", - configSummaryCapDesc->bcdVersion); - AppendTextBuffer("bConfigurationValue: 0x%02X\r\n", - configSummaryCapDesc->bConfigurationValue); - AppendTextBuffer("bMaxPower: 0x%02X\r\n", - configSummaryCapDesc->bMaxPower); - AppendTextBuffer("bNumFunctions: 0x%02X\r\n", - configSummaryCapDesc->bNumFunctions); - - for (i = 0; i < configSummaryCapDesc->bNumFunctions; i++) - { - AppendTextBuffer("Function #: 0x%02X\r\n", - i); - AppendTextBuffer(" bClass: 0x%02X\r\n", - configSummaryCapDesc->Function[i].bClass); - AppendTextBuffer(" bSubClass: 0x%02X\r\n", - configSummaryCapDesc->Function[i].bSubClass); - AppendTextBuffer(" bProtocol: 0x%02X\r\n", - configSummaryCapDesc->Function[i].bProtocol); - } -} - -#endif - -/***************************************************************************** - -DisplayBosDescriptor() - -BosDesc - The Binary Object Store (BOS) Descriptor, and associated Descriptors - -*****************************************************************************/ - -VOID -DisplayBosDescriptor ( - PUSBDEVICEINFO info, - PUSB_BOS_DESCRIPTOR BosDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ) -{ - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - PUSB_DEVICE_CAPABILITY_DESCRIPTOR capDesc = NULL; - - AppendTextBuffer("\r\n ===>BOS Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - BosDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - BosDesc->bDescriptorType); - AppendTextBuffer("wTotalLength: 0x%04X\r\n", - BosDesc->wTotalLength); - AppendTextBuffer("bNumDeviceCaps: 0x%02X\r\n", - BosDesc->bNumDeviceCaps); - - commonDesc = (PUSB_COMMON_DESCRIPTOR)BosDesc; - - while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR)BosDesc, - BosDesc->wTotalLength, - commonDesc, - -1)) != NULL) - { - switch (commonDesc->bDescriptorType) - { - case USB_DEVICE_CAPABILITY_DESCRIPTOR_TYPE: - - capDesc = (PUSB_DEVICE_CAPABILITY_DESCRIPTOR)commonDesc; - - switch (capDesc->bDevCapabilityType) - { - case USB_DEVICE_CAPABILITY_USB20_EXTENSION: - DisplayUsb20ExtensionCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR)capDesc); - break; - case USB_DEVICE_CAPABILITY_SUPERSPEED_USB: - DisplaySuperSpeedCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR)capDesc); - break; - case USB_DEVICE_CAPABILITY_CONTAINER_ID: - DisplayContainerIdCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR)capDesc); - break; - case USB_DEVICE_CAPABILITY_PLATFORM: - DisplayPlatformCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_PLATFORM_DESCRIPTOR)capDesc); - break; - case USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_USB: - DisplaySuperSpeedPlusCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_USB_DESCRIPTOR)capDesc); - break; - case USB_DEVICE_CAPABILITY_BILLBOARD: - DisplayBillboardCapabilityDescriptor((PUSBDEVICEINFO) info, (PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) capDesc, StringDescs); - break; -#ifdef USB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY - case USB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY: - DisplayConfigurationSummaryCapabilityDescriptor((PUSB_DEVICE_CAPABILITY_CONFIGURATION_SUMMARY_DESCRIPTOR)capDesc); - break; -#endif - default: - AppendTextBuffer("\r\n ===>Unknown Capability Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - capDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - capDesc->bDescriptorType); - AppendTextBuffer("bDevCapabilityType: 0x%02X\r\n", - capDesc->bDevCapabilityType); - - DisplayRemainingUnknownDescriptor((PUCHAR)commonDesc, - (ULONG)sizeof(USB_DEVICE_CAPABILITY_DESCRIPTOR), - commonDesc->bLength); - break; - } - break; - - default: - DisplayUnknownDescriptor(commonDesc); - break; - } - } -} - - -/***************************************************************************** - -DisplayConfigurationDescriptor() - -*****************************************************************************/ - -VOID -DisplayConfigurationDescriptor ( - PUSBDEVICEINFO info, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc, - PSTRING_DESCRIPTOR_NODE StringDescs - ) -{ - UINT uCount = 0; - BOOL isSS; - - - isSS = info->ConnectionInfoV2 - && (info->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher || - info->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher) - ? TRUE - : FALSE; - - AppendTextBuffer("\r\n ===>Configuration Descriptor<===\r\n"); - //@@DisplayConfigurationDescriptor - Configuration Descriptor - - //length checked in DisplayConfigDesc() - - AppendTextBuffer("bLength: 0x%02X\r\n", - ConfigDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - ConfigDesc->bDescriptorType); - - //@@TestCase A4.1 - //@@Priority 1 - //@@Descriptor Field - wTotalLength - //@@Verify Configuration length is valid - AppendTextBuffer("wTotalLength: 0x%04X", - ConfigDesc->wTotalLength); - uCount = GetConfigurationSize(info); - if (uCount != ConfigDesc->wTotalLength) { - AppendTextBuffer("\r\n*!*ERROR: Invalid total configuration size 0x%02X, should be 0x%02X\r\n", - ConfigDesc->wTotalLength, uCount); - } else { - AppendTextBuffer(" -> Validated\r\n"); - } - - //@@TestCase A4.2 - //@@Priority 1 - //@@Descriptor Field - bNumInterfaces - //@@Verify the number of interfaces is valid - AppendTextBuffer("bNumInterfaces: 0x%02X\r\n", - ConfigDesc->bNumInterfaces); - -/* Need to check spec vs composite devices - uCount = GetInterfaceCount(info); - if (uCount != ConfigDesc->bNumInterfaces) { - AppendTextBuffer("\r\n*!*ERROR: Invalid total Interfaces %d, should be %d\r\n", - ConfigDesc->bNumInterfaces, uCount); - } else { - AppendTextBuffer(" -> Validated\r\n"); - } -*/ - - AppendTextBuffer("bConfigurationValue: 0x%02X\r\n", - ConfigDesc->bConfigurationValue); - - if(ConfigDesc->bConfigurationValue != 1) - { - //@@TestCase A4.3 - //@@CAUTION - //@@Descriptor Field - bConfigurationValue - //@@Most host controllers do not handle more than one configuration - AppendTextBuffer("*!*CAUTION: Most host controllers will only work with one configuration per speed\r\n"); - OOPS(); - } - - AppendTextBuffer("iConfiguration: 0x%02X\r\n", - ConfigDesc->iConfiguration); - - if (ConfigDesc->iConfiguration && gDoAnnotation) - { - DisplayStringDescriptor(ConfigDesc->iConfiguration, - StringDescs, - info->DeviceInfoNode != NULL? info->DeviceInfoNode->LatestDevicePowerState: PowerDeviceUnspecified); - } - - AppendTextBuffer("bmAttributes: 0x%02X", - ConfigDesc->bmAttributes); - - if (info->ConnectionInfo->DeviceDescriptor.bcdUSB == 0x0100) - { - if (ConfigDesc->bmAttributes & USB_CONFIG_SELF_POWERED) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Self Powered\r\n"); - } - } - if (ConfigDesc->bmAttributes & USB_CONFIG_BUS_POWERED) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Bus Powered\r\n"); - } - } - } - else - { - if (ConfigDesc->bmAttributes & USB_CONFIG_SELF_POWERED) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Self Powered\r\n"); - } - } - else - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Bus Powered\r\n"); - } - } - if ((ConfigDesc->bmAttributes & USB_CONFIG_BUS_POWERED) == 0) - { - AppendTextBuffer("\r\n*!*ERROR: Bit 7 is reserved and must be set\r\n"); - OOPS(); - } - } - - if (ConfigDesc->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Remote Wakeup\r\n"); - } - } - - if (ConfigDesc->bmAttributes & USB_CONFIG_RESERVED) - { - //@@TestCase A4.4 - //@@WARNING - //@@Descriptor Field - bmAttributes - //@@A bit has been set in reserved space - AppendTextBuffer("\r\n*!*ERROR: Bits 4...0 are reserved\r\n"); - OOPS(); - } - - AppendTextBuffer("MaxPower: 0x%02X", - ConfigDesc->MaxPower); - - if(gDoAnnotation) - { - AppendTextBuffer(" = %3d mA\r\n", - isSS ? ConfigDesc->MaxPower * 8 : ConfigDesc->MaxPower * 2); - } - else {AppendTextBuffer("\r\n");} - -} - -/***************************************************************************** - -DisplayInterfaceDescriptor() - -*****************************************************************************/ - -VOID -DisplayInterfaceDescriptor ( - PUSB_INTERFACE_DESCRIPTOR InterfaceDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayInterfaceDescriptor - Interface Descriptor - AppendTextBuffer("\r\n ===>Interface Descriptor<===\r\n"); - - //length checked in DisplayConfigDesc() - AppendTextBuffer("bLength: 0x%02X\r\n", - InterfaceDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - InterfaceDesc->bDescriptorType); - - //@@TestCase A5.1 - //@@Priority 1 - //@@Descriptor Field - bInterfaceNumber - //@@Question - Should we test to verify bInterfaceNumber is valid? - AppendTextBuffer("bInterfaceNumber: 0x%02X\r\n", - InterfaceDesc->bInterfaceNumber); - - //@@TestCase A5.2 - //@@Priority 1 - //@@Descriptor Field - bAlternateSetting - //@@Question - Should we test to verify bAlternateSetting is valid? - AppendTextBuffer("bAlternateSetting: 0x%02X\r\n", - InterfaceDesc->bAlternateSetting); - - //@@TestCase A5.3 - //@@Priority 1 - //@@Descriptor Field - bNumEndpoints - //@@Question - Should we test to verify bNumEndpoints is valid? - AppendTextBuffer("bNumEndpoints: 0x%02X\r\n", - InterfaceDesc->bNumEndpoints); - - AppendTextBuffer("bInterfaceClass: 0x%02X", - InterfaceDesc->bInterfaceClass); - - switch (InterfaceDesc->bInterfaceClass) - { - case USB_DEVICE_CLASS_AUDIO: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Audio Interface Class\r\n"); - } - - AppendTextBuffer("bInterfaceSubClass: 0x%02X", - InterfaceDesc->bInterfaceSubClass); - - if(gDoAnnotation) - { - switch (InterfaceDesc->bInterfaceSubClass) - { - case USB_AUDIO_SUBCLASS_AUDIOCONTROL: - AppendTextBuffer(" -> Audio Control Interface SubClass\r\n"); - break; - - case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: - AppendTextBuffer(" -> Audio Streaming Interface SubClass\r\n"); - break; - - case USB_AUDIO_SUBCLASS_MIDISTREAMING: - AppendTextBuffer(" -> MIDI Streaming Interface SubClass\r\n"); - break; - - default: - //@@TestCase A5.4 - //@@CAUTION - //@@Descriptor Field - bInterfaceSubClass - //@@Invalid bInterfaceSubClass - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bInterfaceSubClass\r\n"); - OOPS(); - break; - } - } - break; - - case USB_DEVICE_CLASS_VIDEO: - if(gDoAnnotation) - AppendTextBuffer(" -> Video Interface Class\r\n"); - - AppendTextBuffer("bInterfaceSubClass: 0x%02X", - InterfaceDesc->bInterfaceSubClass); - - switch(InterfaceDesc->bInterfaceSubClass) - { - case VIDEO_SUBCLASS_CONTROL: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Video Control Interface SubClass\r\n"); - } - break; - - case VIDEO_SUBCLASS_STREAMING: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Video Streaming Interface SubClass\r\n"); - } - break; - - default: - //@@TestCase A5.5 - //@@CAUTION - //@@Descriptor Field - bInterfaceSubClass - //@@Invalid bInterfaceSubClass - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bInterfaceSubClass\r\n"); - OOPS(); - break; - } - break; - - case USB_DEVICE_CLASS_HUMAN_INTERFACE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> HID Interface Class\r\n"); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_HUB: - if(gDoAnnotation) - { - AppendTextBuffer(" -> HUB Interface Class\r\n"); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_RESERVED: - //@@TestCase A5.6 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@A reserved USB Device Interface Class has been defined - AppendTextBuffer("\r\n*!*CAUTION: %d is a Reserved USB Device Interface Class\r\n", - USB_DEVICE_CLASS_RESERVED); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_COMMUNICATIONS: - AppendTextBuffer(" -> This is Communications (CDC Control) USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_MONITOR: - AppendTextBuffer(" -> This is a Monitor USB Device Interface Class*** (This may be obsolete)\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: - AppendTextBuffer(" -> This is a Physical Interface USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_POWER: - if(InterfaceDesc->bInterfaceSubClass == 1 && InterfaceDesc->bInterfaceProtocol == 1) - { - AppendTextBuffer(" -> This is an Image USB Device Interface Class\r\n"); - } - else - { - AppendTextBuffer(" -> This is a Power USB Device Interface Class (This may be obsolete)\r\n"); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_PRINTER: - AppendTextBuffer(" -> This is a Printer USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DEVICE_CLASS_STORAGE: - AppendTextBuffer(" -> This is a Mass Storage USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_CDC_DATA_INTERFACE: - AppendTextBuffer(" -> This is a CDC Data USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_CHIP_SMART_CARD_INTERFACE: - AppendTextBuffer(" -> This is a Chip/Smart Card USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_CONTENT_SECURITY_INTERFACE: - AppendTextBuffer(" -> This is a Content Security USB Device Interface Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_DIAGNOSTIC_DEVICE_INTERFACE: - if(InterfaceDesc->bInterfaceSubClass == 1 && InterfaceDesc->bInterfaceProtocol == 1) - { - AppendTextBuffer(" -> This is a Reprogrammable USB2 Compliance Diagnostic Device USB Device\r\n"); - } - else - { - //@@TestCase A5.7 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@Invalid Interface Class - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_WIRELESS_CONTROLLER_INTERFACE: - if(InterfaceDesc->bInterfaceSubClass == 1 && InterfaceDesc->bInterfaceProtocol == 1) - { - AppendTextBuffer(" -> This is a Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface\r\n"); - } - else - { - //@@TestCase A5.8 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@Invalid Interface Class - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - - case USB_APPLICATION_SPECIFIC_INTERFACE: - AppendTextBuffer(" -> This is an Application Specific USB Device Interface Class\r\n"); - - switch(InterfaceDesc->bInterfaceSubClass) - { - case 1: - AppendTextBuffer(" -> This is a Device Firmware Application Specific USB Device Interface Class\r\n"); - break; - case 2: - AppendTextBuffer(" -> This is an IrDA Bridge Application Specific USB Device Interface Class\r\n"); - break; - case 3: - AppendTextBuffer(" -> This is a Test & Measurement Class (USBTMC) Application Specific USB Device Interface Class\r\n"); - break; - default: - //@@TestCase A5.9 - //@@CAUTION - //@@Descriptor Field - bInterfaceClass - //@@Invalid Interface Class - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - case USB_DEVICE_CLASS_BILLBOARD: - AppendTextBuffer(" -> Billboard Class\r\n"); - AppendTextBuffer("bInterfaceSubClass: 0x%02X", InterfaceDesc->bInterfaceSubClass); - switch (InterfaceDesc->bInterfaceSubClass) - { - case 0: - AppendTextBuffer(" -> Billboard Subclass\r\n"); - break; - default: - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bInterfaceSubClass\r\n"); - break; - } - break; - - default: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Interface Class Unknown to USBView\r\n"); - } - AppendTextBuffer("bInterfaceSubClass: 0x%02X\r\n", - InterfaceDesc->bInterfaceSubClass); - break; - } - - AppendTextBuffer("bInterfaceProtocol: 0x%02X\r\n", - InterfaceDesc->bInterfaceProtocol); - - //This is basically the check for PC_PROTOCOL_UNDEFINED - if ((InterfaceDesc->bInterfaceClass == USB_DEVICE_CLASS_VIDEO) || - (InterfaceDesc->bInterfaceClass == USB_DEVICE_CLASS_AUDIO)) - { - if(InterfaceDesc->bInterfaceProtocol != PC_PROTOCOL_UNDEFINED) - { - //@@TestCase A5.10 - //@@WARNING - //@@Descriptor Field - iInterface - //@@bInterfaceProtocol must be set to PC_PROTOCOL_UNDEFINED - AppendTextBuffer("*!*WARNING: must be set to PC_PROTOCOL_UNDEFINED %d for this class\r\n", - PC_PROTOCOL_UNDEFINED); - OOPS(); - } - } - - AppendTextBuffer("iInterface: 0x%02X\r\n", - InterfaceDesc->iInterface); - - if(gDoAnnotation) - { - if (InterfaceDesc->iInterface) - { - DisplayStringDescriptor(InterfaceDesc->iInterface, - StringDescs, - LatestDevicePowerState); - } - } - - if (InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR2)) - { - PUSB_INTERFACE_DESCRIPTOR2 interfaceDesc2; - - interfaceDesc2 = (PUSB_INTERFACE_DESCRIPTOR2)InterfaceDesc; - - AppendTextBuffer("wNumClasses: 0x%04X\r\n", - interfaceDesc2->wNumClasses); - } - -} - -/***************************************************************************** - -DisplayEndpointDescriptor() - -*****************************************************************************/ - -VOID -DisplayEndpointDescriptor ( - _In_ PUSB_ENDPOINT_DESCRIPTOR - EndpointDesc, - _In_opt_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR - EpCompDesc, - _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR - SspIsochEpCompDesc, - _In_ UCHAR InterfaceClass, - _In_ BOOLEAN EpCompDescAvail - ) -{ - UCHAR epType = EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK; - PUSB_HIGH_SPEED_MAXPACKET hsMaxPacket; - - AppendTextBuffer("\r\n ===>Endpoint Descriptor<===\r\n"); - //@@DisplayEndpointDescriptor - Endpoint Descriptor - //length checked in DisplayConfigDesc() - - AppendTextBuffer("bLength: 0x%02X\r\n", - EndpointDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - EndpointDesc->bDescriptorType); - - AppendTextBuffer("bEndpointAddress: 0x%02X", - EndpointDesc->bEndpointAddress); - - if(gDoAnnotation) - { - if(USB_ENDPOINT_DIRECTION_OUT(EndpointDesc->bEndpointAddress)) - { - AppendTextBuffer(" -> Direction: OUT - EndpointID: %d\r\n", - (EndpointDesc->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)); - } - else if(USB_ENDPOINT_DIRECTION_IN(EndpointDesc->bEndpointAddress)) - { - AppendTextBuffer(" -> Direction: IN - EndpointID: %d\r\n", - (EndpointDesc->bEndpointAddress & USB_ENDPOINT_ADDRESS_MASK)); - } - else - { - //@@TestCase A6.1 - //@@ERROR - //@@Descriptor Field - bEndpointAddress - //@@An invalid endpoint addressl has been defined - AppendTextBuffer("\r\n*!*ERROR: This appears to be an invalid bEndpointAddress\r\n"); - OOPS(); - } - } - else {AppendTextBuffer("\r\n");} - - AppendTextBuffer("bmAttributes: 0x%02X", - EndpointDesc->bmAttributes); - - if(gDoAnnotation) - { - AppendTextBuffer(" -> "); - - switch (epType) - { - case USB_ENDPOINT_TYPE_CONTROL: - AppendTextBuffer("Control Transfer Type\r\n"); - if (EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_CONTROL_RESERVED_MASK) - { - AppendTextBuffer("\r\n*!*ERROR: Bits 7..2 are reserved and must be set to 0\r\n"); - OOPS(); - } - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - AppendTextBuffer("Isochronous Transfer Type, Synchronization Type = "); - - switch (USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION(EndpointDesc->bmAttributes)) - { - case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_NO_SYNCHRONIZATION: - AppendTextBuffer("No Synchronization"); - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_ASYNCHRONOUS: - AppendTextBuffer("Asynchronous"); - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_ADAPTIVE: - AppendTextBuffer("Adaptive"); - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS_SYNCHRONIZATION_SYNCHRONOUS: - AppendTextBuffer("Synchronous"); - break; - } - AppendTextBuffer(", Usage Type = "); - - switch (USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE(EndpointDesc->bmAttributes)) - { - case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_DATA_ENDOINT: - AppendTextBuffer("Data Endpoint\r\n"); - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_FEEDBACK_ENDPOINT: - AppendTextBuffer("Feedback Endpoint\r\n"); - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_IMPLICIT_FEEDBACK_DATA_ENDPOINT: - AppendTextBuffer("Implicit Feedback Data Endpoint\r\n"); - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS_USAGE_RESERVED: - //@@TestCase A6.2 - //@@ERROR - //@@Descriptor Field - bmAttributes - //@@A reserved bit has a value - AppendTextBuffer("\r\n*!*ERROR: This value is Reserved\r\n"); - OOPS(); - break; - } - if (EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_ISOCHRONOUS_RESERVED_MASK) - { - AppendTextBuffer("\r\n*!*ERROR: Bits 7..6 are reserved and must be set to 0\r\n"); - OOPS(); - } - break; - - case USB_ENDPOINT_TYPE_BULK: - AppendTextBuffer("Bulk Transfer Type\r\n"); - if (EndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_BULK_RESERVED_MASK) - { - AppendTextBuffer("\r\n*!*ERROR: Bits 7..2 are reserved and must be set to 0\r\n"); - OOPS(); - } - break; - - case USB_ENDPOINT_TYPE_INTERRUPT: - - if (gDeviceSpeed != UsbSuperSpeed) - { - AppendTextBuffer("Interrupt Transfer Type\r\n"); - if (EndpointDesc->bmAttributes & USB_20_ENDPOINT_TYPE_INTERRUPT_RESERVED_MASK) - { - AppendTextBuffer("\r\n*!*ERROR: Bits 7..2 are reserved and must be set to 0\r\n"); - OOPS(); - } - } - else - { - AppendTextBuffer("Interrupt Transfer Type, Usage Type = "); - - switch (USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE(EndpointDesc->bmAttributes)) - { - case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_PERIODIC: - AppendTextBuffer("Periodic\r\n"); - break; - - case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_NOTIFICATION: - AppendTextBuffer("Notification\r\n"); - break; - - case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_RESERVED10: - case USB_30_ENDPOINT_TYPE_INTERRUPT_USAGE_RESERVED11: - AppendTextBuffer("\r\n*!*ERROR: This value is Reserved\r\n"); - OOPS(); - break; - } - - if (EndpointDesc->bmAttributes & USB_30_ENDPOINT_TYPE_INTERRUPT_RESERVED_MASK) - { - AppendTextBuffer("\r\n*!*ERROR: Bits 7..6 and 3..2 are reserved and must be set to 0\r\n"); - OOPS(); - } - - if (EpCompDescAvail) - { - if (EpCompDesc == NULL) - { - AppendTextBuffer("\r\n*!*ERROR: Endpoint Companion Descriptor missing\r\n"); - OOPS(); - } - else if (EpCompDesc->bmAttributes.Isochronous.SspCompanion == 1 && - SspIsochEpCompDesc == NULL) - { - AppendTextBuffer("\r\n*!*ERROR: SuperSpeedPlus Isoch Endpoint Companion Descriptor missing\r\n"); - OOPS(); - } - } - } - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - - //@@TestCase A6.3 - //@@Priority 1 - //@@Descriptor Field - bInterfaceNumber - //@@Question - Should we test to verify bInterfaceNumber is valid? - AppendTextBuffer("wMaxPacketSize: 0x%04X", - EndpointDesc->wMaxPacketSize); - if(gDoAnnotation) - { - switch (gDeviceSpeed) - { - case UsbSuperSpeed: - switch (epType) - { - case USB_ENDPOINT_TYPE_BULK: - if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_BULK_MAX_PACKET_SIZE) - { - AppendTextBuffer("\r\n*!*ERROR: SuperSpeed Bulk endpoints must be %d bytes\r\n", - USB_ENDPOINT_SUPERSPEED_BULK_MAX_PACKET_SIZE); - } - else - { - AppendTextBuffer("\r\n"); - } - break; - - case USB_ENDPOINT_TYPE_CONTROL: - if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_CONTROL_MAX_PACKET_SIZE) - { - AppendTextBuffer("\r\n*!*ERROR: SuperSpeed Control endpoints must be %d bytes\r\n", - USB_ENDPOINT_SUPERSPEED_CONTROL_MAX_PACKET_SIZE); - } - else - { - AppendTextBuffer("\r\n"); - } - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - - if (EpCompDesc != NULL) - { - if (EpCompDesc->bMaxBurst > 0) - { - if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE) - { - AppendTextBuffer("\r\n*!*ERROR: SuperSpeed isochronous endpoints must have wMaxPacketSize value of %d bytes\r\n", - USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE); - AppendTextBuffer(" when the SuperSpeed endpoint companion descriptor bMaxBurst value is greater than 0\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - } - else if (EndpointDesc->wMaxPacketSize > USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE) - { - AppendTextBuffer("\r\n*!*ERROR: Invalid SuperSpeed isochronous maximum packet size\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - break; - - case USB_ENDPOINT_TYPE_INTERRUPT: - - if (EpCompDesc != NULL) - { - if (EpCompDesc->bMaxBurst > 0) - { - if (EndpointDesc->wMaxPacketSize != USB_ENDPOINT_SUPERSPEED_INTERRUPT_MAX_PACKET_SIZE) - { - AppendTextBuffer("\r\n*!*ERROR: SuperSpeed interrupt endpoints must have wMaxPacketSize value of %d bytes\r\n", - USB_ENDPOINT_SUPERSPEED_INTERRUPT_MAX_PACKET_SIZE); - AppendTextBuffer(" when the SuperSpeed endpoint companion descriptor bMaxBurst value is greater than 0\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - } - else if (EndpointDesc->wMaxPacketSize > USB_ENDPOINT_SUPERSPEED_INTERRUPT_MAX_PACKET_SIZE) - { - AppendTextBuffer("\r\n*!*ERROR: Invalid SuperSpeed interrupt maximum packet size\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - } - else - { - AppendTextBuffer("\r\n"); - } - break; - } - break; - - case UsbHighSpeed: - hsMaxPacket = (PUSB_HIGH_SPEED_MAXPACKET)&EndpointDesc->wMaxPacketSize; - - switch (epType) - { - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - case USB_ENDPOINT_TYPE_INTERRUPT: - switch (hsMaxPacket->HSmux) { - case 0: - if ((hsMaxPacket->MaxPacket < 1) || (hsMaxPacket->MaxPacket >1024)) - { - AppendTextBuffer("*!*ERROR: Invalid maximum packet size, should be between 1 and 1024\r\n"); - } - break; - - case 1: - if ((hsMaxPacket->MaxPacket < 513) || (hsMaxPacket->MaxPacket >1024)) - { - AppendTextBuffer("*!*ERROR: Invalid maximum packet size, should be between 513 and 1024\r\n"); - } - break; - - case 2: - if ((hsMaxPacket->MaxPacket < 683) || (hsMaxPacket->MaxPacket >1024)) - { - AppendTextBuffer("*!*ERROR: Invalid maximum packet size, should be between 683 and 1024\r\n"); - } - break; - - case 3: - AppendTextBuffer("*!*ERROR: Bits 12-11 set to Reserved value in wMaxPacketSize\r\n"); - break; - } - - AppendTextBuffer(" = %d transactions per microframe, 0x%02X max bytes\r\n", hsMaxPacket->HSmux + 1, hsMaxPacket->MaxPacket); - break; - - case USB_ENDPOINT_TYPE_BULK: - case USB_ENDPOINT_TYPE_CONTROL: - AppendTextBuffer(" = 0x%02X max bytes\r\n", hsMaxPacket->MaxPacket); - break; - } - break; - - case UsbFullSpeed: - // full speed - AppendTextBuffer(" = 0x%02X bytes\r\n", - EndpointDesc->wMaxPacketSize & 0x7FF); - break; - default: - // low or invalid speed - if (InterfaceClass == USB_DEVICE_CLASS_VIDEO) - { - AppendTextBuffer(" = Invalid bus speed for USB Video Class\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - break; - } - } - else - { - AppendTextBuffer("\r\n"); - } - - if (EndpointDesc->wMaxPacketSize & 0xE000) - { - //@@TestCase A6.4 - //@@Priority 1 - //@@OTG Descriptor Field - wMaxPacketSize - //@@Attribute bits D7-2 reserved (reset to 0) - AppendTextBuffer("*!*ERROR: wMaxPacketSize bits 15-13 should be 0\r\n"); - } - - if (EndpointDesc->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) - { - //@@TestCase A6.5 - //@@Priority 1 - //@@Descriptor Field - bInterfaceNumber - //@@Question - Should we test to verify bInterfaceNumber is valid? - AppendTextBuffer("bInterval: 0x%02X\r\n", - EndpointDesc->bInterval); - } - else - { - PUSB_ENDPOINT_DESCRIPTOR2 endpointDesc2; - - endpointDesc2 = (PUSB_ENDPOINT_DESCRIPTOR2)EndpointDesc; - - AppendTextBuffer("wInterval: 0x%04X\r\n", - endpointDesc2->wInterval); - - AppendTextBuffer("bSyncAddress: 0x%02X\r\n", - endpointDesc2->bSyncAddress); - } - - if (EpCompDesc != NULL) - { - DisplayEndointCompanionDescriptor(EpCompDesc, SspIsochEpCompDesc, epType); - } - if (SspIsochEpCompDesc != NULL) - { - DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor(SspIsochEpCompDesc); - } - -} - -/***************************************************************************** - -DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor() - -*****************************************************************************/ -VOID -DisplaySuperSpeedPlusIsochEndpointCompanionDescriptor( - _In_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR SspIsochEpCompDesc - ) - { - AppendTextBuffer("\r\n ===>SuperSpeedPlus Isochronous Endpoint Companion Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - SspIsochEpCompDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - SspIsochEpCompDesc->bDescriptorType); - - AppendTextBuffer("wReserved: 0x%02X\r\n", - SspIsochEpCompDesc->wReserved); - - if (gDoAnnotation) - { - if (SspIsochEpCompDesc->wReserved != 0) - { - AppendTextBuffer("*!*ERROR: field is reserved\r\n"); - } - } - - AppendTextBuffer("dwBytesPerInterval: 0x%04X\r\n", - SspIsochEpCompDesc->dwBytesPerInterval); -} - -/***************************************************************************** - -DisplayEndointCompanionDescriptor() - -*****************************************************************************/ -VOID -DisplayEndointCompanionDescriptor ( - _In_ PUSB_SUPERSPEED_ENDPOINT_COMPANION_DESCRIPTOR EpCompDesc, - _In_opt_ PUSB_SUPERSPEEDPLUS_ISOCH_ENDPOINT_COMPANION_DESCRIPTOR SspIsochEpCompDesc, - _In_ UCHAR DescType - ) -{ - AppendTextBuffer("\r\n ===>SuperSpeed Endpoint Companion Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - EpCompDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - EpCompDesc->bDescriptorType); - - AppendTextBuffer("bMaxBurst: 0x%02X\r\n", - EpCompDesc->bMaxBurst); - - AppendTextBuffer("bmAttributes: 0x%02X", - EpCompDesc->bmAttributes.AsUchar); - if(gDoAnnotation) - { - switch (DescType) - { - case USB_ENDPOINT_TYPE_CONTROL: - case USB_ENDPOINT_TYPE_INTERRUPT: - if (EpCompDesc->bmAttributes.AsUchar != 0) - { - AppendTextBuffer("*!*ERROR: Control/Interrupt SuperSpeed endpoints do not support streams\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - break; - case USB_ENDPOINT_TYPE_BULK: - if(EpCompDesc->bmAttributes.Bulk.MaxStreams == 0) - { - AppendTextBuffer("The bulk endpoint does not define streams (MaxStreams == 0)\r\n"); - } - else - { - AppendTextBuffer(" = %d streams supported\r\n", 1 << EpCompDesc->bmAttributes.Bulk.MaxStreams); - } - - if (EpCompDesc->bmAttributes.Bulk.Reserved1 != 0) - { - AppendTextBuffer("*!*ERROR: bmAttributes bits 7-5 should be 0\r\n"); - } - break; - - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - if (EpCompDesc->bmAttributes.Isochronous.SspCompanion == 0) - { - if (EpCompDesc->bMaxBurst == 0 && - EpCompDesc->bmAttributes.Isochronous.Mult != 0) - { - AppendTextBuffer("*!*ERROR: SuperSpeed isochronous endpoint multiplier value should be zero if bMaxBurst is zero\r\n"); - } - else - { - AppendTextBuffer(" = %d maximum number of packets within a service interval\r\n", - (EpCompDesc->bmAttributes.Isochronous.Mult + 1)*(EpCompDesc->bMaxBurst + 1)); - - if (EpCompDesc->bmAttributes.Isochronous.Mult > USB_SUPERSPEED_ISOCHRONOUS_MAX_MULTIPLIER) - { - AppendTextBuffer("*!*ERROR: Maximum SuperSpeed isochronous endpoint multiplier value exceeded\r\n"); - } - } - } - else - { - if (EpCompDesc->bMaxBurst != 0 && SspIsochEpCompDesc != NULL) - { - AppendTextBuffer(" = %d maximum number of packets within a service interval\r\n", - (SspIsochEpCompDesc->dwBytesPerInterval*USB_ENDPOINT_SUPERSPEED_ISO_MAX_PACKET_SIZE) / - EpCompDesc->bMaxBurst); - } - } - - if (EpCompDesc->bmAttributes.Isochronous.Reserved2 != 0) - { - AppendTextBuffer("*!*ERROR: bmAttributes bits 7-2 should be 0\r\n"); - } - else - { - AppendTextBuffer("\r\n"); - } - break; - } - } - AppendTextBuffer("wBytesPerInterval: 0x%04X\r\n", - EpCompDesc->wBytesPerInterval); - - if (EpCompDesc->bmAttributes.Isochronous.SspCompanion == 1 && - EpCompDesc->wBytesPerInterval != 0x1) - { - AppendTextBuffer("*!*ERROR: SuperSpeed endpoint wBytesPerInterval value should be 1 if \ - SuperSpeedPlus Isoch companion descriptor is present\r\n"); - } -} - - -/***************************************************************************** - -DisplayHidDescriptor() - -*****************************************************************************/ - -VOID -DisplayHidDescriptor ( - PUSB_HID_DESCRIPTOR HidDesc - ) -{ - UCHAR i = 0; - - AppendTextBuffer("\r\n ===>HID Descriptor<===\r\n"); - - //length checked in DisplayConfigDesc() - - AppendTextBuffer("bLength: 0x%02X\r\n", - HidDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - HidDesc->bDescriptorType); - AppendTextBuffer("bcdHID: 0x%04X\r\n", - HidDesc->bcdHID); - AppendTextBuffer("bCountryCode: 0x%02X\r\n", - HidDesc->bCountryCode); - AppendTextBuffer("bNumDescriptors: 0x%02X\r\n", - HidDesc->bNumDescriptors); - - for (i=0; ibNumDescriptors; i++) - { - if (HidDesc->OptionalDescriptors[i].bDescriptorType == 0x22) { - AppendTextBuffer("bDescriptorType: 0x%02X (Report Descriptor)\r\n", - HidDesc->OptionalDescriptors[i].bDescriptorType); - } - else { - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - HidDesc->OptionalDescriptors[i].bDescriptorType); - } - - AppendTextBuffer("wDescriptorLength: 0x%04X\r\n", - HidDesc->OptionalDescriptors[i].wDescriptorLength); - } -} - -/***************************************************************************** - -DisplayOTGDescriptor() - -*****************************************************************************/ - -VOID -DisplayOTGDescriptor ( - PUSB_OTG_DESCRIPTOR OTGDesc - ) -{ - AppendTextBuffer("\r\n ===>OTG Descriptor<===\r\n"); - - //length checked in DisplayConfigDesc() - - AppendTextBuffer("bLength: 0x%02X\r\n", - OTGDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - OTGDesc->bDescriptorType); - AppendTextBuffer("bmAttributes: 0x%02X", - OTGDesc->bmAttributes); - - switch (OTGDesc->bmAttributes) - { - case 0: - break; - case 1: - if(gDoAnnotation) - { - AppendTextBuffer(" -> SRP support\r\n"); - } - break; - case 2: - if(gDoAnnotation) - { - AppendTextBuffer(" -> HNP support\r\n"); - } - break; - case 3: - if(gDoAnnotation) - { - AppendTextBuffer(" -> SRP and HNP support\r\n"); - } - break; - default: - //@@TestCase A6.5 - //@@Priority 1 - //@@OTG Descriptor Field - bmAttributes - //@@Attribute bits D7-2 reserved (reset to 0) - AppendTextBuffer("*!*ERROR: bmAttributes bits 2-7 are reserved "\ - "(should be 0)\r\n"); - OOPS(); - break; - } -} - -/***************************************************************************** - -InitializeGlobalFlags () - -Initialize the global device flags in UVCView.h - -*****************************************************************************/ - -void -InitializePerDeviceSettings ( - PUSBDEVICEINFO info - ) -{ - // Save base address for this current device's info (including Configuration descriptor) - CurrentUSBDeviceInfo = info; - - // Initialize Configuration descriptor length - dwConfigLength = 0; - - // Save # of bytes from start of Configuration descriptor - // (Update this in the descriptor parsing routines) - dwConfigIndex = 0; - - // Flags used in dispvid.c to display default Frame descriptor for MJPEG, - // Uncompressed, Vendor and FrameBased Formats - g_chMJPEGFrameDefault = 0; - g_chUNCFrameDefault = 0; - g_chVendorFrameDefault = 0; - g_chFrameBasedFrameDefault = 0; - - // Spec version of UVC device - g_chUVCversion = 0; - - // Start and end address of the configuration descriptor and start of the string descriptors - g_pConfigDesc = NULL; - g_pStringDescs = NULL; - g_descEnd = NULL; - - // - // The GetConfigDescriptor() function in enum.c does not always work - // If that fails, the Configuration descriptor will be NULL - // and we can only display the device descriptor - // - CurrentConfigDesc = NULL; - if (NULL != info) - { - if (NULL != info->ConfigDesc) - { - CurrentConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); - - // Save the LENGTH of the Config descriptor - // Note that IsIADDevice() saves the ADDRESS of the END of the Config desc - // Be aware of the difference - dwConfigLength = CurrentConfigDesc->wTotalLength; - } - } - - return; -} - -/***************************************************************************** - -IsUVCDevice() - -Return Spec version of UVC device - 0x0 = Not a UVC device - 0x10 = UVC 1.0 - 0x11 = UVC 1.1 - - *****************************************************************************/ - -UINT -IsUVCDevice ( - PUSBDEVICEINFO info - ) -{ - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc = NULL; - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - PUCHAR descEnd = NULL; - UINT uUVCversion = 0; - - // - // The GetConfigDescriptor() function in enum.c does not always work - // If that fails, the Configuration descriptor will be NULL - // and we can only display the device descriptor - // - if (NULL == info) - { - return 0; - } - if (NULL == info->ConfigDesc) - { - return 0; - } - ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); - if (NULL == ConfigDesc) - { - return 0; - } - - // We've got a good Configuration Descriptor - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - - // walk through all the descriptors looking for the VIDEO_CONTROL_HEADER_UNIT - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - if ((commonDesc->bDescriptorType == CS_INTERFACE) && - (commonDesc->bLength > sizeof(VIDEO_CONTROL_HEADER_UNIT))) - { - // Right type, size. Now check subtype - PVIDEO_CONTROL_HEADER_UNIT pCSVC = NULL; - pCSVC = (PVIDEO_CONTROL_HEADER_UNIT) commonDesc; - if (VC_HEADER == pCSVC->bDescriptorSubtype) - { - // found the Class-specific VC Interface Header descriptor - uUVCversion = pCSVC->bcdVideoSpec; - // Save the version to global - g_chUVCversion = uUVCversion; - // We're done - break; - } - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - return (uUVCversion); -} - -/***************************************************************************** - -IsIADDevice() - -*****************************************************************************/ - -UINT -IsIADDevice ( - PUSBDEVICEINFO info - ) -{ - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc = NULL; - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - PUCHAR descEnd = NULL; - UINT uIADcount = 0; - - // - // The GetConfigDescriptor() function in enum.c does not always work - // If that fails, the Configuration descriptor will be NULL - // and we can only display the device descriptor - // - if (NULL == info) - { - return 0; - } - if (NULL == info->ConfigDesc) - { - return 0; - } - - ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); - if (NULL != ConfigDesc) - { - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - } - - // return total number of IAD descriptors in this device configuration - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - if (commonDesc->bDescriptorType == USB_IAD_DESCRIPTOR_TYPE) - { - uIADcount++; - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - return (uIADcount); -} - -/***************************************************************************** - -DisplayIADDescriptor() - -*****************************************************************************/ - -VOID -DisplayIADDescriptor ( - PUSB_IAD_DESCRIPTOR IADDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - int nInterfaces, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - AppendTextBuffer("\r\n ===>IAD Descriptor<===\r\n"); - - //length checked in DisplayConfigDesc() - - AppendTextBuffer("bLength: 0x%02X\r\n", - IADDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - IADDesc->bDescriptorType); - AppendTextBuffer("bFirstInterface: 0x%02X\r\n", - IADDesc->bFirstInterface); - AppendTextBuffer("bInterfaceCount: 0x%02X\r\n", - IADDesc->bInterfaceCount); - if (IADDesc->bInterfaceCount == 1) - { - //@@TestCase A7.1 - //@@Priority 1 - //@@Standard IAD Descriptor Field - bInterfaceCount - //@@The number of interfaces must be greater than 1 - AppendTextBuffer("*!*ERROR: bInterfaceCount must be greater than 1 \r\n"); - OOPS(); - } - if (nInterfaces < IADDesc->bFirstInterface + IADDesc->bInterfaceCount) - { - //@@TestCase A7.2 - //@@Priority 1 - //@@Standard IAD Descriptor Field - bInterfaceCount - //@@The total number of interfaces must be greater than or equal to - //@@ the highest linked interface number (base interface number plus count) - AppendTextBuffer("*!*ERROR: The total number of interfaces (%d) must be greater "\ - "than or equal to\r\n", - nInterfaces); - AppendTextBuffer(" the highest linked interface number (base %d + "\ - "count %d = %d)\r\n", - IADDesc->bFirstInterface, IADDesc->bInterfaceCount, - (IADDesc->bFirstInterface + IADDesc->bInterfaceCount)); - OOPS(); - } - AppendTextBuffer("bFunctionClass: 0x%02X", - IADDesc->bFunctionClass); - if (IADDesc->bFunctionClass == 0) - { - //@@TestCase A7.3 - //@@Priority 1 - //@@Standard IAD Descriptor Field - bFunctionClass - //@@"A value of zero is not allowed in this descriptor" - AppendTextBuffer("\r\n*!*ERROR: bFunctionClass contains an illegal value 0 \r\n"); - OOPS(); - } - - switch (IADDesc->bFunctionClass) - { - case USB_DEVICE_CLASS_AUDIO: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Audio Interface Class\r\n"); - } - - AppendTextBuffer("bFunctionSubClass: 0x%02X", - IADDesc->bFunctionSubClass); - - if(gDoAnnotation) - { - switch (IADDesc->bFunctionSubClass) - { - case USB_AUDIO_SUBCLASS_AUDIOCONTROL: - AppendTextBuffer(" -> Audio Control Interface SubClass\r\n"); - break; - - case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: - AppendTextBuffer(" -> Audio Streaming Interface SubClass\r\n"); - break; - - case USB_AUDIO_SUBCLASS_MIDISTREAMING: - AppendTextBuffer(" -> MIDI Streaming Interface SubClass\r\n"); - break; - - default: - //@@TestCase A7.4 - //@@CAUTION - //@@Descriptor Field - bFunctionSubClass - //@@Invalid bFunctionSubClass - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid bFunctionSubClass\r\n"); - OOPS(); - break; - } - } - break; - - case USB_DEVICE_CLASS_VIDEO: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Video Interface Class\r\n"); - } - - AppendTextBuffer("bFunctionSubClass: 0x%02X", - IADDesc->bFunctionSubClass); - - switch(IADDesc->bFunctionSubClass) - { - case SC_VIDEO_INTERFACE_COLLECTION: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Video Interface Collection\r\n"); - } - break; - - default: - //@@TestCase A7.5 - //@@CAUTION - //@@Descriptor Field - bFunctionSubClass - //@@Invalid bFunctionSubClass - AppendTextBuffer("\r\n*!*ERROR: This should be USB_VIDEO_SC_VIDEO_INTERFACE_COLLECTION %d\r\n", - SC_VIDEO_INTERFACE_COLLECTION); - OOPS(); - break; - } - break; - - case USB_DEVICE_CLASS_HUMAN_INTERFACE: - if(gDoAnnotation) - { - AppendTextBuffer(" -> HID Interface Class\r\n"); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_HUB: - if(gDoAnnotation) - { - AppendTextBuffer(" -> HUB Interface Class\r\n"); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_RESERVED: - //@@TestCase A7.6 - //@@CAUTION - //@@Descriptor Field - bFunctionClass - //@@A reserved USB Device Interface Class has been defined - AppendTextBuffer("\r\n*!*CAUTION: %d is a Reserved USB Device Interface Class\r\n", - USB_DEVICE_CLASS_RESERVED); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_COMMUNICATIONS: - AppendTextBuffer(" -> This is Communications (CDC Control) USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_MONITOR: - AppendTextBuffer(" -> This is a Monitor USB Device Interface Class*** (This may be obsolete)\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: - AppendTextBuffer(" -> This is a Physical Interface USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_POWER: - if(IADDesc->bFunctionSubClass == 1 && IADDesc->bFunctionProtocol == 1) - { - AppendTextBuffer(" -> This is an Image USB Device Interface Class\r\n"); - } - else - { - AppendTextBuffer(" -> This is a Power USB Device Interface Class (This may be obsolete)\r\n"); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_PRINTER: - AppendTextBuffer(" -> This is a Printer USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DEVICE_CLASS_STORAGE: - AppendTextBuffer(" -> This is a Mass Storage USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_CDC_DATA_INTERFACE: - AppendTextBuffer(" -> This is a CDC Data USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_CHIP_SMART_CARD_INTERFACE: - AppendTextBuffer(" -> This is a Chip/Smart Card USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_CONTENT_SECURITY_INTERFACE: - AppendTextBuffer(" -> This is a Content Security USB Device Interface Class\r\n"); - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_DIAGNOSTIC_DEVICE_INTERFACE: - if(IADDesc->bFunctionSubClass == 1 && IADDesc->bFunctionProtocol == 1) - { - AppendTextBuffer(" -> This is a Reprogrammable USB2 Compliance Diagnostic Device USB Device\r\n"); - } - else - { - //@@TestCase A7.7 - //@@CAUTION - //@@Descriptor Field - bFunctionClass - //@@Invalid Interface Class - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_WIRELESS_CONTROLLER_INTERFACE: - if(IADDesc->bFunctionSubClass == 1 && IADDesc->bFunctionProtocol == 1) - { - AppendTextBuffer(" -> This is a Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface\r\n"); - } - else - { - //@@TestCase A7.8 - //@@CAUTION - //@@Descriptor Field - bFunctionClass - //@@Invalid Interface Class - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - case USB_APPLICATION_SPECIFIC_INTERFACE: - AppendTextBuffer(" -> This is an Application Specific USB Device Interface Class\r\n"); - - switch(IADDesc->bFunctionSubClass) - { - case 1: - AppendTextBuffer(" -> This is a Device Firmware Application Specific USB Device Interface Class\r\n"); - break; - case 2: - AppendTextBuffer(" -> This is an IrDA Bridge Application Specific USB Device Interface Class\r\n"); - break; - case 3: - AppendTextBuffer(" -> This is a Test & Measurement Class (USBTMC) Application Specific USB Device Interface Class\r\n"); - break; - default: - //@@TestCase A7.9 - //@@CAUTION - //@@Descriptor Field - bFunctionClass - //@@Invalid Interface Class - AppendTextBuffer("\r\n*!*CAUTION: This appears to be an invalid Interface Class\r\n"); - OOPS(); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - - default: - if(gDoAnnotation) - { - AppendTextBuffer(" -> Interface Class Unknown to USBView\r\n"); - } - AppendTextBuffer("bFunctionSubClass: 0x%02X\r\n", - IADDesc->bFunctionSubClass); - break; - } - - AppendTextBuffer("bFunctionProtocol: 0x%02X", - IADDesc->bFunctionProtocol); - - // check protocol for our class - if ((IADDesc->bFunctionClass == USB_DEVICE_CLASS_VIDEO)) - { - // USB Video Class - if(IADDesc->bFunctionProtocol == PC_PROTOCOL_UNDEFINED) - { - // correct protocol for UVC - if(gDoAnnotation) - { - AppendTextBuffer(" -> PC_PROTOCOL_UNDEFINED protocol\r\n"); - } else { - AppendTextBuffer("\r\n"); - } - } else { - // incorrect protocol for UVC - //@@TestCase A7.10 - //@@WARNING - //@@Descriptor Field - iInterface - //@@bFunctionProtocol must be set to PC_PROTOCOL_UNDEFINED - AppendTextBuffer("*!*WARNING: must be set to PC_PROTOCOL_UNDEFINED %d for this class\r\n", - PC_PROTOCOL_UNDEFINED); - OOPS(); - } - } else { - AppendTextBuffer("\r\n"); - } - - AppendTextBuffer("iFunction: 0x%02X\r\n", - IADDesc->iFunction); - - if(gDoAnnotation) - { - if (IADDesc->iFunction) - { - DisplayStringDescriptor(IADDesc->iFunction, - StringDescs, - LatestDevicePowerState); - } - } -} - -/***************************************************************************** - -GetConfigurationSize() - -*****************************************************************************/ - -UINT -GetConfigurationSize ( - PUSBDEVICEINFO info - ) -{ - PUSB_CONFIGURATION_DESCRIPTOR - ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); - PUSB_COMMON_DESCRIPTOR - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - PUCHAR - descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - UINT uCount = 0; - - // return this device configuration's total sum of descriptor lengths - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - uCount += commonDesc->bLength; - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - return (uCount); -} - -/***************************************************************************** - -GetInterfaceCount() - -*****************************************************************************/ - -UINT -GetInterfaceCount ( - PUSBDEVICEINFO info - ) -{ - // how do we handle composite devices? - PUSB_CONFIGURATION_DESCRIPTOR - ConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->ConfigDesc + 1); - PUSB_COMMON_DESCRIPTOR - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - PUCHAR - descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - UINT uCount = 0; - - // return this device configuration's total number of interface descriptors - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - if (commonDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) - { - uCount++; - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - return (uCount); -} - - -/***************************************************************************** - -DisplayUSEnglishStringDescriptor() - -*****************************************************************************/ - -VOID -DisplayUSEnglishStringDescriptor ( - UCHAR Index, - PSTRING_DESCRIPTOR_NODE USStringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - ULONG nBytes = 0; - BOOLEAN FoundMatchingString = FALSE; - CHAR pString[512]; - - //@@DisplayUSEnglishStringDescriptor - String Descriptor - for (; USStringDescs; USStringDescs = USStringDescs->Next) - { - if (USStringDescs->DescriptorIndex == Index && USStringDescs->LanguageID == 0x0409) - { - FoundMatchingString = TRUE; - - AppendTextBuffer("English product name: \""); - memset(pString, 0, 512); - nBytes = WideCharToMultiByte( - CP_ACP, // CodePage - WC_NO_BEST_FIT_CHARS, - USStringDescs->StringDescriptor->bString, - (USStringDescs->StringDescriptor->bLength - 2) / 2, - pString, - 512, - NULL, // lpDefaultChar - NULL); // pUsedDefaultChar - if (nBytes) - AppendTextBuffer("%s\"\r\n", pString); - else - AppendTextBuffer("\"\r\n", pString); - return; - } - } - - //@@TestCase A8.1 - //@@WARNING - //@@Descriptor Field - string index - //@@No support for english - if (!FoundMatchingString) - { - if (LatestDevicePowerState == PowerDeviceD0) - { - AppendTextBuffer("*!*ERROR: No String Descriptor for index %d!\r\n", Index); - OOPS(); - } - else - { - AppendTextBuffer("String Descriptor for index %d not available while device is in low power state.\r\n", Index); - } - } - else - { - AppendTextBuffer("*!*ERROR: The index selected does not support English(US)\r\n"); - OOPS(); - } - return; - -} - - -/***************************************************************************** - -DisplayStringDescriptor() - -*****************************************************************************/ -VOID -DisplayStringDescriptor ( - UCHAR Index, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - ULONG nBytes = 0; - BOOLEAN FoundMatchingString = FALSE; - PCHAR pStr = NULL; - CHAR pString[512]; - - //@@DisplayStringDescriptor - String Descriptor - - while (StringDescs) - { - if (StringDescs->DescriptorIndex == Index) - { - FoundMatchingString = TRUE; - if(gDoAnnotation) - { - pStr= GetLangIDString(StringDescs->LanguageID); - if(pStr) - { - AppendTextBuffer(" %s \"", - pStr); - } - else - { - //@@TestCase A9.1 - //@@WARNING - //@@Descriptor Field - string index - //@@The Language ID does not match any known languages supported by USB ORG - AppendTextBuffer("*!*WARNING: %d is an invalid Language ID\r\n", - Index); - OOPS(); - } - } - else - { - AppendTextBuffer(" 0x%04X: \"", StringDescs->LanguageID); - } - memset(pString, 0, 512); - - if (StringDescs->StringDescriptor->bLength > sizeof(USHORT)) - { - nBytes = WideCharToMultiByte( - CP_ACP, // CodePage - WC_NO_BEST_FIT_CHARS, - StringDescs->StringDescriptor->bString, - (StringDescs->StringDescriptor->bLength - 2) / 2, - pString, - 512, - NULL, // lpDefaultChar - NULL); // pUsedDefaultChar - if (nBytes) - { - AppendTextBuffer("%s\"\r\n", pString); - } - else - { - AppendTextBuffer("\"\r\n"); - } - } - else - { - // - // This is NULL string which is invalid - // - AppendTextBuffer("\"\r\n"); - } - } - StringDescs = StringDescs->Next; - } - - if (!FoundMatchingString) - { - if (LatestDevicePowerState == PowerDeviceD0) - { - AppendTextBuffer("*!*ERROR: No String Descriptor for index %d!\r\n", Index); - OOPS(); - } - else - { - AppendTextBuffer("String Descriptor for index %d not available while device is in low power state.\r\n", Index); - } - } -} - -/***************************************************************************** - -DisplayUnknownDescriptor() - -*****************************************************************************/ -VOID -DisplayUnknownDescriptor ( - PUSB_COMMON_DESCRIPTOR CommonDesc - ) -{ - AppendTextBuffer("\r\n ===>Descriptor Hex Dump<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", - CommonDesc->bLength); - - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", - CommonDesc->bDescriptorType); - - DisplayRemainingUnknownDescriptor((PUCHAR)CommonDesc, 0, CommonDesc->bLength); -} - -VOID -DisplayRemainingUnknownDescriptor( - PUCHAR DescriptorData, - ULONG Start, - ULONG Stop - ) -{ - ULONG i; - - for (i = Start; i < Stop; i++) - { - AppendTextBuffer("%02X ", - DescriptorData[i]); - - if (i % 16 == 15) - { - AppendTextBuffer("\r\n"); - } - } - - if (i % 16 != 0) - { - AppendTextBuffer("\r\n"); - } -} - - - -/***************************************************************************** - -GetVendorString() - -idVendor - USB Vendor ID - -Return Value - Vendor name string associated with idVendor, or NULL if -no vendor name string is found which is associated with idVendor. - -*****************************************************************************/ - -PCHAR -GetVendorString ( - USHORT idVendor - ) -{ - PVENDOR_ID vendorID = NULL; - - if (idVendor == 0x0000) - { - return NULL; - } - - vendorID = USBVendorIDs; - - while (vendorID->usVendorID != 0x0000) - { - if (vendorID->usVendorID == idVendor) - { - break; - } - vendorID++; - } - - return (vendorID->szVendor); -} - -/***************************************************************************** - -GetLangIDString() - -idVendor - USB Vendor ID - -Return Value - Vendor name string associated with idVendor, or NULL if -no vendor name string is found which is associated with idVendor. - -*****************************************************************************/ - -PCHAR -GetLangIDString ( - USHORT idLang - ) -{ - PUSBLANGID langID = NULL; - - if (idLang != 0x0000) - { - langID = USBLangIDs; - - while (langID->usLangID != 0x0000) - { - if (langID->usLangID == idLang) - { - return (langID->szLanguage); - } - langID++; - } - } - - return NULL; -} - -/***************************************************************************** - -GetStringFromList() - -PSTRINGLIST slList, - pointer to STRINGLIST used - -ULONG ulNumElements, - - number of elements in that STRINGLIST calc before call with sizeof(slList) / sizeof(STRINGLIST), -ULONG or ULONGLONG (if H264_SUPPORT is defined)ulFlag - - flag to look for -PCHAR szDefault - string to return if no match - -Return a string associated with a value from a stringtable. - -example: - GetStringFromList(slPowerState, - sizeof(slPowerState) / sizeof(STRINGLIST), - pUPI->SystemState, - "Invalid Power State") - -*****************************************************************************/ - -PCHAR -GetStringFromList( - PSTRINGLIST slList, - ULONG ulNumElements, -#ifdef H264_SUPPORT - ULONGLONG ulFlag, -#else - ULONG ulFlag, -#endif - _In_ PCHAR szDefault - ) -{ - // ulIndex is zero based, but ulNumElements is 1 based - // subtract 1 from ulNumElements so that are same base -#ifdef H264_SUPPORT - ULONGLONG ulIndex = 0; -#else - ULONG ulIndex = 0; -#endif - ulNumElements--; - - - for ( ; ulIndex <= ulNumElements; ulIndex++) - { - if (ulFlag == slList[ulIndex].ulFlag) - { - return (slList[ulIndex].pszString); - } - } - - return szDefault; -} - diff --git a/tests/projects/winsdk/usbview/dispvid.c b/tests/projects/winsdk/usbview/dispvid.c deleted file mode 100644 index 537309721..000000000 --- a/tests/projects/winsdk/usbview/dispvid.c +++ /dev/null @@ -1,5649 +0,0 @@ -/*++ - -Copyright (c) 2002-2008 Microsoft Corporation - -Module Name: - -DISPVID.C - -Abstract: - -This source file contains routines which update the edit control -to display information about USB Video descriptors. - -Environment: - -user mode - -Revision History: - -11-22-2002 : created -03-28-2003 : major revisions from latest specs. -03-28-2008 : include USB Video Class 1.1 - ---*/ - -//***************************************************************************** -// I N C L U D E S -//***************************************************************************** - -#include "uvcview.h" -#include "h264.h" - -//***************************************************************************** -// G L O B A L S P R I V A T E T O T H I S F I L E -//***************************************************************************** - -int StillMethod = 0; - -// -// USB Device Class Definition for Video Devices 0.8b version -// -// 3.6.2.3 Camera Terminal Descriptor -// -STRINGLIST slCameraControl1 [] = -{ - {1, "Scanning Mode", ""}, - {2, "Auto-Exposure Mode", ""}, - {4, "Auto-Exposure Priority", ""}, - {8, "Exposure Time (Absolute)", ""}, - {0x10, "Exposure Time (Relative)", ""}, - {0x20, "Focus (Absolute)", ""}, - {0x40, "Focus (Relative)", ""}, - {0x80, "Iris (Absolute)", ""}, -}; -STRINGLIST slCameraControl2 [] = -{ - {1, "Iris (Relative)", ""}, - {2, "Zoom (Absolute)", ""}, - {4, "Zoom (Relative)", ""}, - {8, "PanTilt (Absolute)", ""}, - {0x10, "PanTilt (Relative)", ""}, - {0x20, "Roll (Absolute)", ""}, - {0x40, "Roll (Relative)", ""}, - {0x80, "Reserved", ""}, -}; -STRINGLIST slCameraControl3 [] = -{ - {1, "Reserved", ""}, - {2, "Focus, Auto", ""}, - {4, "Privacy", ""}, - {8, "Focus, Simple", ""}, - {0x10, "Window", ""}, - {0x20, "Region of Interest", ""}, - {0x40, "Reserved", ""}, - {0x80, "Reserved", ""}, -}; - -// 3.6.2.5 Processing Unit Descriptor -// -STRINGLIST slProcessorControls1 [] = -{ - {1, "Brightness", ""}, - {2, "Contrast", ""}, - {4, "Hue", ""}, - {8, "Saturation", ""}, - {0x10, "Sharpness", ""}, - {0x20, "Gamma", ""}, - {0x40, "White Balance Temperature", ""}, - {0x80, "White Balance Component", ""}, -}; -STRINGLIST slProcessorControls2 [] = -{ - {1, "Backlight Compensation", ""}, - {2, "Gain", ""}, - {4, "Power Line Frequency", ""}, - {8, "Hue, Auto", ""}, - {0x10, "White Balance Temperature, Auto", ""}, - {0x20, "White Balance Component, Auto", ""}, - {0x40, "Digital Multiplier", ""}, - {0x80, "Digital Multiplier Limit", ""}, -}; -STRINGLIST slProcessorControls3 [] = -{ - {1, "Analog Video Standard", ""}, - {2, "Analog Video Lock Status", ""}, - {4, "Contrast, Auto", ""}, - {8, "Reserved", ""}, - {0x10, "Reserved", ""}, - {0x20, "Reserved", ""}, - {0x40, "Reserved", ""}, - {0x80, "Reserved", ""}, -}; - - -STRINGLIST slProcessorVideoStandards [] = -{ - {1, "None", ""}, - {2, "NTSC - 525/60", ""}, - {4, "PAL - 625/50", ""}, - {8, "SECAM - 625/50", ""}, - {0x10, "NTSC - 625/50", ""}, - {0x20, "PAL - 525/60", ""}, - {0x40, "Reserved", ""}, - {0x80, "Reserved", ""}, -}; - -// 3.8.2.1 Input Header Descriptor -// -STRINGLIST slInputHeaderControls[]= -{ - {1, "Key Frame Rate" , ""}, - {2, "P Frame Rate" , ""}, - {4, "Compression Quality" , ""}, - {8, "Compression Window Size", ""}, - {0x10, "Generate Key Frame" , ""}, - {0x20, "Update Frame Segment" , ""}, - {0x40, "Reserved" , ""}, - {0x80, "Reserved" , ""}, -}; - -STRINGLIST slOutputHeaderControls[]= -{ - {1, "Key Frame Rate" , ""}, - {2, "P Frame Rate" , ""}, - {4, "Compression Quality" , ""}, - {8, "Compression Window Size", ""}, - {0x10, "Reserved" , ""}, - {0x20, "Reserved" , ""}, - {0x40, "Reserved" , ""}, - {0x80, "Reserved" , ""}, -}; - -STRINGLIST slMediaTransportControls[]= -{ - {1, "Transport Control" , ""}, - {2, "Absolute Track Number Control", ""}, - {4, "Media Information" , ""}, - {8, "Time Code Information" , ""}, - {0x10, "Reserved" , ""}, - {0x20, "Reserved" , ""}, - {0x40, "Reserved" , ""}, - {0x80, "Reserved" , ""}, -}; - -STRINGLIST slMediaTransportModes1[]= -{ - {1, "Play Forward", ""}, - {2, "Pause", ""}, - {4, "Rewind", ""}, - {8, "Fast Forward", ""}, - {0x10, "High Speed Rewind", ""}, - {0x20, "Stop", ""}, - {0x40, "Eject", ""}, - {0x80, "Play Next Frame", ""}, -}; - -STRINGLIST slMediaTransportModes2[]= -{ - {1, "Play Slowest Forward", ""}, - {2, "Play Slow Forward 4", ""}, - {4, "Play Slow Forward 3", ""}, - {8, "Play Slow Forward 2", ""}, - {0x10, "Play Slow Forward 1", ""}, - {0x20, "Play X1", ""}, - {0x40, "Play Fast Forward 1", ""}, - {0x80, "Play Fast Forward 2", ""}, -}; - -STRINGLIST slMediaTransportModes3[]= -{ - {1, "Play Fast Forward 3", ""}, - {2, "Play Fast Forward 4", ""}, - {4, "Play Fastest Forward", ""}, - {8, "Play Previous Frame", ""}, - {0x10, "Play Slowest Reverse", ""}, - {0x20, "Play Slow Reverse 4", ""}, - {0x40, "Play Slow Reverse 3", ""}, - {0x80, "Play Slow Reverse 2", ""}, -}; - -STRINGLIST slMediaTransportModes4[]= -{ - {1, "Play Slow Reverse 1", ""}, - {2, "Play X1 Reverse", ""}, - {4, "Play Fast Reverse 1", ""}, - {8, "Play Fast Reverse 2", ""}, - {0x10, "Play Fast Reverse 3", ""}, - {0x20, "Play Fast Reverse 4", ""}, - {0x40, "Play Fastest Reverse", ""}, - {0x80, "Record StateStart", ""}, -}; - -STRINGLIST slMediaTransportModes5[]= -{ - {1, "Record Pause", ""}, - {2, "Reserved", ""}, - {4, "Reserved", ""}, - {8, "Reserved", ""}, - {0x10, "Reserved", ""}, - {0x20, "Reserved", ""}, - {0x40, "Reserved", ""}, - {0x80, "Reserved", ""}, -}; - -STRINGLIST slInputTermTypes[]= -{ - {0x0100, "TT_VENDOR_SPECIFIC", "I//O"}, - {0x0101, "TT_STREAMING", "I//O"}, - {0x0400, "EXTERNAL_VENDOR_SPECIFIC", "I//O"}, - {0x0401, "COMPOSITE_CONNECTOR", "I//O"}, - {0x0402, "SVIDEO_CONNECTOR", "I//O"}, - {0x0403, "COMPONENT_CONNECTOR", "I//O"}, - {0x0200, "ITT_VENDOR_SPECIFIC", "I"}, - {0x0201, "ITT_CAMERA", "I"}, - {0x0202, "ITT_MEDIA_TRANSPORT_INPUT", "I"}, -}; -STRINGLIST slOutputTermTypes[]= -{ - {0x0100, "TT_VENDOR_SPECIFIC", "I//O"}, - {0x0101, "TT_STREAMING", "I//O"}, - {0x0400, "EXTERNAL_VENDOR_SPECIFIC", "I//O"}, - {0x0401, "COMPOSITE_CONNECTOR", "I//O"}, - {0x0402, "SVIDEO_CONNECTOR", "I//O"}, - {0x0403, "COMPONENT_CONNECTOR", "I//O"}, - {0x0300, "OTT_VENDOR_SPECIFIC", "O"}, - {0x0301, "OTT_DISPLAY", "O"}, - {0x0302, "OTT_MEDIA_TRANSPORT_OUTPUT", "O"}, -}; - -//***************************************************************************** -// L O C A L F U N C T I O N P R O T O T Y P E S -//***************************************************************************** - -BOOL -DisplayVCHeader ( - PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc - ); -BOOL -DisplayVCInputTerminal ( - PVIDEO_INPUT_TERMINAL VidITDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -BOOL -DisplayVCOutputTerminal ( - PVIDEO_OUTPUT_TERMINAL VidOTDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -BOOL -DisplayVCCameraTerminal ( - PVIDEO_CAMERA_TERMINAL CameraDesc - ); -BOOL -DisplayVCMediaTransInputTerminal ( - PVIDEO_INPUT_MTT VCMedTransInDesc - ); -BOOL -DisplayVCMediaTransOutputTerminal ( - PVIDEO_OUTPUT_MTT VCMedTransOutDesc - ); -BOOL -DisplayVCSelectorUnit ( - PVIDEO_SELECTOR_UNIT VidSelectorDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -BOOL -DisplayVCProcessingUnit ( - PVIDEO_PROCESSING_UNIT VidProcessingDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -BOOL -DisplayVCExtensionUnit ( - PVIDEO_EXTENSION_UNIT VidExtensionDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -BOOL -DisplayVidInHeader ( - PVIDEO_STREAMING_INPUT_HEADER VidInHeaderDesc - ); -BOOL -DisplayVidOutHeader ( - PVIDEO_STREAMING_OUTPUT_HEADER VidOutHeaderDesc - ); -BOOL -DisplayStillImageFrame ( - PVIDEO_STILL_IMAGE_FRAME StillFrameDesc - ); -BOOL -DisplayColorMatching ( - PVIDEO_COLORFORMAT ColorMatchDesc - ); -BOOL -DisplayUncompressedFormat ( - PVIDEO_FORMAT_UNCOMPRESSED UnCompFormatDesc - ); -BOOL -DisplayUncompressedFrameType ( - PVIDEO_FRAME_UNCOMPRESSED UnCompFrameDesc - ); -BOOL -DisplayUnComContinuousFrameType( - PVIDEO_FRAME_UNCOMPRESSED UContinuousDesc - ); -BOOL -DisplayUnComDiscreteFrameType( - PVIDEO_FRAME_UNCOMPRESSED UDiscreteDesc - ); -BOOL -DisplayMJPEGFormat ( - PVIDEO_FORMAT_MJPEG MJPEGFormatDesc - ); -BOOL -DisplayMJPEGFrameType ( - PVIDEO_FRAME_MJPEG MJPEGFrameDesc - ); -BOOL -DisplayMJPEGContinuousFrameType( - PVIDEO_FRAME_MJPEG MContinuousDesc - ); -BOOL -DisplayMJPEGDiscreteFrameType( - PVIDEO_FRAME_MJPEG MDiscreteDesc - ); -BOOL -DisplayMPEG1SSFormat ( - PVIDEO_FORMAT_MPEG1SS MPEG1SSFormatDesc - ); -BOOL -DisplayMPEG2PSFormat ( - PVIDEO_FORMAT_MPEG2PS MPEG2PSFormatDesc - ); -BOOL -DisplayMPEG2TSFormat ( - PVIDEO_FORMAT_MPEG2TS MPEG2TSFormatDesc - ); -BOOL -DisplayMPEG4SLFormat ( - PVIDEO_FORMAT_MPEG4SL MPEG4SLFormatDesc - ); -BOOL -DisplayDVFormat ( - PVIDEO_FORMAT_DV DVFormatDesc - ); -BOOL -DisplayVendorVidFormat ( - PVIDEO_FORMAT_VENDOR VendorVidFormatDesc - ); -BOOL -DisplayVendorVidFrameType ( - PVIDEO_FRAME_VENDOR VendorVidFrameDesc - ); -BOOL -DisplayVendorVidContinuousFrameType( - PVIDEO_FRAME_VENDOR VContinuousDesc - ); -BOOL -DisplayVendorVidDiscreteFrameType( - PVIDEO_FRAME_VENDOR VDiscreteDesc - ); -BOOL -DisplayFramePayloadFormat( - PVIDEO_FORMAT_FRAME FramePayloadFormatDesc - ); -BOOL -DisplayFramePayloadFrame( - PVIDEO_FRAME_FRAME FramePayloadFrameDesc - ); -BOOL -DisplayFramePayloadContinuousFrameType( - PVIDEO_FRAME_FRAME FContinuousDesc - ); -BOOL -DisplayFramePayloadDiscreteFrameType( - PVIDEO_FRAME_FRAME FDiscreteDesc - ); -BOOL -DisplayStreamPayload( - PVIDEO_FORMAT_STREAM StreamPayloadDesc - ); -BOOL -DisplayVSEndpoint ( - PVIDEO_CS_INTERRUPT VidEndpointDesc - ); -VOID -VDisplayBytes ( - PUCHAR Data, - USHORT Len - ); -PCHAR -VidFormatGUIDCodeToName ( - REFGUID VidFormatGUIDCode - ); -UINT -GetVCInterfaceSize ( - PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc - ); -UINT -CheckForColorMatchingDesc ( - PVIDEO_SPECIFIC FormatDesc, - UCHAR bNumFrameDescriptors, - UCHAR bDescriptorSubtype - ); -UINT -GetVSInterfaceSize ( - PUSB_COMMON_DESCRIPTOR VidInHeaderDesc, - USHORT wTotalLength - ); -BOOL -ValidateTerminalID( - UINT uTerminalID - ); -VOID -VDisplayDescString ( - UINT uControlSize, - PUCHAR pControl , - PSTRINGLIST pslControl - ); - -//***************************************************************************** -// L O C A L F U N C T I O N S -//***************************************************************************** - -//***************************************************************************** -// -// DisplayVideoDescriptor() UPDATED -// -// VidCommonDesc - An Video Class Descriptor -// -// bInterfaceSubClass - The SubClass of the Interface containing the descriptor -// -//***************************************************************************** - -BOOL -DisplayVideoDescriptor ( - PVIDEO_SPECIFIC VidCommonDesc, - UCHAR bInterfaceSubClass, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayVideoDescriptor -Class-Specific Video Descriptor - switch (VidCommonDesc->bDescriptorType) - { - case CS_INTERFACE: - //@@DisplayVideoDescriptor -Class-Specific Video Interface Descriptor - switch (bInterfaceSubClass) - { - case VIDEO_SUBCLASS_CONTROL: - //@@DisplayVideoDescriptor -Class-Specific Video Control Interface Descriptor - switch (VidCommonDesc->bDescriptorSubtype) - { - case VC_HEADER: - return DisplayVCHeader( - (PVIDEO_CONTROL_HEADER_UNIT)VidCommonDesc); - - case INPUT_TERMINAL: - return DisplayVCInputTerminal( - (PVIDEO_INPUT_TERMINAL)VidCommonDesc, - StringDescs, - LatestDevicePowerState); - - case OUTPUT_TERMINAL: - return DisplayVCOutputTerminal( - (PVIDEO_OUTPUT_TERMINAL)VidCommonDesc, - StringDescs, - LatestDevicePowerState); - - case SELECTOR_UNIT: - return DisplayVCSelectorUnit( - (PVIDEO_SELECTOR_UNIT)VidCommonDesc, - StringDescs, - LatestDevicePowerState); - - case PROCESSING_UNIT: - return DisplayVCProcessingUnit( - (PVIDEO_PROCESSING_UNIT)VidCommonDesc, - StringDescs, - LatestDevicePowerState); - - case EXTENSION_UNIT: - return DisplayVCExtensionUnit( - (PVIDEO_EXTENSION_UNIT)VidCommonDesc, - StringDescs, - LatestDevicePowerState); - -#ifdef H264_SUPPORT - case H264_ENCODING_UNIT: - return DisplayVCH264EncodingUnit( - (PVIDEO_ENCODING_UNIT)VidCommonDesc - ); - -#endif - -#ifdef H264_SUPPORT - case MAX_TYPE_UNIT+1: - // for H.264, the bDescriptorSubtype = 7, which is equal to MAX_TYPE_UNIT - // so now MAX_TYPE_UNIT needs to be set to 8 - //(TODO: need to change nt\sdpublic\internal\drivers\inc\uvcdesc.h's define - // of MAX_TYPE_UNIT from7 to 8, and ad the type for H.264 = 8) -#else - case MAX_TYPE_UNIT: -#endif - //@@TestCase B1.1 - //@@CAUTION - //@@Descriptor Field - bDescriptorSubtype - //@@An undefined descriptor subtype has been defined - AppendTextBuffer("*!*CAUTION: This is an undefined class specific "\ - "Video Control bDescriptorSubtype\r\n"); - break; - - default: - //@@TestCase B1.2 - //@@ERROR - //@@Descriptor Field - bDescriptorSubtype - //@@An unknown descriptor subtype has been defined - AppendTextBuffer("*!*ERROR: unknown bDescriptorSubtype\r\n"); - OOPS(); - break; - } - break; - - case VIDEO_SUBCLASS_STREAMING: - //@@DisplayVideoDescriptor -Class-Specific Video Streaming Interface Descriptor - switch (VidCommonDesc->bDescriptorSubtype) - { - case VS_INPUT_HEADER: - return DisplayVidInHeader( - (PVIDEO_STREAMING_INPUT_HEADER)VidCommonDesc); - - case VS_OUTPUT_HEADER: - return DisplayVidOutHeader( - (PVIDEO_STREAMING_OUTPUT_HEADER)VidCommonDesc); - - case VS_STILL_IMAGE_FRAME: - return DisplayStillImageFrame( - (PVIDEO_STILL_IMAGE_FRAME)VidCommonDesc); - - case VS_FORMAT_UNCOMPRESSED: -#ifdef H264_SUPPORT - { - BOOL retCode = DisplayUncompressedFormat( (PVIDEO_FORMAT_UNCOMPRESSED)VidCommonDesc ); - g_expectedNumberOfUncompressedFrameFrameDescriptors += ((PVIDEO_FORMAT_UNCOMPRESSED)VidCommonDesc)->bNumFrameDescriptors; - return retCode; - } -#else - return DisplayUncompressedFormat( - (PVIDEO_FORMAT_UNCOMPRESSED)VidCommonDesc); -#endif - - case VS_FRAME_UNCOMPRESSED: -#ifdef H264_SUPPORT - { - BOOL retCode = DisplayUncompressedFrameType( (PVIDEO_FRAME_UNCOMPRESSED)VidCommonDesc ); - g_numberOfUncompressedFrameFrameDescriptors++; - return retCode; - } -#else - return DisplayUncompressedFrameType( - (PVIDEO_FRAME_UNCOMPRESSED)VidCommonDesc); -#endif - -#ifdef H264_SUPPORT - case VS_FORMAT_H264: - { - BOOL retCode = DisplayVCH264Format( (PVIDEO_FORMAT_H264)VidCommonDesc ); - g_expectedNumberOfH264FrameDescriptors += ((PVIDEO_FORMAT_H264)VidCommonDesc)->bNumFrameDescriptors; - return retCode; - } - - case VS_FRAME_H264: - { - BOOL retCode = DisplayVCH264FrameType( (PVIDEO_FRAME_H264)VidCommonDesc ); - g_numberOfH264FrameDescriptors++; - return retCode; - } -#endif - - case VS_FORMAT_MJPEG: -#ifdef H264_SUPPORT // additional checks - { - BOOL retCode = DisplayMJPEGFormat( (PVIDEO_FORMAT_MJPEG)VidCommonDesc ); - g_expectedNumberOfMJPEGFrameDescriptors += ((PVIDEO_FORMAT_MJPEG)VidCommonDesc)->bNumFrameDescriptors; - return retCode; - } -#else - return DisplayMJPEGFormat( - (PVIDEO_FORMAT_MJPEG)VidCommonDesc); -#endif - - case VS_FRAME_MJPEG: -#ifdef H264_SUPPORT - { - BOOL retCode = DisplayMJPEGFrameType( (PVIDEO_FRAME_MJPEG)VidCommonDesc ); - g_numberOfMJPEGFrameDescriptors++; - return retCode; - } - -#else - return DisplayMJPEGFrameType( - (PVIDEO_FRAME_MJPEG)VidCommonDesc); -#endif - - - - case VS_FORMAT_MPEG1: - { - if (UVC10 == g_chUVCversion) - { - return DisplayMPEG1SSFormat( - (PVIDEO_FORMAT_MPEG1SS)VidCommonDesc); - } - else // this format is obsoleted in UVC version >= 1.1 - { - AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); - OOPS(); - break; - } - } - - case VS_FORMAT_MPEG2PS: - { - if (UVC10 == g_chUVCversion) - { - return DisplayMPEG2PSFormat( - (PVIDEO_FORMAT_MPEG2PS)VidCommonDesc); - } - else // this format is obsoleted in UVC version >= 1.1 - { - AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); - OOPS(); - break; - } - } - - case VS_FORMAT_MPEG2TS: - return DisplayMPEG2TSFormat( - (PVIDEO_FORMAT_MPEG2TS)VidCommonDesc); - - case VS_FORMAT_MPEG4SL: - { - if (UVC10 == g_chUVCversion) - { - return DisplayMPEG4SLFormat( - (PVIDEO_FORMAT_MPEG4SL)VidCommonDesc); - } - else // this format is obsoleted in UVC version >= 1.1 - { - AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); - OOPS(); - break; - } - } - - case VS_FORMAT_DV: - return DisplayDVFormat( - (PVIDEO_FORMAT_DV)VidCommonDesc); - - case VS_COLORFORMAT: - return DisplayColorMatching( - (PVIDEO_COLORFORMAT)VidCommonDesc); - - case VS_FORMAT_VENDOR: - { - if (UVC10 == g_chUVCversion) - { - return DisplayVendorVidFormat( - (PVIDEO_FORMAT_VENDOR)VidCommonDesc); - } - else // this format is obsoleted in UVC version >= 1.1 - { - AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); - OOPS(); - break; - } - } - - case VS_FRAME_VENDOR: - { - if (UVC10 == g_chUVCversion) - { - return DisplayVendorVidFrameType( - (PVIDEO_FRAME_VENDOR)VidCommonDesc); - } - else // this format is obsoleted in UVC version >= 1.1 - { - AppendTextBuffer("*!*ERROR: obsoleted bDescriptorSubtype\r\n"); - OOPS(); - break; - } - } - - case VS_FORMAT_FRAME_BASED: - { - if (UVC10 != g_chUVCversion) - { - return DisplayFramePayloadFormat( - (PVIDEO_FORMAT_FRAME)VidCommonDesc); - } - else // this format did not exist in UVC 1.0 - { - AppendTextBuffer("*!*ERROR: bDescriptorSubtype did not exist in UVC 1.0\r\n"); - OOPS(); - break; - } - } - - case VS_FRAME_FRAME_BASED: - { - if (UVC10 != g_chUVCversion) - { - return DisplayFramePayloadFrame( - (PVIDEO_FRAME_FRAME)VidCommonDesc); - } - else // this format did not exist in UVC 1.0 - { - AppendTextBuffer("*!*ERROR: bDescriptorSubtype did not exist in UVC 1.0\r\n"); - OOPS(); - break; - } - } - - case VS_FORMAT_STREAM_BASED: - { - if (UVC10 != g_chUVCversion) - { - return DisplayStreamPayload( - (PVIDEO_FORMAT_STREAM)VidCommonDesc); - } - else // this format did not exist in UVC 1.0 - { - AppendTextBuffer("*!*ERROR: bDescriptorSubtype did not exist in UVC 1.0\r\n"); - OOPS(); - break; - } - } - - case VS_DESCRIPTOR_UNDEFINED: - //@@TestCase B1.3 - //@@CAUTION - //@@Descriptor Field - bDescriptorSubtype - //@@An undefined descriptor subtype has been defined - AppendTextBuffer("*!*CAUTION: This is an undefined class specific Video "\ - "Streaming bDescriptorSubtype\r\n"); - break; - - default: - //@@TestCase B1.4 - //@@ERROR - //@@Descriptor Field - bDescriptorSubtype - //@@An unknown descriptor subtype has been defined - AppendTextBuffer("*!*ERROR: unknown bDescriptorSubtype\r\n"); - OOPS(); - break; - } - break; - - default: - //@@TestCase B1.6 - //@@ERROR - //@@Descriptor Field - bInterfaceSubClass - //@@An unknown interface sub-class has been defined - AppendTextBuffer("*!*ERROR: unknown bInterfaceSubClass\r\n"); - OOPS(); - break; - } - break; - - case CS_ENDPOINT: - //@@DisplayVideoDescriptor -Class-Specific Video Endpoint Descriptor - switch (VidCommonDesc->bDescriptorSubtype) - { - //@@TestCase B1.7 - //@@CAUTION - //@@Descriptor Field - bInterfaceSubtype - //@@An undefined descriptor subtype has been defined - case EP_UNDEFINED: - AppendTextBuffer("*!*CAUTION: This is an undefined bDescriptorSubtype\r\n"); - break; - //@@TestCase B1.8 - //@@Not yet implemented - Priority 3 - //@@Descriptor Field - bDescriptorSubtype - //@@Question: How valid are VIDEO_EP_GENERAL and VIDEO_EP_ENDPOINT? Should we test? - case EP_GENERAL: - break; - case EP_ENDPOINT: - break; - case EP_INTERRUPT: - return DisplayVSEndpoint( - (PVIDEO_CS_INTERRUPT)VidCommonDesc); - break; - default: - //@@TestCase B1.9 - //@@ERROR - //@@Descriptor Field - bDescriptorSubtype - //@@An unknown descriptor subtype has been defined - AppendTextBuffer("*!*CAUTION: Unknown bDescriptorSubtype"); - break; - } - break; - //@@DisplayVideoDescriptor -Class-Specific Video Device Descriptor - //@@DisplayVideoDescriptor -Class-Specific Video Configuration Descriptor - //@@DisplayVideoDescriptor -Class-Specific Video String Descriptor - //@@DisplayVideoDescriptor -Class-Specific Video Undefined Descriptor - //@@TestCase B1.10 - //@@Not yet implemented - Priority 3 - //@@Descriptor -Class-Specific Device, Configuration, String, Undefined - //@@Descriptor Field - bDescriptorType - //@@Question: How valid are these Descriptor Types? Should we test? - - /* case USB_VIDEO_CS_DEVICE: - AppendTextBuffer("USB_VIDEO_CS_DEVICE bDescriptorType\r\n"); - break; - - case USB_VIDEO_CS_CONFIGURATION: - AppendTextBuffer("USB_VIDEO_CS_CONFIGURATION bDescriptorType\r\n"); - break; - - case USB_VIDEO_CS_STRING: - AppendTextBuffer("USB_VIDEO_CS_STRING bDescriptorType\r\n"); - break; - - case USB_VIDEO_CS_UNDEFINED: - AppendTextBuffer("USB_VIDEO_CS_UNDEFINED bDescriptorType\r\n"); - break; - */ - default: - //@@TestCase B1.11 - //@@ERROR - //@@Descriptor Field - bDescriptorType - //@@An unknown descriptor type has been defined - AppendTextBuffer("*!*CAUTION: Unknown bDescriptorSubtype"); - OOPS(); - break; - } - - return FALSE; -} - - -//***************************************************************************** -// -// DisplayVCHeader() -// -//***************************************************************************** - -BOOL -DisplayVCHeader ( - PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc - ) -{ - //@@DisplayVCHeader -Video Control Interface Header - UINT i = 0; - UINT uSize = 0; - PUCHAR pData = NULL; - - AppendTextBuffer("\r\n ===>Class-Specific Video Control Interface Header "\ - "Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VCInterfaceDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VCInterfaceDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VCInterfaceDesc->bDescriptorSubtype); - if ( UVC10 == g_chUVCversion ) - { - AppendTextBuffer("bcdVDC: 0x%04X\r\n", VCInterfaceDesc->bcdVideoSpec); - } - else - { - AppendTextBuffer("bcdUVC: 0x%04X\r\n", VCInterfaceDesc->bcdVideoSpec); - } - AppendTextBuffer("wTotalLength: 0x%04X", VCInterfaceDesc->wTotalLength); - - // Verify the total interface size (size of this header and all descriptors - // following until and not including the first endpoint) - uSize = GetVCInterfaceSize(VCInterfaceDesc); - if (uSize != VCInterfaceDesc->wTotalLength) { - AppendTextBuffer("\r\n*!*ERROR: Invalid total interface size 0x%02X, should be 0x%02X\r\n", - VCInterfaceDesc->wTotalLength, uSize); - } else { - AppendTextBuffer(" -> Validated\r\n"); - } - AppendTextBuffer("dwClockFreq: 0x%08X", - VCInterfaceDesc->dwClockFreq); - if (gDoAnnotation) - { - AppendTextBuffer(" = (%d) Hz", VCInterfaceDesc->dwClockFreq); - } - AppendTextBuffer("\r\nbInCollection: 0x%02X\r\n", - VCInterfaceDesc->bInCollection); - - // baInterfaceNr is a variable length field - // Size is in bInCollection - for (i = 1, pData = (PUCHAR) &VCInterfaceDesc->bInCollection; - i <= VCInterfaceDesc->bInCollection; i++, pData++) - { - AppendTextBuffer("baInterfaceNr[%d]: 0x%02X\r\n", - i, *pData); - } - - uSize = (sizeof(VIDEO_CONTROL_HEADER_UNIT) + VCInterfaceDesc->bInCollection); - if (VCInterfaceDesc->bLength != uSize) - { - //@@TestCase B2.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is less than required length in - //@@ the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - VCInterfaceDesc->bLength, uSize); - OOPS(); - } - - //@@TestCase B2.2 (also in Descript.c) - //@@WARNING - //@@Descriptor Field - bcdVDC - //@@The bcdVDC version of the device is not the same as the version of used by USBView - if(VCInterfaceDesc->bcdVideoSpec < BCDVDC) - { - AppendTextBuffer("*!*WARNING: This device is set to the old USB Video "\ - "Class spec version 0x%04X\r\n", VCInterfaceDesc->bcdVideoSpec); - OOPS(); - } - - if (VCInterfaceDesc->dwClockFreq < 1) - { - //@@TestCase B2.3 (Descript.c Line 70) - //@@WARNING - //@@dwClockFrequency should be greater than 0 - //@@Question should we check that any non-zero value is accurate - AppendTextBuffer("*!*ERROR: dwClockFreq must be non-zero\r\n"); - OOPS(); - } - - //@@TestCase B2.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - baInterfaceNr - //@@We should test to verify each interface number is valid? - // for (i=0; ibInCollection; i++) - // {AppendTextBuffer("baInterfaceNr[%d]: 0x%02X\r\n", i+1, - // VCInterfaceDesc->baInterfaceNr[i]);} - - - if (gDoAnnotation) - { - switch(g_chUVCversion) - { - case UVC10: - AppendTextBuffer("USB Video Class device: spec version 1.0\r\n"); - break; - case UVC11: - AppendTextBuffer("USB Video Class device: spec version 1.1\r\n"); - break; -#ifdef H264_SUPPORT - case UVC15: - AppendTextBuffer("USB Video Class device: spec version 1.5\r\n"); - break; -#endif - - default: - break; - } - } - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCInputTerminal() -// -//***************************************************************************** - -BOOL -DisplayVCInputTerminal ( - PVIDEO_INPUT_TERMINAL VidITDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayVCInputTerminal -Video Control Input Terminal - PCHAR pStr = NULL; - - AppendTextBuffer("\r\n ===>Video Control Input Terminal Descriptor<===\r\n"); - - AppendTextBuffer("bLength: 0x%02X\r\n", VidITDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidITDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidITDesc->bDescriptorSubtype); - AppendTextBuffer("bTerminalID: 0x%02X\r\n", VidITDesc->bTerminalID); - AppendTextBuffer("wTerminalType: 0x%04X", VidITDesc->wTerminalType); - if(gDoAnnotation) - { - pStr = GetStringFromList(slInputTermTypes, - sizeof(slInputTermTypes) / sizeof(STRINGLIST), - VidITDesc->wTerminalType, - "Invalid Input Terminal Type"); - AppendTextBuffer(" = (%s)", pStr); - } - AppendTextBuffer("\r\n"); - - AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidITDesc->bAssocTerminal); - AppendTextBuffer("iTerminal: 0x%02X\r\n", VidITDesc->iTerminal); - if (gDoAnnotation) - { - if (VidITDesc->iTerminal) - { - // if executing this code, the configuration descriptor has been - // obtained. If a device is suspended, then its configuration - // descriptor was not obtained and we do not want errors to be - // displayed when string descriptors were not obtained. - DisplayStringDescriptor(VidITDesc->iTerminal, StringDescs, LatestDevicePowerState); - } - } - - if (VidITDesc->bLength < sizeof(VIDEO_INPUT_TERMINAL)) - { - //@@TestCase B3.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is less than required length in - //@@ the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d is too small\r\n", VidITDesc->bLength); - OOPS(); - } - - if (VidITDesc->bTerminalID < 1) - { - //@@TestCase B3.2 (descript.c line 133) - //@@ERROR - //@@Descriptor Field - bTerminalID - //@@bTerminalID should be greater than 0 - //@@Question: Should test to verify terminal number is valid - AppendTextBuffer("*!*ERROR: bTerminalID of %d is too small\r\n", VidITDesc->bTerminalID); - OOPS(); - } - - if (!(pStr)) - { - //@@TestCase B3.3 - //@@CAUTION - //@@Descriptor Field - wTerminalType - //@@No valid Terminal Type was found - AppendTextBuffer("*!*CAUTION: 0x%04X is an unknown wTerminalType for an Input "\ - "Terminal\r\n", VidITDesc->wTerminalType); - OOPS(); - } - - //@@TestCase B3.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bAssocTerminal - //@@Should test to verify terminal number is valid? - // AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidITDesc->bAssocTerminal); - - switch (VidITDesc->wTerminalType) - { - case 0x0100: // TT_VENDOR_SPECIFIC Terminal Type - break; - case 0x0101: // TT_STREAMING Terminal Type - break; - case 0x0200: // ITT_VENDOR_SPECIFIC Terminal Type - break; - case 0x0201: // ITT_CAMERA Terminal Type - return DisplayVCCameraTerminal( - (PVIDEO_CAMERA_TERMINAL)VidITDesc); - case 0x0202: // ITT_MEDIA_TRANSPORT_INPUT Terminal Type - return DisplayVCMediaTransInputTerminal( - (PVIDEO_INPUT_MTT)VidITDesc); - case 0x0400: // EXTERNAL_VENDOR_SPECIFIC Terminal Type - break; - case 0x0401: // COMPOSITE_CONNECTOR Terminal Type - break; - case 0x0402: // SVIDEO_CONNECTOR Terminal Type - break; - case 0x0403: // COMPONENT_CONNECTOR Terminal Type - break; - default: - break; - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCOutputTerminal() -// -//***************************************************************************** - -BOOL -DisplayVCOutputTerminal ( - PVIDEO_OUTPUT_TERMINAL VidOTDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayVCOutputTerminal -Video Control Output Terminal - PCHAR pStr = NULL; - - AppendTextBuffer("\r\n ===>Video Control Output Terminal Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VidOTDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidOTDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidOTDesc->bDescriptorSubtype); - AppendTextBuffer("bTerminalID: 0x%02X\r\n", VidOTDesc->bTerminalID); - AppendTextBuffer("wTerminalType: 0x%04X", VidOTDesc->wTerminalType); - if(gDoAnnotation) - { - pStr = GetStringFromList(slOutputTermTypes, - sizeof(slOutputTermTypes) / sizeof(STRINGLIST), - VidOTDesc->wTerminalType, - "Invalid Output Terminal Type"); - AppendTextBuffer(" = (%s)", pStr); - } - AppendTextBuffer("\r\n"); - AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidOTDesc->bAssocTerminal); - AppendTextBuffer("bSourceID: 0x%02X\r\n", VidOTDesc->bSourceID); - AppendTextBuffer("iTerminal: 0x%02X\r\n", VidOTDesc->iTerminal); - if (gDoAnnotation) - { - if (VidOTDesc->iTerminal) - { - // if executing this code, the configuration descriptor has been - // obtained. If a device is suspended, then its configuration - // descriptor was not obtained and we do not want errors to be - // displayed when string descriptors were not obtained. - DisplayStringDescriptor(VidOTDesc->iTerminal, StringDescs, LatestDevicePowerState); - } - } - - if (VidOTDesc->bLength < sizeof(PVIDEO_OUTPUT_TERMINAL)) - { - //@@TestCase B4.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is less than required length in - //@@ the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d is too small\r\n", VidOTDesc->bLength); - OOPS(); - } - - if (VidOTDesc->bTerminalID < 1) - { - //@@TestCase B4.2 (see Descript.c line 328) - //@@ERROR - //@@Descriptor Field - bTerminalID - //@@bTerminalID should be greater than 0 - //@@Question: Should test to verify terminal number is valid - AppendTextBuffer("*!*ERROR: bTerminalID of %d is too small\r\n", VidOTDesc->bTerminalID); - OOPS(); - } - - - if (!(pStr)) - { - //@@TestCase B4.3 - //@@ERROR - //@@Descriptor Field - wTerminalType - //@@No valid Terminal Type was found - AppendTextBuffer("*!*ERROR: 0x%04X is an invalid wTerminalType for an Output Terminal\r\n", - VidOTDesc->wTerminalType); - OOPS(); - } - - //@@TestCase B4.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bAssocTerminal - //@@We should test to verify terminal number is valid - // AppendTextBuffer("bAssocTerminal: 0x%02X\r\n", VidOTDesc->bAssocTerminal); - - if (VidOTDesc->bSourceID < 1) - { - //@@TestCase B4.5 (see Descript.c line 333) - //@@ERROR - //@@Descriptor Field - bSourceID - //@@bSourceID should be greater than 0 - //@@Question: Should test to verify source number is valid - AppendTextBuffer("*!*ERROR: bSourceID of %d is too small\r\n", VidOTDesc->bSourceID); - OOPS(); - } - - switch (VidOTDesc->wTerminalType) - { - case 0x0100: // TT_VENDOR_SPECIFIC Terminal Type - break; - case 0x0101: // TT_STREAMING Terminal Type - break; - case 0x0300: // OTT_VENDOR_SPECIFIC Terminal Type - break; - case 0x0301: // OTT_DISPLAY Terminal Type - break; - case 0x0302: // OTT_MEDIA_TRANSPORT_OUTPUT Terminal Type - return DisplayVCMediaTransOutputTerminal( - (PVIDEO_OUTPUT_MTT)VidOTDesc); - case 0x0400: // EXTERNAL_VENDOR_SPECIFIC Terminal Type - break; - case 0x0401: // COMPOSITE_CONNECTOR Terminal Type - break; - case 0x0402: // SVIDEO_CONNECTOR Terminal Type - break; - case 0x0403: // COMPONENT_CONNECTOR Terminal Type - break; - default: - break; - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCMediaTransInputTerminal() -// -//***************************************************************************** - -BOOL -DisplayVCMediaTransInputTerminal( - PVIDEO_INPUT_MTT MediaTransportInDesc - ) -{ - //@@DisplayVCMediaTransInputTerminal -Video Control Media Transport Input Terminal - UCHAR p = 0; - PUCHAR pData = NULL; - size_t bLength = 0; - - bLength = SizeOfVideoInputMTT(MediaTransportInDesc); - - AppendTextBuffer("===>Additional Media Transport Input Terminal Data\r\n"); - AppendTextBuffer("bControlSize: 0x%02X\r\n", - MediaTransportInDesc->bControlSize); - - // point to bControlSize - pData = & MediaTransportInDesc->bControlSize; - - // Are there any controls? - if (0 < * pData) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 1); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportControls, - sizeof(slMediaTransportControls) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportCtrl bmControl value")); - - cMask = cMask << 1; - } - } - - // point to bTransportModeSize - pData = pData + 2 ; - - // Are there any controls? - if (0 < * pData) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 1); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes1, - sizeof(slMediaTransportModes1) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - - // Is there a second control? - if (1 < * pData) - { - // map the second control - for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 2); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes2, - sizeof(slMediaTransportModes2) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - // Is there a third control? - if (2 < * pData) - { - // map the third control - for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 3); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes3, - sizeof(slMediaTransportModes3) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - // Is there a fourth control? - if (3 < * pData) - { - // map the fourth control - for ( uBitIndex = 24, cMask = 1; uBitIndex < 32; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 4); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes4, - sizeof(slMediaTransportModes4) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - // Is there a fifth control? - if (4 < * pData) - { - // map the fifth control - for ( uBitIndex = 32, cMask = 1; uBitIndex < 40; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 5); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes5, - sizeof(slMediaTransportModes5) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - } - - // The size of a Media Transport Descriptor is - // the size of the Descriptor plus - // (bControlSize - 1) plus - // IF bmControls & 1 THEN 1 (bTransportModeSize) plus - // bTransportModeSize - // -// p = sizeof(VIDEO_INPUT_MTT) + -// (MediaTransportInDesc->bControlSize - 1); -// if (MediaTransportInDesc->bmControls[0] & 1) -// p += 1 + (*pData); - if (MediaTransportInDesc->bLength != bLength) - { - //@@TestCase B5.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@Invalid Descriptor length - AppendTextBuffer("*!*ERROR: Invalid descriptor bLength 0x%02X. "\ - "Should be 0x%02X\r\n", - MediaTransportInDesc->bLength, p); - OOPS(); - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCMediaTransOutputTerminal() -// -//***************************************************************************** - -BOOL -DisplayVCMediaTransOutputTerminal( - PVIDEO_OUTPUT_MTT MediaTransportOutDesc - ) -{ - //@@DisplayVCMediaTransOutputTerminal -Video Control Media Transport Output Terminal - UCHAR p = 0; - PUCHAR pData = NULL; - - AppendTextBuffer("===>Additional Media Transport Output Terminal Data\r\n"); - AppendTextBuffer("bControlSize: 0x%02X\r\n", - MediaTransportOutDesc->bControlSize); - - // point to bControlSize - pData = & MediaTransportOutDesc->bControlSize; - - // Are there any controls? - if (0 < * pData) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 1); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportControls, - sizeof(slMediaTransportControls) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportCtrl bmControl value")); - - cMask = cMask << 1; - } - } - - // point to bTransportModeSize - pData = pData + 2 ; - - // Are there any controls? - if (0 < * pData) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 1); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes1, - sizeof(slMediaTransportModes1) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - - // Is there a second control? - if (1 < * pData) - { - // map the second control - for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 2); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes2, - sizeof(slMediaTransportModes2) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - // Is there a third control? - if (2 < * pData) - { - // map the third control - for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 3); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes3, - sizeof(slMediaTransportModes3) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - // Is there a fourth control? - if (3 < * pData) - { - // map the fourth control - for ( uBitIndex = 24, cMask = 1; uBitIndex < 32; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 4); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes4, - sizeof(slMediaTransportModes4) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - // Is there a fifth control? - if (4 < * pData) - { - // map the fourth control - for ( uBitIndex = 32, cMask = 1; uBitIndex < 40; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 5); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slMediaTransportModes5, - sizeof(slMediaTransportModes5) / sizeof(STRINGLIST), - cMask, - "Invalid MediaTransportMode value")); - - cMask = cMask << 1; - } - } - } - - // The size of a Media Transport Descriptor is - // the size of the Descriptor plus - // (bControlSize - 1) plus - // IF bmControls & 1 THEN 1 (bTransportModeSize) plus - // bTransportModeSize - // - p = sizeof(VIDEO_OUTPUT_MTT) + - (MediaTransportOutDesc->bControlSize - 1); - if (MediaTransportOutDesc->bmControls[0] & 1) - p += 1 + (*pData); - if (MediaTransportOutDesc->bLength != p) - { - //@@TestCase B5.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@Invalid Descriptor length - AppendTextBuffer("*!*ERROR: Invalid descriptor bLength 0x%02X. "\ - "Should be 0x%02X\r\n", - MediaTransportOutDesc->bLength, p); - OOPS(); - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCCameraTerminal() -// -//***************************************************************************** - -BOOL -DisplayVCCameraTerminal( - PVIDEO_CAMERA_TERMINAL CameraDesc - ) -{ - //@@DisplayVCCameraTerminal -Video Control Camera Terminal - UCHAR p = 0; - PUCHAR pData = NULL; - - AppendTextBuffer("===>Camera Input Terminal Data\r\n"); - AppendTextBuffer("wObjectiveFocalLengthMin: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMin); - AppendTextBuffer("wObjectiveFocalLengthMax: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMax); - AppendTextBuffer("wOcularFocalLength: 0x%04X\r\n", CameraDesc->wOcularFocalLength); - AppendTextBuffer("bControlSize: 0x%02X\r\n", CameraDesc->bControlSize); - - pData = &CameraDesc->bControlSize; - - // Are there any controls? - if (0 < * pData) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 1); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slCameraControl1, - sizeof(slCameraControl1) / sizeof(STRINGLIST), - cMask, - "Invalid CamCtrl bmControl value")); - - cMask = cMask << 1; - } - - // Is there a second control? - if (1 < * pData) - { - // map the second control - for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 2); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slCameraControl2, - sizeof(slCameraControl2) / sizeof(STRINGLIST), - cMask, - "Invalid CamCtrl bmControl value")); - - cMask = cMask << 1; - } - } - // Is there a third control? - if (2 < * pData) - { - // map the third control - for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 3); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slCameraControl3, - sizeof(slCameraControl3) / sizeof(STRINGLIST), - cMask, - "Invalid CamCtrl bmControl value")); - - cMask = cMask << 1; - } - } - } - - p = (sizeof(VIDEO_CAMERA_TERMINAL) + CameraDesc->bControlSize); - if (CameraDesc->bLength != p) - { - //@@TestCase B7.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The descriptor should be the size of the descriptor structure - //@@ plus the number of controls - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - CameraDesc->bLength, p); - OOPS(); - } - - //@@TestCase B7.2 - //@@Not yet implemented - Priority 3 - //@@Descriptor Field - wObjectiveFocalLengthMin - //@@Question - Should we do any checking here? What are the acceptable boundaries? - //@@Question - Is zero an acceptable value? - // AppendTextBuffer("wObjectiveFocalLengthMin: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMin); - - //@@TestCase B7.3 - //@@Not yet implemented - Priority 3 - //@@Descriptor Field - wObjectiveFocalLengthMax - //@@Question - Should we do any checking here? What are the acceptable boundaries - //@@Question - Is zero an acceptable value? - // AppendTextBuffer("wObjectiveFocalLengthMax: 0x%04X\r\n", CameraDesc->wObjectiveFocalLengthMax); - - //@@TestCase B7.4 - //@@Not yet implemented - Priority 3 - //@@Descriptor Field - wOcularFocalLength - //@@Question - Should we do any checking here? What are the acceptable boundaries - //@@Question - Is zero an acceptable value? - // AppendTextBuffer("wOcularFocalLength: 0x%04X\r\n", CameraDesc->wOcularFocalLength); - - //@@TestCase B7.5 - //@@ERROR - //@@Descriptor Field - wObjectiveFocalLengthMin and wObjectiveFocalLengthMax - //@@Verify that wObjectiveFocalLengthMax is greater than wObjectiveFocalLengthMin - if(CameraDesc->wObjectiveFocalLengthMin > CameraDesc->wObjectiveFocalLengthMax) - { - AppendTextBuffer("*!*ERROR: wObjectiveFocalLengthMin is larger than wObjectiveFocalLengthMax\r\n"); - OOPS(); - } - - //@@TestCase B7.6 - //@@ERROR - //@@Descriptor Field - bControlSize - //@@Verify that wObjectiveFocalLengthMax is 3 or less - if(CameraDesc->bControlSize > 3) - { - AppendTextBuffer("*!*ERROR: bControlSize must be 3 or less\r\n"); - OOPS(); - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayVCSelectorUnit() -// -//***************************************************************************** - -BOOL -DisplayVCSelectorUnit ( - PVIDEO_SELECTOR_UNIT VidSelectorDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayVCSelectorUnit -Video Control Selector Unit - UCHAR i = 0; - UCHAR p = 0; - PUCHAR pData = NULL; - - AppendTextBuffer("\r\n ===>Video Control Selector Unit Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VidSelectorDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidSelectorDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidSelectorDesc->bDescriptorSubtype); - AppendTextBuffer("bUnitID: 0x%02X\r\n", VidSelectorDesc->bUnitID); - AppendTextBuffer("bNrInPins: 0x%02X\r\n", VidSelectorDesc->bNrInPins); - if (gDoAnnotation) - { - AppendTextBuffer("===>List of Connected Unit and Terminal ID's\r\n"); - } - // baSourceID is a variable length field - // Size is in bNrInPins, must be at least 1 (so index starts at 1) - for (i = 1, pData = (PUCHAR) &VidSelectorDesc->baSourceID; - i <= VidSelectorDesc->bNrInPins; i++, pData++) - { - AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", - i, *pData); - } - - // get address of iSelector, the last field in this descriptor - pData = (PUCHAR) VidSelectorDesc + (VidSelectorDesc->bLength - 1); - AppendTextBuffer("iSelector: 0x%02X\r\n", *pData); - if (gDoAnnotation) - { - if (*pData) - { - // if executing this code, the configuration descriptor has been - // obtained. If a device is suspended, then its configuration - // descriptor was not obtained and we do not want errors to be - // displayed when string descriptors were not obtained. - DisplayStringDescriptor(*pData, StringDescs, LatestDevicePowerState); - } - } - - p = (sizeof(VIDEO_SELECTOR_UNIT) + VidSelectorDesc->bNrInPins + 1); - if (VidSelectorDesc->bLength != p) - { - //@@TestCase B8.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The descriptor should be the size of the descriptor structure plus the number of pins - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - VidSelectorDesc->bLength, p); - OOPS(); - } - - if (VidSelectorDesc->bUnitID < 1) - { - //@@TestCase B8.2 (Descript.c Line 396) - //@@ERROR - //@@Descriptor Field - bUnitID - //@@bUnitID must be greater than 0 - //@@Question: Should we test to verify unit number is unique? - AppendTextBuffer("*!*ERROR: bUnitID must be non-zero\r\n"); - OOPS(); - } - - if (VidSelectorDesc->bNrInPins < 1) - { - //@@TestCase B8.3 - //@@ERROR - //@@Descriptor Field - bNrInPins - //@@bNrInPins should be greater than 0 - //@@Question: Should test to verify total in pins is valid - AppendTextBuffer("*!*ERROR: bNrInPins must be non-zero\r\n"); - OOPS(); - } - - // baSourceID is a variable length field - // Size is in bNrInPins, must be at least 1 (so index starts at 1) - for (i = 1, pData = (PUCHAR) &VidSelectorDesc->baSourceID; - i <= VidSelectorDesc->bNrInPins; i++, pData++) - { - if (*pData < 1) - { - //@@TestCase B8.4 - //@@ERROR - //@@Descriptor Field - baSourceID[] - //@@baSourceID should be greater than 0 - AppendTextBuffer("*!*ERROR: baSourceID[%d] must be non-zero\r\n", i); - OOPS(); - } else { - if (! ValidateTerminalID(*pData)) { - //@@TestCase B8.5 - //@@ERROR - //@@Descriptor Field - baSourceID[] - //@@baSourceID should be a valid terminal ID - AppendTextBuffer("*!*ERROR: baSourceID[%d] must be non-zero\r\n", i); - OOPS(); - } - } - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCProcessingUnit() -// -//***************************************************************************** - -BOOL -DisplayVCProcessingUnit ( - PVIDEO_PROCESSING_UNIT VidProcessingDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayVCProcessingUnit -Video Control Processor Unit - PUCHAR pData = NULL; - UCHAR bLength = 0; - - AppendTextBuffer("\r\n ===>Video Control Processing Unit Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VidProcessingDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidProcessingDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidProcessingDesc->bDescriptorSubtype); - AppendTextBuffer("bUnitID: 0x%02X\r\n", VidProcessingDesc->bUnitID); - AppendTextBuffer("bSourceID: 0x%02X\r\n", VidProcessingDesc->bSourceID); - AppendTextBuffer("wMaxMultiplier: 0x%04X\r\n", VidProcessingDesc->wMaxMultiplier); - AppendTextBuffer("bControlSize: 0x%02X\r\n", VidProcessingDesc->bControlSize); - - pData = &VidProcessingDesc->bControlSize; - - // Are there any controls? - if (0 < * pData) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 1); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slProcessorControls1, - sizeof(slProcessorControls1) / sizeof(STRINGLIST), - cMask, - "Invalid PU bmControl value")); - - cMask = cMask << 1; - } - - // Is there a second control? - if (1 < * pData) - { - // map the second control - for ( uBitIndex = 8, cMask = 1; uBitIndex < 16; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 2); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slProcessorControls2, - sizeof(slProcessorControls2) / sizeof(STRINGLIST), - cMask, - "Invalid PU bmControl value")); - - cMask = cMask << 1; - } - } - - // Is there a third control? - if (2 < * pData) - { - // map the third control - for ( uBitIndex = 16, cMask = 1; uBitIndex < 24; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + 3); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slProcessorControls3, - sizeof(slProcessorControls3) / sizeof(STRINGLIST), - cMask, - "Invalid PU bmControl value")); - - cMask = cMask << 1; - } - } - } - - // get address of iProcessing - if (UVC10 != g_chUVCversion) - { - // size of descriptor is struct size plus control size plus 2 if UVC11 - bLength = sizeof(VIDEO_PROCESSING_UNIT) + 2 + VidProcessingDesc->bControlSize; - pData = (PUCHAR) VidProcessingDesc + (VidProcessingDesc->bLength - 2); - } - else // UVC 1.0 - { - // size of descriptor is struct size plus control size plus 1 if UVC10 - bLength = sizeof(VIDEO_PROCESSING_UNIT) + 1 + VidProcessingDesc->bControlSize; - pData = (PUCHAR) VidProcessingDesc + (VidProcessingDesc->bLength - 1); - } - AppendTextBuffer("iProcessing : 0x%02X\r\n", *pData); - if (gDoAnnotation) - { - if (*pData) - { - // if executing this code, the configuration descriptor has been - // obtained. If a device is suspended, then its configuration - // descriptor was not obtained and we do not want errors to be - // displayed when string descriptors were not obtained. - DisplayStringDescriptor(*pData, StringDescs, LatestDevicePowerState); - } - } - - // check for new UVC 1.1 bmVideoStandards fields - if (UVC10 != g_chUVCversion) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - pData = (PUCHAR) VidProcessingDesc + (VidProcessingDesc->bLength - 1); - - AppendTextBuffer("bmVideoStandards : "); - VDisplayBytes(pData, 1); - - // map the first control - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slProcessorVideoStandards, - sizeof(slProcessorVideoStandards) / sizeof(STRINGLIST), - cMask, - "Invalid PU bmVideoStandards value")); - - cMask = cMask << 1; - } - } - - if (VidProcessingDesc->bLength != bLength) - { - //@@TestCase B9.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - AppendTextBuffer("*!*ERROR: bLength of 0x%02X incorrect, should be 0x%02X\r\n", - VidProcessingDesc->bLength, bLength); - OOPS(); - } - - if (VidProcessingDesc->bUnitID < 1) - { - //@@TestCase B9.2 (Descript.c Line 466) - //@@ERROR - //@@Descriptor Field - bUnitID - //@@bUnitID must be greater than 0 - //@@Question: Should we test to verify unit number is unique? - AppendTextBuffer("*!*ERROR: bUnitID must be non-zero\r\n"); - OOPS(); - } - - if (VidProcessingDesc->bSourceID < 1) - { - //@@TestCase B9.3 (Descript.c Line 471) - //@@ERROR - //@@Descriptor Field - bSourceID - //@@bSourceID must be non-zero - //@@Question: Should we test to verify the bSourceID is valid? - AppendTextBuffer("*!*ERROR: bSourceID must be non-zero\r\n"); - OOPS(); - } - - //@@TestCase B9.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - wMaxMultiplier - //@@We should test to verify multiplier is valid - // AppendTextBuffer("wMaxMultiplier: 0x%04X\r\n", VidProcessingDesc->wMaxMultiplier); - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCExtensionUnit() -// -//***************************************************************************** - -BOOL -DisplayVCExtensionUnit ( - PVIDEO_EXTENSION_UNIT VidExtensionDesc, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ) -{ - //@@DisplayVCExtensionUnit -Video Control Extension Unit - int i = 0; - UCHAR p = 0; - UCHAR bControlSize = 0; - PUCHAR pData = NULL; - OLECHAR szGUID[256]; - size_t bLength = 0; - - bLength = SizeOfVideoExtensionUnit(VidExtensionDesc); - - memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); - i = StringFromGUID2((REFGUID) &VidExtensionDesc->guidExtensionCode, (LPOLESTR) szGUID, 255); - i++; - - AppendTextBuffer("\r\n ===>Video Control Extension Unit Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VidExtensionDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidExtensionDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidExtensionDesc->bDescriptorSubtype); - AppendTextBuffer("bUnitID: 0x%02X\r\n", VidExtensionDesc->bUnitID); - AppendTextBuffer("guidExtensionCode: %S\r\n", szGUID); - AppendTextBuffer("bNumControls: 0x%02X\r\n", VidExtensionDesc->bNumControls); - AppendTextBuffer("bNrInPins: 0x%02X\r\n", VidExtensionDesc->bNrInPins); - if (gDoAnnotation) - { - AppendTextBuffer("===>List of Connected Units and Terminal ID's\r\n"); - } - // baSourceID is a variable length field - // Size is in bNrInPins, must be at least 1 (so index starts at 1) - for (i = 1, pData = (PUCHAR) &VidExtensionDesc->baSourceID; - i <= VidExtensionDesc->bNrInPins; i++, pData++) - { - AppendTextBuffer("baSourceID[%d]: 0x%02X\r\n", - i, *pData); - } - // point to bControlSize (address of bNrInPins plus number of fields in bNrInPins - // plus 1 for next field) - pData = &VidExtensionDesc->bNrInPins + VidExtensionDesc->bNrInPins +1; - bControlSize = *pData; - AppendTextBuffer("bControlSize: 0x%02X\r\n", bControlSize); - - // Are there any controls? - if ( bControlSize > 0) - { - AppendTextBuffer("bmControls : "); - VDisplayBytes(pData + 1, *pData); - - // Map one byte at a time of the bmControls field in the Video Control Extension Unit Descriptor - for (i = 1; i <= bControlSize; i++) - { - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - // map byte - for ( ; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData + i); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex + 8 * (i-1), - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - "Vendor-Specific (Optional)"); - - cMask = cMask << 1; - } - } - } - - // get address of iExtension - pData = &VidExtensionDesc->bNrInPins + VidExtensionDesc->bNrInPins + bControlSize + 2; -// pData = (PUCHAR) VidExtensionDesc + (VidExtensionDesc->bLength - 1); - AppendTextBuffer("iExtension: 0x%02X\r\n", *pData); - if (gDoAnnotation) - { - if (*pData) - { - DisplayStringDescriptor(*pData,StringDescs, LatestDevicePowerState); - } - } - - // size of descriptor struct size (23) + bNrInPins + bControlSize + iExtension size - // -// p = (sizeof(VIDEO_EXTENSION_UNIT) -// + VidExtensionDesc->bNrInPins + bControlSize + 1); - if (VidExtensionDesc->bLength != bLength) - { - //@@TestCase B10.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@ required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of 0x%02X incorrect, should be 0x%02X\r\n", - VidExtensionDesc->bLength, p); - OOPS(); - } - - if (VidExtensionDesc->bUnitID < 1) - { - //@@TestCase B10.2 (Descript.c Line 517) - //@@ERROR - //@@Descriptor Field - bUnitID - //@@bUnitID must be non-zero - //@@Question: Should we test to verify bUnitID is valid - AppendTextBuffer("*!*ERROR: bUnitID must be non-zero\r\n"); - OOPS(); - } - - //bugbug do we need two - if (VidExtensionDesc->bNrInPins < 1) - { - //@@TestCase B10.3 (Descript.c Line 522) - //@@ERROR - //@@Descriptor Field - bNrInPins - //@@bNrInPins must be non-zero - //@@Question: Should we test to verify bNrInPins is valid - AppendTextBuffer("*!*ERROR: bNrInPins must be non-zero\r\n"); - OOPS(); - } - - for (i = 1, pData = (PUCHAR) &VidExtensionDesc->baSourceID; - i <= VidExtensionDesc->bNrInPins; i++, pData++) - { - if (*pData == 0) - { - //@@TestCase B10.4 (Descript.c Line 527) - //@@ERROR - //@@Descriptor Field - baSourceID[] - //@@baSourceID[] must be non-zero - //@@Question: Should we test to verify baSourceID is valid - AppendTextBuffer("*!*ERROR: baSourceID[%d] must be non-zero\r\n", *pData); - OOPS(); - } - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayVidInHeaderl() -// -//***************************************************************************** - -BOOL -DisplayVidInHeader ( - PVIDEO_STREAMING_INPUT_HEADER VidInHeaderDesc - ) -{ - //@@DisplayVidInHeader -Video Streaming Video Input Header - UINT p = 0; - UINT uCount = 0; - PUCHAR pData = NULL; - - AppendTextBuffer("\r\n ===>Video Class-Specific VS Video Input Header Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VidInHeaderDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidInHeaderDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidInHeaderDesc->bDescriptorSubtype); - AppendTextBuffer("bNumFormats: 0x%02X\r\n", VidInHeaderDesc->bNumFormats); - AppendTextBuffer("wTotalLength: 0x%04X", VidInHeaderDesc->wTotalLength); - - uCount = GetVSInterfaceSize((PUSB_COMMON_DESCRIPTOR) VidInHeaderDesc, VidInHeaderDesc->wTotalLength); - if (uCount != VidInHeaderDesc->wTotalLength) { - AppendTextBuffer("\r\n*!*ERROR: invalid interface size 0x%02X, should be 0x%02X\r\n", - VidInHeaderDesc->wTotalLength, uCount); - } else { - AppendTextBuffer(" -> Validated\r\n"); - } - - AppendTextBuffer("bEndpointAddress: 0x%02X", - VidInHeaderDesc->bEndpointAddress); - if (USB_ENDPOINT_DIRECTION_IN(VidInHeaderDesc->bEndpointAddress)) - { - if (gDoAnnotation) - { - AppendTextBuffer(" -> Direction: IN - EndpointID: %d", - (VidInHeaderDesc->bEndpointAddress & 0x0F)); - } - AppendTextBuffer("\r\n"); - } - AppendTextBuffer("bmInfo: 0x%02X", VidInHeaderDesc->bmInfo); - if (gDoAnnotation) - { - AppendTextBuffer(" -> Dynamic Format Change %sSupported", - ! (VidInHeaderDesc->bmInfo & 0x01) ? "not " : " "); - } - AppendTextBuffer("\r\nbTerminalLink: 0x%02X\r\n", - VidInHeaderDesc->bTerminalLink); - AppendTextBuffer("bStillCaptureMethod: 0x%02X", - VidInHeaderDesc->bStillCaptureMethod); - - // globally save the StillMethod, then verify value - StillMethod = VidInHeaderDesc->bStillCaptureMethod; - if (StillMethod > 3) - { - //@@TestCase B11.1 (Descript.c Line 798) - //@@ERROR - //@@Descriptor Field - bStillCaptureMethod - //@@bStillCaptureMethod is greater than 3 - AppendTextBuffer("*!*ERROR: invalid bStillCaptureMethod 0x%02X\r\n", - VidInHeaderDesc->bStillCaptureMethod); - if (gDoAnnotation) - { - AppendTextBuffer(" -> Invalid Still Capture Method"); - } - } - else - { - if (0 == StillMethod) - { - AppendTextBuffer(" -> No Still Capture"); - } - else - { - AppendTextBuffer(" -> Still Capture Method %d", - VidInHeaderDesc->bStillCaptureMethod); - } - } - - AppendTextBuffer("\r\nbTriggerSupport: 0x%02X", - VidInHeaderDesc->bTriggerSupport); - if(gDoAnnotation) - { - AppendTextBuffer(" -> "); - if (! VidInHeaderDesc->bTriggerSupport) - AppendTextBuffer("No "); - AppendTextBuffer("Hardware Triggering Support"); - } - AppendTextBuffer("\r\n"); - - AppendTextBuffer("bTriggerUsage: 0x%02X", - VidInHeaderDesc->bTriggerUsage); - if (gDoAnnotation) - { - if (VidInHeaderDesc->bTriggerSupport != 0) - { - if (VidInHeaderDesc->bTriggerUsage == 0) - AppendTextBuffer(" -> Host will initiate still image capture"); - if (VidInHeaderDesc->bTriggerUsage == 1) - AppendTextBuffer(" -> Host will notify client application of button event"); - } - } - - AppendTextBuffer("\r\nbControlSize: 0x%02X\r\n", - VidInHeaderDesc->bControlSize); - - // are there formats to display? - if (VidInHeaderDesc->bNumFormats) - { - UINT uFormatIndex = 1; - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - // There are (bNumFormats) bmaControls fields, each with size (bControlSize) - pData = (PUCHAR) &(VidInHeaderDesc->bControlSize); - - // VidInHeaderDesc->bNumFormats -> number of formats - // VidInHeaderDesc->bControlSize -> size of EACH format control - // ((PUCHAR) &VidInHeaderDesc->bControlSize) + 1 -> address of first format control - for ( pData++ ; uFormatIndex <= VidInHeaderDesc->bNumFormats; uFormatIndex++ ) - { - AppendTextBuffer("Video Payload Format %d ", uFormatIndex); - - // Handle case of 0 control size - if (! VidInHeaderDesc->bControlSize) - { - AppendTextBuffer("0x00\r\n"); - } - else - { - VDisplayBytes(pData, VidInHeaderDesc->bControlSize); - - // map the first control - for (uBitIndex = 0, cMask = 1; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pData); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slInputHeaderControls, - sizeof(slInputHeaderControls) / sizeof(STRINGLIST), - cMask, - "Invalid Control value")); - - cMask = cMask << 1; - } - } - pData += VidInHeaderDesc->bControlSize; - } - } - - p = (sizeof(VIDEO_STREAMING_INPUT_HEADER) + - (VidInHeaderDesc->bNumFormats * VidInHeaderDesc->bControlSize)); - if (VidInHeaderDesc->bLength != p) - { - //@@TestCase B11.2 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The descriptor should be the size of the descriptor structure - //@@ plus the number of formats times the size of each format - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - VidInHeaderDesc->bLength, p); - OOPS(); - } - - if (VidInHeaderDesc->bNumFormats < 1) - { - //@@TestCase B11.3 (Descript.c Line778) - //@@ERROR - //@@Descriptor Field - bNumFormats - //@@bNumFormats must be non-zero - //@@Question: Should we test to verify the non-zero value for bNumFormats is valid - AppendTextBuffer("*!*ERROR: bNumFormats must be non-zero\r\n", - VidInHeaderDesc->bNumFormats); - OOPS(); - } - - if (VidInHeaderDesc->bEndpointAddress < 1) - { - //@@TestCase B11.4 (Descript.c Line788) - //@@ERROR - //@@Descriptor Field - bEndpointAddress - //@@bEndpointAddress should be greater than 0 - //@@Question: Should we test to verify the non-zero value for bEndpointAddress is valid - AppendTextBuffer("*!*ERROR: bEndpointAddress of %d is too small\r\n", - VidInHeaderDesc->bEndpointAddress); - OOPS(); - } - - //@@TestCase B11.5 - //@@ERROR - //@@Descriptor Field - bEndPointAddress - //@@The bEndPointAddress is set incorrectly according to the USB Video Device Specification - if (!USB_ENDPOINT_DIRECTION_IN(VidInHeaderDesc->bEndpointAddress)){ - AppendTextBuffer("\r\n*!*ERROR: bEndPointAddress needs to have the Direction IN for this header\r\n"); - OOPS();} - - //@@TestCase B11.6 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bmInfo - //@@We should validate that reserved bits are set to zero. - // AppendTextBuffer("bmInfo: 0x%02X", VidInHeaderDesc->bmInfo); - - if (VidInHeaderDesc->bTerminalLink < 1) - { - //@@TestCase B11.7 (Descript.c Line 793) - //@@ERROR - //@@Descriptor Field - bTerminalLink - //@@bTerminalLink should be greater than 0 - //@@Question: Should we test to verify the non-zero value for bTerminalLink is valid - AppendTextBuffer("*!*ERROR: bTerminalLink of %d is too small\r\n", - VidInHeaderDesc->bTerminalLink); - OOPS(); - } - - //@@TestCase B11.8 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bTriggerSupport - //@@We should validate that reserved bits are set to zero. - // AppendTextBuffer("bTriggerSupport: 0x%02X", VidInHeaderDesc->bTriggerSupport); - - //@@TestCase B11.9 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bTriggerUsage - //@@We should validate that reserved bits are set to zero. - // AppendTextBuffer("bTriggerUsage: 0x%02X", VidInHeaderDesc->bTriggerUsage); - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVidOutHeader() -// -//***************************************************************************** - -BOOL -DisplayVidOutHeader ( - PVIDEO_STREAMING_OUTPUT_HEADER VidOutHeaderDesc - ) -{ - //@@DisplayVidOutHeader -Video Streaming Video Output Header - UINT uCount = 0; - UCHAR bLength = sizeof(VIDEO_STREAMING_OUTPUT_HEADER); - - AppendTextBuffer("\r\n ===>Video Class-Specific VS Video Output Header Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VidOutHeaderDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidOutHeaderDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidOutHeaderDesc->bDescriptorSubtype); - AppendTextBuffer("bNumFormats: 0x%02X\r\n", VidOutHeaderDesc->bNumFormats); - AppendTextBuffer("wTotalLength: 0x%04X", VidOutHeaderDesc->wTotalLength); - - uCount = GetVSInterfaceSize((PUSB_COMMON_DESCRIPTOR) VidOutHeaderDesc, VidOutHeaderDesc->wTotalLength); - if (uCount != VidOutHeaderDesc->wTotalLength) { - AppendTextBuffer("\r\n*!*ERROR: invalid interface size 0x%02X, should be 0x%02X\r\n", - VidOutHeaderDesc->wTotalLength, uCount); - } else { - AppendTextBuffer(" -> Validated\r\n"); - } - - AppendTextBuffer("bEndpointAddress: 0x%02X", VidOutHeaderDesc->bEndpointAddress); - if(USB_ENDPOINT_DIRECTION_OUT(VidOutHeaderDesc->bEndpointAddress)) { - if (gDoAnnotation) - { - AppendTextBuffer(" -> Direction: OUT - EndpointID: %d", - (VidOutHeaderDesc->bEndpointAddress & 0x0F)); - } - AppendTextBuffer("\r\n"); - } - AppendTextBuffer("bTerminalLink: 0x%02X\r\n", VidOutHeaderDesc->bTerminalLink); - - // UVC11 Video Output Header has additional fields, larger size -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) -#else - if (UVC11 == g_chUVCversion) -#endif - { - UCHAR bControlSize = 0; - PUCHAR pControls = NULL; - - // bControlSize field is next after bTerminalLink - pControls = &(VidOutHeaderDesc->bTerminalLink)+1; - bControlSize = *(pControls); - // point to first bmaControls - pControls++; - - // Size of UVC 1.1 Video Output Header is 1.0 size - // plus 1 (bControlSize field) plus (number of formats * bControlSize) - bLength += 1 + (VidOutHeaderDesc->bNumFormats * bControlSize); - - // Need new uvcdesc.h to handle new fields - AppendTextBuffer("bControlSize: 0x%02X\r\n", bControlSize); - - // are there formats to display? - if (VidOutHeaderDesc->bNumFormats) - { - UINT uFormatIndex = 1; - UINT uBitIndex = 0; - BYTE cCheckBit = 0; - BYTE cMask = 1; - - // There are (bNumFormats) bmaControls fields, each with size (bControlSize) - for ( ; uFormatIndex <= VidOutHeaderDesc->bNumFormats; uFormatIndex++, pControls ++) - { - AppendTextBuffer("Video Payload Format %d ", uFormatIndex); - - // Handle case of 0 control size - if (0 == bControlSize) - { - AppendTextBuffer("0x00\r\n"); - } - else - { - VDisplayBytes(pControls, bControlSize); - - // map the first control - for (uBitIndex = 0, cMask = 1; uBitIndex < 8; uBitIndex++ ) - { - cCheckBit = cMask & *(pControls); - - AppendTextBuffer(" D%02d = %d %s %s\r\n", - uBitIndex, - cCheckBit ? 1 : 0, - cCheckBit ? "yes - " : " no - ", - GetStringFromList(slOutputHeaderControls, - sizeof(slOutputHeaderControls) / sizeof(STRINGLIST), - cMask, - "Invalid control value")); - - cMask = cMask << 1; - } - } - } // for ( pData++ ; uFormatIndex <= VidOutHeaderDesc->bNumFormats; uFormatIndex++ ) - } // if (VidOutHeaderDesc->bNumFormats) - } // if (UVC11 == g_chUVCversion) - - if (VidOutHeaderDesc->bLength != bLength) - { - //@@TestCase B12.1 (also in Descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@ required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - VidOutHeaderDesc->bLength, - sizeof(VIDEO_STREAMING_OUTPUT_HEADER)); - OOPS(); - } - - if (VidOutHeaderDesc->bNumFormats < 1) - { - //@@TestCase B12.2 (Descript.c Line 827) - //@@ERROR - //@@Descriptor Field - bNumFormats - //@@bNumFormats should be greater than 0 - //@@Question: Should we test to verify the non-zero value for bNumFormats is valid - AppendTextBuffer("*!*ERROR: bNumFormats of %d is too small\r\n", - VidOutHeaderDesc->bNumFormats); - OOPS(); - } - - if (VidOutHeaderDesc->wTotalLength < VidOutHeaderDesc->bLength) - { - //@@TestCase B12.3 (Descript.c Line 832) - //@@ERROR - //@@Descriptor Field - wTotalLength - //@@wTotalLength should be greater than bLength - //@@Question: Should we calculate wTotalLength to verify the value is valid - AppendTextBuffer("*!*ERROR: wTotalLength of %d is small than the bLength of %d\r\n", - VidOutHeaderDesc->wTotalLength, - VidOutHeaderDesc->bLength); - OOPS(); - } - - if (VidOutHeaderDesc->bEndpointAddress < 1) - { - //@@TestCase B12.4 (Descript.c Line 837) - //@@ERROR - //@@Descriptor Field - bEndpointAddress - //@@bEndpointAddress should be greater than 0 - //@@Question: Should we test to verify the non-zero value for bEndpointAddress is valid - AppendTextBuffer("*!*ERROR: bEndpointAddress of %d is too small\r\n", - VidOutHeaderDesc->bEndpointAddress); - OOPS(); - } - - if(!(USB_ENDPOINT_DIRECTION_OUT(VidOutHeaderDesc->bEndpointAddress))) { - //@@TestCase B12.5 - //@@ERROR - //@@Descriptor Field - bEndPointAddress - //@@The bEndPointAddress is set for the wrong direction - AppendTextBuffer("\r\n*!*ERROR: bEndPointAddress needs to have the Direction OUT for this header\r\n"); - OOPS();} - - if (VidOutHeaderDesc->bTerminalLink < 1) - { - //@@TestCase B12.6 (Descript.c Line 842) - //@@ERROR - //@@Descriptor Field - bTerminalLink - //@@bTerminalLink should be greater than 0 - //@@Question: Should we test to verify the non-zero value for bTerminalLink is valid - AppendTextBuffer("*!*ERROR: bTerminalLink of %d is too small\r\n", - VidOutHeaderDesc->bTerminalLink); - OOPS(); - } - - return TRUE; - -} - - -//***************************************************************************** -// -// DisplayStillImageFrame() -// -//***************************************************************************** - -BOOL -DisplayStillImageFrame ( - PVIDEO_STILL_IMAGE_FRAME StillFrameDesc - ) -{ - //@@DisplayStillImageFrame -Still Image Frame - VIDEO_STILL_IMAGE_RECT * pXY; - PUCHAR pbCurr = NULL; - UINT i = 0; - UINT uNumComp = 0; - UINT uSize = 0; - size_t bLength = 0; - - bLength = SizeOfVideoStillImageFrame(StillFrameDesc); - - AppendTextBuffer("\r\n ===>Still Image Frame Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", StillFrameDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", StillFrameDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", StillFrameDesc->bDescriptorSubtype); - AppendTextBuffer("bEndpointAddress: 0x%02X\r\n", StillFrameDesc->bEndpointAddress); - AppendTextBuffer("bNumImageSizePatterns: 0x%02X\r\n", - StillFrameDesc->bNumImageSizePatterns); - if (StillFrameDesc->bNumImageSizePatterns < 1) - { - //@@TestCase B13.1 (also Descript.c Line 886) - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bNumImageSizePatterns - //@@The bNumImageSizePatterns should be greater than 0 - //@@Question: Should we test to verify the non-zero value for bNumImageSizePatterns is valid - AppendTextBuffer("*!*ERROR: bNumImageSizePatterns must be non-zero\r\n"); - OOPS(); - } - - // point to first StillFrameDesc->dwStillImage structure - pXY = (VIDEO_STILL_IMAGE_RECT *) &StillFrameDesc->aStillRect[0]; - - for (i = 1; i <= StillFrameDesc->bNumImageSizePatterns; i++, pXY++) - { - AppendTextBuffer("wWidth[%d]: 0x%04X\r\n", - i, pXY->wWidth); - AppendTextBuffer("wHeight[%d]: 0x%04X\r\n", - i, pXY->wHeight); - } - // point to bNumCompressionPattern field (after variable count field dwStillImage) - pbCurr = (PUCHAR) pXY; - // get number of compression patterns - uNumComp = *pbCurr; - - AppendTextBuffer("bNumCompressionPattern: 0x%02X\r\n", *pbCurr++); - for (i = 1; i <= uNumComp; i++) - { - AppendTextBuffer("bCompression[%d]: 0x%02X\r\n", - i, *pbCurr++); - } - - switch(StillMethod) { - case 0: - //@@TestCase B13.2 - //@@ERROR - //@@Descriptor Field - Still Image Frame Type Descriptor - //@@An still method type has been defined that shouldn't use a Still Image Frame - AppendTextBuffer("*!*ERROR: VS Video Input Header set to "\ - "No Still Method support\r\n"); - OOPS(); - case 1: - //@@TestCase B13.3 - //@@ERROR - //@@Descriptor Field - Still Image Frame Type Descriptor - //@@An still method type has been defined that shouldn't use a Still Image Frame - AppendTextBuffer("*!*ERROR: VS Video Input Header set to "\ - "Still Method One support with a Still Image Frame descriptor\r\n"); - OOPS(); - default: - break;} - - if (StillFrameDesc->bLength != bLength) - { - //@@TestCase B13.4 (Also in descript.c) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is incorrect - AppendTextBuffer("*!*ERROR: bLength 0x%02X incorrect, should be 0x%02X\r\n", - StillFrameDesc->bLength, uSize); - OOPS(); - } - - //@@TestCase B13.5 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bEndpointAddress - //@@Should test to verify endpoint validity - // AppendTextBuffer("bEndpointAddress: 0x%02X", StillFrameDesc->bEndpointAddress); - - if(USB_ENDPOINT_DIRECTION_IN(StillFrameDesc->bEndpointAddress) && StillMethod==3){ - if((StillFrameDesc->bEndpointAddress) == 0){ - //@@TestCase B13.6 - //@@ERROR - //@@Descriptor Field - bEndPointAddress - //@@bEndPointAddress should be non-zero for 0 when using StillMethod 3 - AppendTextBuffer("\r\n*!*ERROR: bEndpointAddress is reported as %d. "\ - "This should be non-zero when using StillMethod 3.\r\n", - (StillFrameDesc->bEndpointAddress)); - OOPS(); } - if (gDoAnnotation) - { - AppendTextBuffer(" -> Direction: IN - EndpointID: %d", - (StillFrameDesc->bEndpointAddress & 0x0F)); - } - AppendTextBuffer("\r\n"); - } - else if(USB_ENDPOINT_DIRECTION_OUT(StillFrameDesc->bEndpointAddress) && StillMethod==2) { - if((StillFrameDesc->bEndpointAddress & 0x0F) != 0) { - //@@TestCase B13.7 - //@@ERROR - //@@Descriptor Field - bEndPointAddress - //@@The EndpointID of bEndPointAddress should be set for 0 when using StillMethod 2 - AppendTextBuffer("\r\n*!*ERROR: The EndpointID of the "\ - "bEndpointAddress is reported as %d. This should be 0.\r\n", - (StillFrameDesc->bEndpointAddress & 0x0F)); - OOPS(); } - else {AppendTextBuffer("\r\n");}} - else if (StillFrameDesc->bEndpointAddress != 0) { - //@@TestCase B13.8 - //@@ERROR - //@@Descriptor Field - bEndPointAddress - //@@The bEndPointAddress should be set for 0 when not using StillMethod 2 or 3 - AppendTextBuffer("\r\n*!*ERROR: bEndPointAddress should be 0.\r\n"); - OOPS(); } - else {AppendTextBuffer("\r\n");} - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayColorMatching() -// -//***************************************************************************** - -BOOL -DisplayColorMatching ( - PVIDEO_COLORFORMAT ColorMatchDesc - ) -{ - //@@DisplayColorMatching -Color Matching - - AppendTextBuffer("\r\n ===>Color Matching Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", ColorMatchDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", ColorMatchDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", ColorMatchDesc->bDescriptorSubtype); - AppendTextBuffer("bColorPrimaries: 0x%02X\r\n", ColorMatchDesc->bColorPrimaries); - AppendTextBuffer("bTransferCharacteristics: 0x%02X\r\n", ColorMatchDesc->bTransferCharacteristics); - AppendTextBuffer("bMatrixCoefficients: 0x%02X\r\n", ColorMatchDesc->bMatrixCoefficients); - - if (ColorMatchDesc->bLength != sizeof(VIDEO_COLORFORMAT)) - { - //@@TestCase B14.1 (Descript.c Line 1596) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - ColorMatchDesc->bLength, - sizeof(VIDEO_COLORFORMAT)); - OOPS(); - } - - //@@TestCase B14.2 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bColorPrimaries - //@@Question - Should we test to verify bColorPrimaries - // AppendTextBuffer("bColorPrimaries: 0x%02X\r\n", ColorMatchDesc->bColorPrimaries); - - //@@TestCase B14.3 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bTransferCharacteristics - //@@Question - Should we test to verify bTransferCharacteristics - // AppendTextBuffer("bTransferCharacteristics: 0x%02X\r\n", ColorMatchDesc->bTransferCharacteristics); - - //@@TestCase B14.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bMatrixCoefficients - //@@Question - Should we test to verify bMatrixCoefficients - // AppendTextBuffer("bMatrixCoefficients: 0x%02X\r\n", ColorMatchDesc->bMatrixCoefficients); - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayUncompressedFormat() -// -//***************************************************************************** - -BOOL -DisplayUncompressedFormat ( - PVIDEO_FORMAT_UNCOMPRESSED UnCompFormatDesc - ) -{ - //@@DisplayUncompressedFormat - Uncompressed Format - int i = 0; - PCHAR pStr = NULL; - OLECHAR szGUID[256]; - - // Initialize the default Frame - g_chUNCFrameDefault = UnCompFormatDesc->bDefaultFrameIndex; - - memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); - i = StringFromGUID2((REFGUID) &UnCompFormatDesc->guidFormat, (LPOLESTR) szGUID, 255); - i++; - - AppendTextBuffer("\r\n ===>Video Streaming Uncompressed Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", UnCompFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", UnCompFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", UnCompFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", UnCompFormatDesc->bFormatIndex); - AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", UnCompFormatDesc->bNumFrameDescriptors); - AppendTextBuffer("guidFormat: %S", szGUID); - - pStr = VidFormatGUIDCodeToName((REFGUID) &UnCompFormatDesc->guidFormat); - if ( pStr ) - { - if ( gDoAnnotation ) - { - AppendTextBuffer(" = %s Format", pStr); - } - } - AppendTextBuffer("\r\n"); - AppendTextBuffer("bBitsPerPixel: 0x%02X\r\n", UnCompFormatDesc->bBitsPerPixel); - AppendTextBuffer("bDefaultFrameIndex: 0x%02X\r\n", UnCompFormatDesc->bDefaultFrameIndex); - - if (UnCompFormatDesc->bLength != sizeof(VIDEO_FORMAT_UNCOMPRESSED)) - { - //@@TestCase B15.1 (descript.c line 925) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required - //@@length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - UnCompFormatDesc->bLength, - sizeof(VIDEO_FORMAT_UNCOMPRESSED)); - OOPS(); - } - - if (UnCompFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B15.2 (descript.c line 930) - //@@ERROR - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bFormatIndex = 0, this is a 1 based index\r\n"); - OOPS(); - } - - if (UnCompFormatDesc->bNumFrameDescriptors == 0 ) - { - //@@TestCase B15.3 (descript.c line 930) - //@@ERROR - //@@Descriptor Field - bNumFrameDescriptors - //@@bNumFrameDescriptors is set to zero which is not in accordance with the - //@@USB Video Device Specification - AppendTextBuffer("*!*ERROR: bNumFrameDescriptors = 0, must have at least 1 Frame descriptor\r\n"); - OOPS(); - } - - if(!(pStr)) - { - //@@TestCase B15.4 - //@@WARNING - //@@Descriptor Field - guidFormat - //@@guidFormat is set to unknown or undefined format - AppendTextBuffer("\r\n*!*WARNING: guidFormat is an unknown format\r\n"); - OOPS(); - } - - if (UnCompFormatDesc->bBitsPerPixel == 0 ) - { - //@@TestCase B15.5 (descript.c line 940) - //@@ERROR - //@@Descriptor Field - bBitsPerPixel - //@@bBitsPerPixel is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bBitsPerPixel = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (UnCompFormatDesc->bDefaultFrameIndex == 0 || UnCompFormatDesc->bDefaultFrameIndex > - UnCompFormatDesc->bNumFrameDescriptors) - { - //@@TestCase B15.6 (desctipt.c line 945) - //@@ERROR - //@@Descriptor Field - bDefaultFrameIndex - //@@The value for bDefaultFrameIndex is not greater than 0 or less than or equal to bNumFrameDescriptors - AppendTextBuffer("*!*ERROR: The value %d for the bDefaultFrameIndex is out of range, this invalidates the descriptor\r\n*!*The proper range is 1 to %d)", - UnCompFormatDesc->bDefaultFrameIndex, - UnCompFormatDesc->bNumFrameDescriptors); - OOPS(); - } - - AppendTextBuffer("bAspectRatioX: 0x%02X\r\n", - UnCompFormatDesc->bAspectRatioX); - AppendTextBuffer("bAspectRatioY: 0x%02X", - UnCompFormatDesc->bAspectRatioY); - - if (((UnCompFormatDesc->bmInterlaceFlags & 0x01) && - (UnCompFormatDesc->bAspectRatioY != 0 && - UnCompFormatDesc->bAspectRatioX != 0))) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Aspect Ratio is set for a %d:%d display", - (UnCompFormatDesc->bAspectRatioX),(UnCompFormatDesc->bAspectRatioY)); - } - else - { - if (UnCompFormatDesc->bAspectRatioY != 0 || UnCompFormatDesc->bAspectRatioX != 0) - { - //@@TestCase B15.7 - //@@ERROR - //@@Descriptor Field - bAspectRatioX, bAspectRatioY - //@@Verify that that bAspectRatioX and bAspectRatioY are set to zero - //@@ if stream is non-interlaced - AppendTextBuffer("\r\n*!*ERROR: Both bAspectRatioX and bAspectRatioY "\ - "must equal 0 if stream is non-interlaced"); - OOPS(); - } - } - } - AppendTextBuffer("\r\nbmInterlaceFlags: 0x%02X\r\n", - UnCompFormatDesc->bmInterlaceFlags); - - if (gDoAnnotation) - { - AppendTextBuffer(" D0 = 0x%02X Interlaced stream or variable: %s\r\n", - (UnCompFormatDesc->bmInterlaceFlags & 1), - (UnCompFormatDesc->bmInterlaceFlags & 1) ? "Yes" : "No"); - AppendTextBuffer(" D1 = 0x%02X Fields per frame: %s\r\n", - ((UnCompFormatDesc->bmInterlaceFlags >> 1) & 1), - ((UnCompFormatDesc->bmInterlaceFlags >> 1) & 1) ? "1 field" : "2 fields"); - AppendTextBuffer(" D2 = 0x%02X Field 1 first: %s\r\n", - ((UnCompFormatDesc->bmInterlaceFlags >> 2) & 1), - ((UnCompFormatDesc->bmInterlaceFlags >> 2) & 1) ? "Yes" : "No"); - //@@TestCase B15.9 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bmInterlaceFlags - //@@Validate that reserved bits (D3) are set to zero. - AppendTextBuffer(" D3 = 0x%02X Reserved%s\r\n", - ((UnCompFormatDesc->bmInterlaceFlags >> 3) & 1), - ((UnCompFormatDesc->bmInterlaceFlags >> 3) & 1) ? - "\r\n*!*ERROR: Reserved to 0" : "" ); - AppendTextBuffer(" D4..5 = 0x%02X Field patterns ->", - ((UnCompFormatDesc->bmInterlaceFlags >> 4) & 3)); - switch(UnCompFormatDesc->bmInterlaceFlags & 0x30) - { - case 0x00: - AppendTextBuffer(" Field 1 only"); - break; - case 0x10: - AppendTextBuffer(" Field 2 only"); - break; - case 0x20: - AppendTextBuffer(" Regular Pattern of fields 1 and 2"); - break; - case 0x30: - AppendTextBuffer(" Random Pattern of fields 1 and 2"); - break; - } - AppendTextBuffer("\r\n D6..7 = 0x%02X Display Mode ->", - ((UnCompFormatDesc->bmInterlaceFlags >> 6) & 3)); - - switch(UnCompFormatDesc->bmInterlaceFlags & 0xC0) - { - case 0x00: - AppendTextBuffer(" Bob only"); - break; - case 0x40: - AppendTextBuffer(" Weave only"); - break; - case 0x80: - AppendTextBuffer(" Bob or weave"); - break; - case 0xC0: - //@@TestCase B15.10 - //@@Not yet implemented - Priority 3 - //@@Descriptor Field - bmInterlaceFlags - //@@Question - Should we validate that reserved bits are set to zero? - AppendTextBuffer(" Reserved"); - break; - } - } - - //@@TestCase B15.11 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bCopyProtect - //@@Question - Are their reserved bits and should we validate that - //@@ reserved bits are set to zero? - AppendTextBuffer("\r\nbCopyProtect: 0x%02X", - UnCompFormatDesc->bCopyProtect); - if (gDoAnnotation) - { - if (UnCompFormatDesc->bCopyProtect) - AppendTextBuffer(" -> Duplication Restricted"); - else - AppendTextBuffer(" -> Duplication Unrestricted"); - } - AppendTextBuffer("\r\n"); - - //@@TestCase B15.12 - //@@We should check to make sure that a Color Matching Descriptor is included in the device - // Check that the correct number of Frame Descriptors and one Color Matching - // descriptor follow - CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) UnCompFormatDesc, - UnCompFormatDesc->bNumFrameDescriptors, VS_FRAME_UNCOMPRESSED); - - return TRUE; - } - - -//***************************************************************************** -// -// DisplayUncompressedFrameType() -// -//***************************************************************************** - -BOOL -DisplayUncompressedFrameType ( - PVIDEO_FRAME_UNCOMPRESSED UnCompFrameDesc - ) -{ - size_t bLength = 0; - bLength = SizeOfVideoFrameUncompressed(UnCompFrameDesc); - - //@@DisplayUncompressedFrameType -Uncompressed Frame - - AppendTextBuffer("\r\n ===>Video Streaming Uncompressed Frame Type Descriptor<===\r\n"); - if (gDoAnnotation) - { - if(UnCompFrameDesc->bFrameIndex == g_chUNCFrameDefault) - { - AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); - } - } - AppendTextBuffer("bLength: 0x%02X\r\n", UnCompFrameDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", UnCompFrameDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", UnCompFrameDesc->bDescriptorSubtype); - AppendTextBuffer("bFrameIndex: 0x%02X\r\n", UnCompFrameDesc->bFrameIndex); - AppendTextBuffer("bmCapabilities: 0x%02X\r\n", UnCompFrameDesc->bmCapabilities); - AppendTextBuffer("wWidth: 0x%04X = %d\r\n", UnCompFrameDesc->wWidth, UnCompFrameDesc->wWidth); - AppendTextBuffer("wHeight: 0x%04X = %d\r\n", UnCompFrameDesc->wHeight, UnCompFrameDesc->wHeight); - AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", UnCompFrameDesc->dwMinBitRate); - AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", UnCompFrameDesc->dwMaxBitRate); - AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", UnCompFrameDesc->dwMaxVideoFrameBufferSize); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - UnCompFrameDesc->dwDefaultFrameInterval, - ((double)UnCompFrameDesc->dwDefaultFrameInterval)/10000.0, - (10000000.0/((double)UnCompFrameDesc->dwDefaultFrameInterval)) - ); - AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", UnCompFrameDesc->bFrameIntervalType); - - if (UnCompFrameDesc->bLength != bLength) - { - //@@TestCase B15.1 (descript.c line 925) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required - //@@length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - UnCompFrameDesc->bLength, bLength); - OOPS(); - } - - if (UnCompFrameDesc->bFrameIndex == 0 ) - { - //@@TestCase B16.2 (descript.c line 991) - //@@ERROR - //@@Descriptor Field - bFrameIndex - //@@bFrameIndex must be nonzero - AppendTextBuffer("*!*ERROR: bFrameIndex = 0, this is a 1 based index\r\n"); - OOPS(); - } - - //@@TestCase B16.3 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bmCapabilities - //@@Question: Should we try to verify that bmCapabilities is valid? - // AppendTextBuffer("bmCapabilities: 0x%02X\r\n", UnCompFrameDesc->bmCapabilities); - - if (UnCompFrameDesc->wWidth == 0 ) - { - //@@TestCase B16.4 (descript.c line 996) - //@@ERROR - //@@Descriptor Field - wWidth - //@@wWidth must be nonzero - AppendTextBuffer("*!*ERROR: wWidth must be nonzero\r\n"); - OOPS(); - } - - if (UnCompFrameDesc->wHeight == 0 ) - { - //@@TestCase B16.5 (descript.c line 1001) - //@@ERROR - //@@Descriptor Field - wHeight - //@@wHeight must be nonzero - AppendTextBuffer("*!*ERROR: wHeight must be nonzero\r\n"); - OOPS(); - } - - if (UnCompFrameDesc->dwMinBitRate == 0 ) - { - //@@TestCase B16.6 (descript.c line 1006) - //@@ERROR - //@@Descriptor Field - dwMinBitRate - //@@dwMinBitRate must be nonzero - AppendTextBuffer("*!*ERROR: dwMinBitRate must be nonzero\r\n"); - OOPS(); - } - - if (UnCompFrameDesc->dwMaxBitRate == 0 ) - { - //@@TestCase B16.7 (descript.c line 1011) - //@@ERROR - //@@Descriptor Field - dwMaxBitRate - //@@dwMaxBitRate must be nonzero - AppendTextBuffer("*!*ERROR: dwMaxBitRate must be nonzero\r\n"); - OOPS(); - } - - if(UnCompFrameDesc->dwMinBitRate > UnCompFrameDesc->dwMaxBitRate) - { - //@@TestCase B16.8 - //@@ERROR - //@@Descriptor Field - dwMinBitRate and dwMaxBitRate - //@@Verify that dwMaxBitRate is greater than dwMinBitRate - AppendTextBuffer("*!*ERROR: dwMinBitRate should be less than dwMaxBitRate\r\n"); - OOPS(); - } - else - { - if (UnCompFrameDesc->bFrameIntervalType == 1 && - UnCompFrameDesc->dwMinBitRate != UnCompFrameDesc->dwMaxBitRate) - { - //@@TestCase B16.9 - //@@WARNING - //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate - //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 - AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate "\ - "should equal dwMaxBitRate\r\n"); - OOPS(); - } - } - - if (UnCompFrameDesc->dwMaxVideoFrameBufferSize == 0 ) - { - //@@TestCase B16.10 (descript.c line 1015) - //@@WARNING - //@@Descriptor Field - bFrameIndex - //@@bFrameIndex must be nonzero - AppendTextBuffer("*!*WARNING: dwMaxVideoFrameBufferSize must be nonzero\r\n"); - OOPS(); - } - - if (UnCompFrameDesc->dwDefaultFrameInterval == 0 ) - { - //@@TestCase B16.11 (descript.c line 1020) - //@@WARNING - //@@Descriptor Field - dwDefaultFrameInterval - //@@dwDefaultFrameInterval must be nonzero - AppendTextBuffer("*!*WARNING: dwDefaultFrameInterval must be nonzero\r\n"); - OOPS(); - } - if (0 == UnCompFrameDesc->bFrameIntervalType) - { - DisplayUnComContinuousFrameType(UnCompFrameDesc); - } - else - { - DisplayUnComDiscreteFrameType(UnCompFrameDesc); - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayUnComContinuousFrameType() -// -//***************************************************************************** - -BOOL -DisplayUnComContinuousFrameType( - PVIDEO_FRAME_UNCOMPRESSED UContinuousDesc - ) -{ - //@@DisplayUnComContinuousFrameType -Uncompressed Continuous Frame - ULONG dwMinFrameInterval = UContinuousDesc->adwFrameInterval[0]; - ULONG dwMaxFrameInterval = UContinuousDesc->adwFrameInterval[1]; - ULONG dwFrameIntervalStep = UContinuousDesc->adwFrameInterval[2]; - - AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - - AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMinFrameInterval, - ((double)dwMinFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); - - AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMaxFrameInterval, - ((double)dwMaxFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); - - AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); - - if (dwMinFrameInterval == 0 ) - { - //@@TestCase B17.2 (descript.c line 1025) - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval - //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (dwMaxFrameInterval == 0 ) - { - //@@TestCase B17.3 (descript.c line 1025) - //@@ERROR - //@@Descriptor Field - dwMaxFrameInterval - //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if(dwMinFrameInterval > dwMaxFrameInterval) - { - //@@TestCase B17.4 (descript.c 1043) - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval - AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); - OOPS(); - } - else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) - { - //@@TestCase B17.5 - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) - { - //@@TestCase B17.6 - //@@CAUTION - //@@Descriptor Field - dwFrameIntervalStep - //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero - AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) - { - //@@TestCase B17.7 (descript.c 1052) - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); - OOPS(); - } - - if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) - { - //@@TestCase B17.8 (descript.c line 1032) - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval - AppendTextBuffer("*!*WARNING: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between dwMinFrameInterval and dwMaxFrameInterval\r\n"); - OOPS(); - } - - return TRUE; -} - -//***************************************************************************** -// -// DisplayUnComDiscreteFrameType() -// -//***************************************************************************** - -BOOL -DisplayUnComDiscreteFrameType( - PVIDEO_FRAME_UNCOMPRESSED UDiscreteDesc - ) -{ - //@@DisplayUnComDiscreteFrameType -Uncompressed Discrete Frame - UINT iNdex = 1; - UINT iCurFrame = 0; - ULONG * ulFrameInterval = NULL; - - AppendTextBuffer("===>Additional Discrete Frame Type Data\r\n"); - - // There are (UDiscreteDesc->bFrameIntervalType) dwFrameIntervals (1 based index) - for (; iNdex <= UDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) - { - ulFrameInterval = &UDiscreteDesc->adwFrameInterval[iCurFrame]; - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - iNdex, *ulFrameInterval, - ((double)*ulFrameInterval)/10000.0, - (10000000.0/((double)*ulFrameInterval)) - ); - if (0 == *ulFrameInterval) - { - //@@TestCase B18.1 (descript.c line 1061) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[x] must be non-zero - AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); - OOPS(); - } - if ((iNdex > 1)&&(*ulFrameInterval <= UDiscreteDesc->adwFrameInterval[iCurFrame - 1])) - { - //@@TestCase B18.2 (descript.c line 1067) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] - AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ - "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); - OOPS(); - } - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayMJPEGFormat() -// -//***************************************************************************** - -BOOL -DisplayMJPEGFormat ( - PVIDEO_FORMAT_MJPEG MJPEGFormatDesc - ) -{ - //@@DisplayMJPEGFormat - MJPEG Format - // Initialize the default Frame - g_chMJPEGFrameDefault = MJPEGFormatDesc->bDefaultFrameIndex; - - AppendTextBuffer("\r\n ===>Video Streaming MJPEG Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", MJPEGFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MJPEGFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MJPEGFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MJPEGFormatDesc->bFormatIndex); - AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", MJPEGFormatDesc->bNumFrameDescriptors); - - if (MJPEGFormatDesc->bLength != sizeof(VIDEO_FORMAT_MJPEG)) - { - //@@TestCase B19.1 (descript.c line 1098) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the - //@@ required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - MJPEGFormatDesc->bLength, - sizeof(VIDEO_FORMAT_MJPEG)); - OOPS(); - } - - if (MJPEGFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B19.2 (descript.c line 1103) - //@@ERROR - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with - //@@ the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bFormatIndex must be non-zero\r\n"); - OOPS(); - } - - if (MJPEGFormatDesc->bNumFrameDescriptors == 0 ) - { - //@@TestCase B19.3 (descript.c line 1108) - //@@ERROR - //@@Descriptor Field - bNumFrameDescriptors - //@@bNumFrameDescriptors is set to zero which is not in accordance - //@@ with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bNumFrameDescriptors must be non-zero\r\n"); - OOPS(); - } - - AppendTextBuffer("bmFlags: 0x%02X", - (MJPEGFormatDesc->bmFlags & 0x01)); - - //@@TestCase B19.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bmFlags - //@@We should validate that reserved bits are set to zero. - if (gDoAnnotation) - { - if(MJPEGFormatDesc->bmFlags & 0x01) - { - AppendTextBuffer(" -> Sample Size is Fixed"); - } - else - { - AppendTextBuffer(" -> Sample Size is Not Fixed"); - } - } - AppendTextBuffer("\r\nbDefaultFrameIndex: 0x%02X\r\n", - MJPEGFormatDesc->bDefaultFrameIndex); - - if (MJPEGFormatDesc->bDefaultFrameIndex == 0 || - MJPEGFormatDesc->bDefaultFrameIndex > - MJPEGFormatDesc->bNumFrameDescriptors) - { - //@@TestCase B19.5 (descript.c line 1113) - //@@ERROR - //@@Descriptor Field - bDefaultFrameIndex - //@@bDefaultFrameIndex is not in the domain of constrained by - //@@ bNumFrameDescriptors - AppendTextBuffer("*!*ERROR: bDefaultFrameIndex 0x%02X invalid, should "\ - "be between 1 and 0x%02x/r/n", - MJPEGFormatDesc->bDefaultFrameIndex, - MJPEGFormatDesc->bNumFrameDescriptors); - OOPS(); - } - - AppendTextBuffer("bAspectRatioX: 0x%02X\r\n", - MJPEGFormatDesc->bAspectRatioX); - AppendTextBuffer("bAspectRatioY: 0x%02X", - MJPEGFormatDesc->bAspectRatioY); - - if(((MJPEGFormatDesc->bmInterlaceFlags & 0x01) && - ((MJPEGFormatDesc->bAspectRatioY != 0) && - (MJPEGFormatDesc->bAspectRatioX != 0)))) - { - if (gDoAnnotation) - { - AppendTextBuffer(" -> Aspect Ratio is set for a %d:%d display", - (MJPEGFormatDesc->bAspectRatioX), (MJPEGFormatDesc->bAspectRatioY)); - } - } - else - { - if (MJPEGFormatDesc->bAspectRatioY != 0 || MJPEGFormatDesc->bAspectRatioX != 0) - { - //@@TestCase B19.6 - //@@ERROR - //@@Descriptor Field - bAspectRatioX and bAspectRatioY - //@@Verify that that bAspectRatioX and bAspectRatioY are set to zero - //@@ if stream is non-interlaced - AppendTextBuffer("\r\n*!*ERROR: bAspectRatioX and bAspectRatioY must "\ - "be 0 if stream non-Interlaced"); - OOPS(); - } - } - AppendTextBuffer("\r\nbmInterlaceFlags: 0x%02X\r\n", - MJPEGFormatDesc->bmInterlaceFlags); - - if (gDoAnnotation) - { - AppendTextBuffer(" D00 = %x %sInterlaced stream or variable\r\n", - (MJPEGFormatDesc->bmInterlaceFlags & 1), - (MJPEGFormatDesc->bmInterlaceFlags & 1) ? "" : " non-"); - AppendTextBuffer(" D01 = %x %s per frame\r\n", - ((MJPEGFormatDesc->bmInterlaceFlags >> 1) & 1), - ((MJPEGFormatDesc->bmInterlaceFlags >> 1) & 1) ? " 1 field" : " 2 fields"); - AppendTextBuffer(" D02 = %x Field 1 %sfirst\r\n", - ((MJPEGFormatDesc->bmInterlaceFlags >> 2) & 1), - ((MJPEGFormatDesc->bmInterlaceFlags >> 2) & 1) ? "" : "not "); - //@@TestCase B19.7 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bmInterlaceFlags - //@@Validate that reserved bits (D3) are set to zero. - AppendTextBuffer(" D03 = %x Reserved%s\r\n", - ((MJPEGFormatDesc->bmInterlaceFlags >> 3) & 1), - ((MJPEGFormatDesc->bmInterlaceFlags >> 3) & 1) ? - "\r\n*!*ERROR: non zero" : "" ); - AppendTextBuffer(" D4..5 = %x Field patterns ->", - ((MJPEGFormatDesc->bmInterlaceFlags >> 4) & 3)); - switch (MJPEGFormatDesc->bmInterlaceFlags & 0x30) - { - case 0x00: - AppendTextBuffer(" Field 1 only"); - break; - case 0x10: - AppendTextBuffer(" Field 2 only"); - break; - case 0x20: - AppendTextBuffer(" Regular Pattern of fields 1 and 2"); - break; - case 0x30: - AppendTextBuffer(" Random Pattern of fields 1 and 2"); - break; - } - AppendTextBuffer("\r\n D6..7 = %x Display Mode ->", - ((MJPEGFormatDesc->bmInterlaceFlags >> 6) & 3)); - switch(MJPEGFormatDesc->bmInterlaceFlags & 0xC0) - { - case 0x00: - AppendTextBuffer(" Bob only"); - break; - case 0x40: - AppendTextBuffer(" Weave only"); - break; - case 0x80: - AppendTextBuffer(" Bob or weave"); - break; - case 0xC0: - //@@TestCase B19.8 - //@@Not yet implemented - Priority 3 - //@@Descriptor Field - bmInterlaceFlags - //@@Question - Should we validate that reserved bits are set to zero? - AppendTextBuffer(" Reserved"); - break; - } - } - - //@@TestCase B19.9 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bCopyProtect - //@@Question - Are their reserved bits and should we validate that - //@@ reserved bits are set to zero? - AppendTextBuffer("\r\nbCopyProtect: 0x%02X", - MJPEGFormatDesc->bCopyProtect); - if (gDoAnnotation) - { - if (MJPEGFormatDesc->bCopyProtect) - AppendTextBuffer(" -> Duplication Restricted"); - else - AppendTextBuffer(" -> Duplication Unrestricted"); - } - AppendTextBuffer("\r\n"); - - // Check that the correct number of Frame Descriptors and one Color Matching - // descriptor follow - CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) MJPEGFormatDesc, - MJPEGFormatDesc->bNumFrameDescriptors, VS_FRAME_MJPEG); - - return TRUE; -} - -//***************************************************************************** -// -// DisplayMJPEGFrameType() -// -//***************************************************************************** - -BOOL -DisplayMJPEGFrameType ( - PVIDEO_FRAME_MJPEG MJPEGFrameDesc - ) -{ - //@@DisplayMJPEGFrameType -MJPEG Frame - size_t bLength = 0; - bLength = SizeOfVideoFrameMjpeg(MJPEGFrameDesc); - - AppendTextBuffer("\r\n ===>Video Streaming MJPEG Frame Type Descriptor<===\r\n"); - if (gDoAnnotation) - { - if(MJPEGFrameDesc->bFrameIndex == g_chMJPEGFrameDefault) - { - AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); - } - } - AppendTextBuffer("bLength: 0x%02X\r\n", MJPEGFrameDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MJPEGFrameDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MJPEGFrameDesc->bDescriptorSubtype); - AppendTextBuffer("bFrameIndex: 0x%02X\r\n", MJPEGFrameDesc->bFrameIndex); - AppendTextBuffer("bmCapabilities: 0x%02X\r\n", MJPEGFrameDesc->bmCapabilities); - AppendTextBuffer("wWidth: 0x%04X = %d\r\n", MJPEGFrameDesc->wWidth, MJPEGFrameDesc->wWidth); - AppendTextBuffer("wHeight: 0x%04X = %d\r\n", MJPEGFrameDesc->wHeight, MJPEGFrameDesc->wHeight); - AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", MJPEGFrameDesc->dwMinBitRate); - AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", MJPEGFrameDesc->dwMaxBitRate); - AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", MJPEGFrameDesc->dwMaxVideoFrameBufferSize); - - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - MJPEGFrameDesc->dwDefaultFrameInterval, - ((double)MJPEGFrameDesc->dwDefaultFrameInterval)/10000.0, - (10000000.0/((double)MJPEGFrameDesc->dwDefaultFrameInterval)) - ); - AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", MJPEGFrameDesc->bFrameIntervalType); - - if (MJPEGFrameDesc->bLength != bLength) - { - //@@TestCase B20.1 (descript.c line 1154) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is less than required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d is incorrect, should be %d\r\n", - MJPEGFrameDesc->bLength, bLength); - OOPS(); - } - - if (MJPEGFrameDesc->bFrameIndex == 0 ) - { - //@@TestCase B20.2 (descript.c line 1159) - //@@WARNING - //@@Descriptor Field - bFrameIndex - //@@bFrameIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: bFrameIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - //@@TestCase B20.3 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bmCapabilities - //@@Question: Should we try to verify that bmCapabilities is valid? - // AppendTextBuffer("bmCapabilities: 0x%02X\r\n", MJPEGFrameDesc->bmCapabilities); - - if (MJPEGFrameDesc->wWidth == 0 ) - { - //@@TestCase B20.4 (descript.c line 1164) - //@@ERROR - //@@Descriptor Field - wWidth - //@@wWidth is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: wWidth = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (MJPEGFrameDesc->wHeight == 0 ) - { - //@@TestCase B20.5 (descript.c line 1169) - //@@ERROR - //@@Descriptor Field - wHeight - //@@wHeight is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: wHeight = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (MJPEGFrameDesc->dwMinBitRate == 0 ) - { - //@@TestCase B20.6 (descript.c line 1174) - //@@ERROR - //@@Descriptor Field - dwMinBitRate - //@@dwMinBitRate is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMinBitRate = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (MJPEGFrameDesc->dwMaxBitRate == 0 ) - { - //@@TestCase B20.7 (descript.c line 1179) - //@@ERROR - //@@Descriptor Field - dwMaxBitRate - //@@dwMaxBitRate is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxBitRate = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if(MJPEGFrameDesc->dwMinBitRate > MJPEGFrameDesc->dwMaxBitRate) - { - //@@TestCase B20.8 - //@@ERROR - //@@Descriptor Field - dwMinBitRate and dwMaxBitRate - //@@Verify that dwMaxBitRate is greater than dwMinBitRate - AppendTextBuffer("*!*ERROR: dwMinBitRate > dwMaxBitRate, this invalidates the descriptor\r\n"); - OOPS(); - } - else if(MJPEGFrameDesc->bFrameIntervalType == 1 && MJPEGFrameDesc->dwMinBitRate != MJPEGFrameDesc->dwMaxBitRate) - { - //@@TestCase B20.9 - //@@WARNING - //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate - //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 - AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate should equal dwMaxBitRate\r\n"); - OOPS(); - } - - if (MJPEGFrameDesc->dwMaxVideoFrameBufferSize == 0 ) - { - //@@TestCase B20.10 (descript.c line 1183) - //@@ERROR - //@@Descriptor Field - dwMaxVideoFrameBufferSize - //@@dwMaxVideoFrameBufferSize is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxVideoFrameBufferSize = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (MJPEGFrameDesc->dwMaxVideoFrameBufferSize == 0 ) - { - //@@TestCase B20.11 (descript.c line 1188) - //@@ERROR - //@@Descriptor Field - dwDefaultFrameInterval - //@@dwDefaultFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwDefaultFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (0 == MJPEGFrameDesc->bFrameIntervalType) - { - DisplayMJPEGContinuousFrameType(MJPEGFrameDesc); - } - else - { - DisplayMJPEGDiscreteFrameType(MJPEGFrameDesc); - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayMJPEGContinuousFrameType() -// -//***************************************************************************** - -BOOL -DisplayMJPEGContinuousFrameType( - PVIDEO_FRAME_MJPEG MContinuousDesc - ) -{ - //@@DisplayMJPEGContinuousFrameType - MJPEG Continuous Frame - ULONG dwMinFrameInterval = MContinuousDesc->adwFrameInterval[0]; - ULONG dwMaxFrameInterval = MContinuousDesc->adwFrameInterval[1]; - ULONG dwFrameIntervalStep = MContinuousDesc->adwFrameInterval[2]; - - AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - - AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMinFrameInterval, - ((double)dwMinFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); - - AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMaxFrameInterval, - ((double)dwMaxFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); - - AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); - - if (dwMinFrameInterval == 0 ) - { - //@@TestCase B21.2 (descript.c line 1188) - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval - //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (dwMaxFrameInterval == 0 ) - { - //@@TestCase B21.3 (descript.c line 1188) - //@@ERROR - //@@Descriptor Field - dwMaxFrameInterval - //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if(dwMinFrameInterval > dwMaxFrameInterval) - { - //@@TestCase B21.4 (descript.c line 1211) - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval - AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); - OOPS(); - } - else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) - { - //@@TestCase B21.5 - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) - { - //@@TestCase B21.6 - //@@CAUTION - //@@Descriptor Field - dwFrameIntervalStep - //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero - AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) - { - //@@TestCase B21.7 (descript.c line 1220) - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); - OOPS(); - } - - if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) - { - //@@TestCase B21.8 (descript.c line 1200) - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval - AppendTextBuffer("*!*WARNING: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between \r\n *!*dwMinFrameInterval and dwMaxFrameInterval\r\n"); - OOPS(); - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayMJPEGDiscreteFrameType() -// -//***************************************************************************** - -BOOL -DisplayMJPEGDiscreteFrameType( - PVIDEO_FRAME_MJPEG MDiscreteDesc - ) -{ - //@@DisplayMJPEGDiscreteFrameType -MJPEG Discrete Frame - UINT iNdex = 1; - UINT iCurFrame = 0; - ULONG * ulFrameInterval = NULL; - - AppendTextBuffer("===>Additional Discrete Frame TypeData\r\n"); - - // There are (MDiscreteDesc->bFrameIntervalType) dwFrameIntervals (1 based index) - for (; iNdex <= MDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) - { - ulFrameInterval = &MDiscreteDesc->adwFrameInterval[iCurFrame]; - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - iNdex, *ulFrameInterval, - ((double)*ulFrameInterval)/10000.0, - (10000000.0/((double)*ulFrameInterval)) - ); - if (0 == *ulFrameInterval) - { - //@@TestCase B22.1 (descript.c line 1229) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[x] must be non-zero - AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); - OOPS(); - } - if ((iNdex > 1)&&(*ulFrameInterval <= MDiscreteDesc->adwFrameInterval[iCurFrame - 1])) - { - //@@TestCase B22.2 (descript.c line 1235) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] - AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ - "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); - OOPS(); - } - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayMPEG1SSFormat() -// -//***************************************************************************** - -BOOL -DisplayMPEG1SSFormat ( - PVIDEO_FORMAT_MPEG1SS MPEG1SSFormatDesc - ) -{ - //@@DisplayMPEG1SSFormat -MPEG1 SS Format - AppendTextBuffer("\r\n ===>Video Streaming MPEG1-SS Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", MPEG1SSFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG1SSFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG1SSFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG1SSFormatDesc->bFormatIndex); - AppendTextBuffer("wPacketLength: 0x%02X\r\n", MPEG1SSFormatDesc->bPacketLength); - AppendTextBuffer("wPackLength: 0x%02X\r\n", MPEG1SSFormatDesc->bPackLength); - AppendTextBuffer("bPackdataType: 0x%02X", (MPEG1SSFormatDesc->bPackDataType)); - if(gDoAnnotation) { - if(MPEG1SSFormatDesc->bPackDataType & 0x01){AppendTextBuffer(" -> Pack data size fixed\r\n");} - else {AppendTextBuffer(" -> Pack data size variable\r\n"); }} - else {AppendTextBuffer("\r\n");} - - - if (MPEG1SSFormatDesc->bLength != sizeof(VIDEO_FORMAT_MPEG1SS)) - { - //@@TestCase B23.1 (descript.c line 1514) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", - MPEG1SSFormatDesc->bLength, - sizeof(VIDEO_FORMAT_MPEG1SS)); - OOPS(); - } - - if (MPEG1SSFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B23.2 (descript.c line 1519) - //@@WARNING - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - //@@TestCase B23.3 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bPackdataType - //@@Question - Should we validate that reserved bits are set to zero? - // AppendTextBuffer("bPackdataType: 0x%02X", (MPEG1SSFormatDesc->bPackdataType & 0x01)); - - // This descriptor is deprecated for UVC 1.1 -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); - } -#else - if (UVC11 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); - } -#endif - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayMPEG2PSFormat() -// -//***************************************************************************** - -BOOL -DisplayMPEG2PSFormat ( - PVIDEO_FORMAT_MPEG2PS MPEG2PSFormatDesc - ) -{ - //@@DisplayMPEG2PSFormat -MPEG2 PS Format - AppendTextBuffer("\r\n ===>Video Streaming MPEG2-PS Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", MPEG2PSFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG2PSFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG2PSFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG2PSFormatDesc->bFormatIndex); - AppendTextBuffer("bPacketLength: 0x%02X\r\n", MPEG2PSFormatDesc->bPacketLength); - AppendTextBuffer("bPackLength: 0x%02X\r\n", MPEG2PSFormatDesc->bPackLength); - AppendTextBuffer("bPackDataType: 0x%02X", (MPEG2PSFormatDesc->bPackDataType)); - - if (MPEG2PSFormatDesc->bLength != sizeof(VIDEO_FORMAT_MPEG2PS)) - { - //@@TestCase B24.1 (descript.c line 1542) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", - MPEG2PSFormatDesc->bLength, - sizeof(VIDEO_FORMAT_MPEG2PS)); - OOPS(); - AppendTextBuffer("*!*USBView will try to display the rest of the descriptor but results may not be accurate\r\n"); - } - - if (MPEG2PSFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B24.2 (descript.c line 1547) - //@@WARNING - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - //@@TestCase B24.3 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bPackdataType - //@@Question - Should we validate that reserved bits are set to zero? - // AppendTextBuffer("bPackdataType: 0x%02X", (MPEG2PSFormatDesc->bPackdataType & 0x01)); - - // This descriptor is deprecated for UVC 1.1 -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); - } -#else - if (UVC11 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); - } -#endif - - return TRUE; - -} - - -//***************************************************************************** -// -// DisplayMPEG2TSFormat() -// -//***************************************************************************** - -BOOL -DisplayMPEG2TSFormat ( - PVIDEO_FORMAT_MPEG2TS MPEG2TSFormatDesc - ) -{ - //@@DisplayMPEG2TSFormat -MPEG2 TS Format - UCHAR bLength = sizeof(VIDEO_FORMAT_MPEG2TS); - - AppendTextBuffer("\r\n ===>Video Streaming MPEG2-TS Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", MPEG2TSFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG2TSFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG2TSFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG2TSFormatDesc->bFormatIndex); - AppendTextBuffer("bDataOffset: 0x%02X\r\n", MPEG2TSFormatDesc->bDataOffset); - AppendTextBuffer("bPacketLength: 0x%02X\r\n", MPEG2TSFormatDesc->bPacketLength); - AppendTextBuffer("bStrideLength: 0x%02X\r\n", MPEG2TSFormatDesc->bStrideLength); - -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) -#else - if (UVC11 == g_chUVCversion) -#endif - { - int i = 0; - PCHAR pStr = NULL; - OLECHAR szGUID[256]; - GUID * pStrideGuid = NULL; - - pStrideGuid = (GUID *) (&MPEG2TSFormatDesc->bStrideLength + 1); - - memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); - i = StringFromGUID2((REFGUID) pStrideGuid, (LPOLESTR) szGUID, 255); - i++; - AppendTextBuffer("guidStrideFormat: %S", szGUID); - pStr = VidFormatGUIDCodeToName((REFGUID) pStrideGuid); - if(gDoAnnotation) - { - if (pStr) - { - AppendTextBuffer(" = %s Format", pStr); - } - } - AppendTextBuffer("\r\n"); - bLength = sizeof(VIDEO_FORMAT_MPEG2TS) + sizeof(GUID); - } - - if (MPEG2TSFormatDesc->bLength != bLength) - { - //@@TestCase B25.1 (descript.c line 1486) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - MPEG2TSFormatDesc->bLength, - sizeof(VIDEO_FORMAT_MPEG2TS)); - OOPS(); - } - - if (MPEG2TSFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B25.2 (descript.c line 1491) - //@@WARNING - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - //@@TestCase B25.3 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bDataOffset, wPacket and wStride - //@@Question - Should we check that if bDataOffset is 0 that wPacket and wStride should equal each other - // AppendTextBuffer("bDataOffset: 0x%02X\r\n", MPEG2TSFormatDesc->bDataOffset); - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayMPEG4SLFormat() -// -//***************************************************************************** - -BOOL -DisplayMPEG4SLFormat ( - PVIDEO_FORMAT_MPEG4SL MPEG4SLFormatDesc - ) -{ - //@@DisplayMPEG4SLFormat -MPEG4 SL Format - - AppendTextBuffer("\r\n ===>Video Streaming MPEG4-SL Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", MPEG4SLFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", MPEG4SLFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", MPEG4SLFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", MPEG4SLFormatDesc->bFormatIndex); - AppendTextBuffer("bPacketLength: 0x%02X\r\n", MPEG4SLFormatDesc->bPacketLength); - - if (MPEG4SLFormatDesc->bLength != sizeof(VIDEO_FORMAT_MPEG4SL)) - { - //@@TestCase B26.1 (descript.c line 1568) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", - MPEG4SLFormatDesc->bLength, - sizeof(VIDEO_FORMAT_MPEG4SL)); - OOPS(); - } - - if (MPEG4SLFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B26.2 (descript.c line 1573) - //@@WARNING - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - // This descriptor is deprecated for UVC 1.1 -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); - } -#else - if (UVC11 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); - } -#endif - return TRUE; -} - - -//***************************************************************************** -// -// DisplayStreamPayload() -// -//***************************************************************************** - -BOOL -DisplayStreamPayload ( - PVIDEO_FORMAT_STREAM StreamPayloadDesc - ) -{ - //@@DisplayStreamPayload -Stream Based Payload Format - PCHAR pStr = NULL; - OLECHAR szGUID[256]; - int i = 0; - - memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); - i = StringFromGUID2((REFGUID) &StreamPayloadDesc->guidFormat, (LPOLESTR) szGUID, 255); - i++; - - AppendTextBuffer("\r\n ===>Video Streaming Stream Based Payload Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", StreamPayloadDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", StreamPayloadDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", StreamPayloadDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", StreamPayloadDesc->bFormatIndex); - AppendTextBuffer("guidFormat: %S", szGUID); - - pStr = VidFormatGUIDCodeToName((REFGUID) &StreamPayloadDesc->guidFormat); - if(gDoAnnotation) - { - if (pStr) - { - AppendTextBuffer(" = %s Format", pStr); - } - } - AppendTextBuffer("\r\n"); - AppendTextBuffer("dwPacketLength: 0x%02X\r\n", StreamPayloadDesc->dwPacketLength); - - if (StreamPayloadDesc->bLength != sizeof(VIDEO_FORMAT_STREAM)) - { - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - StreamPayloadDesc->bLength, - sizeof(PVIDEO_FORMAT_STREAM)); - OOPS(); - } - - if (StreamPayloadDesc->bFormatIndex == 0 ) - { - //@@WARNING - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: bFormatIndex = 0, this is a 1 based index\r\n"); - OOPS(); - } - - // This descriptor is new for UVC 1.1 - if (UVC10 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.0 devices\r\n"); - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayDVFormat() -// -//***************************************************************************** - -BOOL -DisplayDVFormat ( - PVIDEO_FORMAT_DV DVFormatDesc - ) -{ - //@@DisplayDVFormat -Digital Video Format - - AppendTextBuffer("\r\n ===>Video Streaming DV Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", DVFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", DVFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", DVFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", DVFormatDesc->bFormatIndex); - AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", DVFormatDesc->dwMaxVideoFrameBufferSize); - AppendTextBuffer("bFormatType: 0x%02X\r\n", DVFormatDesc->bFormatType); - if (gDoAnnotation) - { - AppendTextBuffer(" D0..6 = Format Type ->"); - switch(DVFormatDesc->bFormatType & 0x03) - { - case 0x00: - AppendTextBuffer(" SD-DV\r\n"); - break; - case 0x01: - AppendTextBuffer(" SDL-DV\r\n"); - break; - case 0x02: - AppendTextBuffer(" HD-DV\r\n"); - break; - default: - AppendTextBuffer(" Unknown Format\r\n"); - break; - } - if (DVFormatDesc->bFormatType & 0x80) - AppendTextBuffer(" D7 = 60Hz"); - else - AppendTextBuffer(" D7 = 50Hz"); - AppendTextBuffer("\r\n");} - - if (DVFormatDesc->bLength != sizeof(VIDEO_FORMAT_DV)) - { - //@@TestCase B27.1 (descript.c line 1453) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - DVFormatDesc->bLength, - sizeof(VIDEO_FORMAT_DV)); - OOPS(); - } - - if (DVFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B27.2 (descript.c line 1458) - //@@ERROR - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex invalid - AppendTextBuffer("*!*ERROR: bFormatIndex of 0x%02X is invalid\r\n", - DVFormatDesc->bFormatIndex); - OOPS(); - } - - if (DVFormatDesc->dwMaxVideoFrameBufferSize == 0 ) - { - //@@TestCase B27.3 (descript.c line 1463) - //@@ERROR - //@@Descriptor Field - dwMaxVideoFrameBufferSize - //@@dwMaxVideoFrameBufferSize invalid - AppendTextBuffer("*!*ERROR: dwMaxVideoFrameBufferSize of 0x%02X is invalid\r\n", - DVFormatDesc->dwMaxVideoFrameBufferSize); - OOPS(); - } - - //@@TestCase B27.4 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bFormatType - //@@Question - Should we validate that reserved bits are set to zero? - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVidVendorFormat() -// -//***************************************************************************** - -BOOL -DisplayVendorVidFormat ( - PVIDEO_FORMAT_VENDOR VendorVidFormatDesc - ) -{ - //@@DisplayVendorVidFormat -Vendor Video Format - OLECHAR szGUID[256]; - int i = 0; - - // Initialize the default Frame - g_chVendorFrameDefault = VendorVidFormatDesc->bDefaultFrameIndex; - - memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); - i = StringFromGUID2((REFGUID) &VendorVidFormatDesc->guidMajorFormat, (LPOLESTR) szGUID, 255); - i++; - - AppendTextBuffer("\r\n ===>Video Streaming Vendor Video Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", VendorVidFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VendorVidFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VendorVidFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", VendorVidFormatDesc->bFormatIndex); - AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", VendorVidFormatDesc->bNumFrameDescriptors); - AppendTextBuffer("guidMajorFormat: %S\r\n", szGUID); - i = StringFromGUID2((REFGUID) &VendorVidFormatDesc->guidSubFormat, (LPOLESTR) szGUID, 255); - i++; - AppendTextBuffer("guidSubFormat: %S\r\n", szGUID); - i = StringFromGUID2((REFGUID) &VendorVidFormatDesc->guidSpecifier, (LPOLESTR) szGUID, 255); - i++; - AppendTextBuffer("guidSpecifier: %S\r\n", szGUID); - AppendTextBuffer("bPayloadClass: 0x%02X\r\n", VendorVidFormatDesc->bPayloadClass); - AppendTextBuffer("bDefaultFrameIndex: 0x%02X\r\n", VendorVidFormatDesc->bDefaultFrameIndex); - AppendTextBuffer("bCopyProtect: 0x%02X", VendorVidFormatDesc->bCopyProtect); - if(gDoAnnotation) { - if(VendorVidFormatDesc->bCopyProtect) { AppendTextBuffer(" -> Duplication Restricted\r\n");} - else {AppendTextBuffer(" -> Duplication Unrestricted\r\n");}} - else {AppendTextBuffer("\r\n");} - - if (VendorVidFormatDesc->bLength != sizeof(VIDEO_FORMAT_VENDOR)) - { - //@@TestCase B28.1 (descript.c line 1297) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", - VendorVidFormatDesc->bLength, - sizeof(VIDEO_FORMAT_VENDOR)); - OOPS(); - } - - if (VendorVidFormatDesc->bFormatIndex == 0 ) - { - //@@TestCase B28.2 (descript.c line 1302) - //@@ERROR - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bFormatIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (VendorVidFormatDesc->bNumFrameDescriptors == 0 ) - { - //@@TestCase B28.3 (descript.c line 1307) - //@@ERROR - //@@Descriptor Field - bNumFrameDescriptors - //@@bNumFrameDescriptors is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bNumFrameDescriptors = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if(VendorVidFormatDesc->bPayloadClass > 1) - { - //@@TestCase B28.4 - //@@WARNING - //@@Descriptor Field - bPayloadClass - //@@bPayloadClass is using reserved space - AppendTextBuffer("*!*WARNING: bPayloadClass is incorrectly using reserved space\r\n"); - OOPS(); - } - else - { - if (gDoAnnotation) - { - if(VendorVidFormatDesc->bPayloadClass == 1) { AppendTextBuffer(" -> Using a Frame Based Payload\r\n");} - else { AppendTextBuffer(" -> Using a Stream Based Payload\r\n");} - } - else {AppendTextBuffer("\r\n");} - } - - if (VendorVidFormatDesc->bDefaultFrameIndex == 0 ) - { - //@@TestCase B28.5 (descript.c line 1312) - //@@ERROR - //@@Descriptor Field - bDefaultFrameIndex - //@@bDefaultFrameIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bDefaultFrameIndex = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (VendorVidFormatDesc->bDefaultFrameIndex == 0 || VendorVidFormatDesc->bDefaultFrameIndex > VendorVidFormatDesc->bNumFrameDescriptors) - { - //@@TestCase B28.6 - //@@WARNING - //@@Descriptor Field - bDefaultFrameIndex - //@@bDefaultFrameIndex is out of range - AppendTextBuffer("*!*WARNING: The value %d for the bDefaultFrameIndex is out of range this invalidates the descriptor\r\n*!* The proper range is 1 to %d)", - VendorVidFormatDesc->bDefaultFrameIndex, - VendorVidFormatDesc->bNumFrameDescriptors); - OOPS(); - } - - //@@TestCase B28.7 - //@@Not yet implemented - Priority 1 - //@@Descriptor Field - bCopyProtect - //@@Question - Are their reserved bits and should we validate that reserved bits are set to zero? - // AppendTextBuffer("bCopyProtect: 0x%02X", VendorVidFormatDesc->bCopyProtect); - - // Check that the correct number of Frame Descriptors and one Color Matching - // descriptor follow - CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) VendorVidFormatDesc, - VendorVidFormatDesc->bNumFrameDescriptors, VS_FRAME_VENDOR); - - // This descriptor is deprecated for UVC 1.1 -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); - } -#else - if (UVC11 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); - } -#endif - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVendorVidFrameType() -// -//***************************************************************************** - -BOOL -DisplayVendorVidFrameType ( - PVIDEO_FRAME_VENDOR VendorVidFrameDesc - ) -{ - //@@DisplayVendorVidFrameType -Vendor Video Frame - size_t bLength = 0; - bLength = SizeOfVideoFrameVendor(VendorVidFrameDesc); - - AppendTextBuffer("\r\n ===>Video Streaming Vendor Video Frame Type Descriptor<===\r\n"); - if (gDoAnnotation) - { - if(VendorVidFrameDesc->bFrameIndex == g_chVendorFrameDefault) - { - AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); - } - } - AppendTextBuffer("bLength: 0x%02X\r\n", VendorVidFrameDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VendorVidFrameDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VendorVidFrameDesc->bDescriptorSubtype); - AppendTextBuffer("bFrameIndex: 0x%02X\r\n", VendorVidFrameDesc->bFrameIndex); - - if (VendorVidFrameDesc->bLength != bLength) - { - //@@TestCase B29.1 (descript.c line 1352) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is less than required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - VendorVidFrameDesc->bLength, bLength); - OOPS(); - } - - if (VendorVidFrameDesc->bFrameIndex == 0 ) - { - //@@TestCase B29.2 (descript.c line 1357) - //@@ERROR - //@@Descriptor Field - bFrameIndex - //@@bFrameIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bFrameIndex = 0, this is a 1 based index\r\n"); - OOPS(); - } - - AppendTextBuffer("bmCapabilities: 0x%02X", VendorVidFrameDesc->bmCapabilities); - - if(VendorVidFrameDesc->bmCapabilities & 0x01){ - if(gDoAnnotation) { AppendTextBuffer(" -> Still Images are supported\r\n");} - else {AppendTextBuffer("\r\n");} } - else if (VendorVidFrameDesc->bmCapabilities & 0xFF) - { - //@@TestCase B29.3 - //@@WARNING - //@@Descriptor Field - bmCapabilities - //@@bmCapabilities has a bit using reserved areas that should be set to zero - AppendTextBuffer("\r\n*!*WARNING: bmCapabilities is using reserved areas.\r\n"); - OOPS(); } - else {AppendTextBuffer("\r\n");} - AppendTextBuffer("wWidth: 0x%04X = %d\r\n", VendorVidFrameDesc->wWidth, VendorVidFrameDesc->wWidth); - AppendTextBuffer("wHeight: 0x%04X = %d\r\n", VendorVidFrameDesc->wHeight, VendorVidFrameDesc->wHeight); - AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", VendorVidFrameDesc->dwMinBitRate); - AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", VendorVidFrameDesc->dwMaxBitRate); - AppendTextBuffer("dwMaxVideoFrameBufferSize: 0x%08X\r\n", VendorVidFrameDesc->dwMaxVideoFrameBufferSize); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - VendorVidFrameDesc->dwDefaultFrameInterval, - ((double)VendorVidFrameDesc->dwDefaultFrameInterval)/10000.0, - (10000000.0/((double)VendorVidFrameDesc->dwDefaultFrameInterval)) - ); - AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", VendorVidFrameDesc->bFrameIntervalType); - - if (VendorVidFrameDesc->wWidth == 0 ) - { - //@@TestCase B29.4 (descript.c line 1362) - //@@ERROR - //@@Descriptor Field - wWidth - //@@wWidth is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: wWidth must be nonzero\r\n"); - OOPS(); - } - - if (VendorVidFrameDesc->wHeight == 0 ) - { - //@@TestCase B29.5 (descript.c line 1367) - //@@ERROR - //@@Descriptor Field - wHeight - //@@wHeight is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: wHeight must be nonzero\r\n"); - OOPS(); - } - - if (VendorVidFrameDesc->dwMinBitRate == 0 ) - { - //@@TestCase B29.6 (descript.c line 1372) - //@@ERROR - //@@Descriptor Field - dwMinBitRate - //@@dwMinBitRate is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMinBitRate must be nonzero\r\n"); - OOPS(); - } - - if (VendorVidFrameDesc->dwMaxBitRate == 0 ) - { - //@@TestCase B29.7 (descript.c line 1377) - //@@ERROR - //@@Descriptor Field - dwMaxBitRate - //@@dwMaxBitRate is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxBitRate must be nonzero\r\n"); - OOPS(); - } - - if(VendorVidFrameDesc->dwMinBitRate > VendorVidFrameDesc->dwMaxBitRate) - { - //@@TestCase B29.8 - //@@ERROR - //@@Descriptor Field - dwMinBitRate and dwMaxBitRate - //@@Verify that dwMaxBitRate is greater than dwMinBitRate - AppendTextBuffer("*!*ERROR: dwMinBitRate should be less than dwMaxBitRate\r\n"); - OOPS(); - } - else - { - if (VendorVidFrameDesc->bFrameIntervalType == 1 && - VendorVidFrameDesc->dwMinBitRate != VendorVidFrameDesc->dwMaxBitRate) - { - //@@TestCase B29.9 - //@@WARNING - //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate - //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 - AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate "\ - "should equal dwMaxBitRate\r\n"); - OOPS(); - } - } - - if (VendorVidFrameDesc->dwMaxVideoFrameBufferSize == 0 ) - { - //@@TestCase B29.10 (descript.c line 1382) - //@@WARNING - //@@Descriptor Field - dwMaxVideoFrameBufferSize - //@@dwMaxVideoFrameBufferSize is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*WARNING: dwMaxVideoFrameBufferSize must be nonzero\r\n"); - OOPS(); - } - if (VendorVidFrameDesc->dwDefaultFrameInterval == 0 ) - { - //@@TestCase B29.11 (descript.c line 1020) - //@@WARNING - //@@Descriptor Field - dwDefaultFrameInterval - //@@dwDefaultFrameInterval must be nonzero - AppendTextBuffer("*!*WARNING: dwDefaultFrameInterval must be nonzero\r\n"); - OOPS(); - } - - if (VendorVidFrameDesc->bFrameIntervalType == 0) - { - DisplayVendorVidContinuousFrameType(VendorVidFrameDesc); - } - else - { - DisplayVendorVidDiscreteFrameType(VendorVidFrameDesc); - } - // This descriptor is deprecated for UVC 1.1 -#ifdef H264_SUPPORT - if (UVC10 != g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC version >= 1.1 devices\r\n"); - } -#else - if (UVC11 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.1 devices\r\n"); - } -#endif - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVendorVidContinuousFrameType() -// -//***************************************************************************** - -BOOL -DisplayVendorVidContinuousFrameType( - PVIDEO_FRAME_VENDOR VContinuousDesc - ) -{ - //@@DisplayVendorVidContinuousFrameType -Vendor Video Continuous Frame - ULONG dwMinFrameInterval = VContinuousDesc->adwFrameInterval[0]; - ULONG dwMaxFrameInterval = VContinuousDesc->adwFrameInterval[1]; - ULONG dwFrameIntervalStep = VContinuousDesc->adwFrameInterval[2]; - - AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - - AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMinFrameInterval, - ((double)dwMinFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); - - AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMaxFrameInterval, - ((double)dwMaxFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); - AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); - - if (dwMinFrameInterval == 0 ) - { - //@@TestCase B30.2 (descript.c line 1388) - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval - //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (dwMaxFrameInterval == 0 ) - { - //@@TestCase B30.3 (descript.c line 1388) - //@@ERROR - //@@Descriptor Field - dwMaxFrameInterval - //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if(dwMinFrameInterval > dwMaxFrameInterval) - { - //@@TestCase B30.4 (descript.c line 1405) - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval - AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); - OOPS(); - } - else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) - { - //@@TestCase B30.5 - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) - { - //@@TestCase B30.6 - //@@CAUTION - //@@Descriptor Field - dwFrameIntervalStep - //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero - AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) - { - //@@TestCase B30.7 (descript.c line 1414) - //@@ERROR - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep - AppendTextBuffer("*!*ERROR: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); - OOPS(); - } - - if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) - { - //@@TestCase B30.8 (descript.c line 1394) - //@@ERROR - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval - AppendTextBuffer("*!*ERROR: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between \r\n dwMinFrameInterval and dwMaxFrameInterval\r\n"); - OOPS(); - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVendorVidDiscreteFrameType() -// -//***************************************************************************** - -BOOL -DisplayVendorVidDiscreteFrameType( - PVIDEO_FRAME_VENDOR VDiscreteDesc - ) -{ - //@@DisplayVendorVidDiscreteFrameType -Vendor Video Discrete Frame - UINT iNdex = 1; - UINT iCurFrame = 0; - ULONG * ulFrameInterval = NULL; - - AppendTextBuffer("===>Additional Discrete Frame TypeData\r\n"); - - // There are (VDiscreteDesc->bFrameIntervalType) dwFrameIntervals - for (; iNdex <= VDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) - { - ulFrameInterval = &VDiscreteDesc->adwFrameInterval[iCurFrame]; - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - iNdex, *ulFrameInterval, - ((double)*ulFrameInterval)/10000.0, - (10000000.0/((double)*ulFrameInterval)) - ); - if (0 == *ulFrameInterval) - { - //@@TestCase B31.1 (descript.c line 1061) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[x] must be non-zero - AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); - OOPS(); - } - if ((iNdex > 1)&&(*ulFrameInterval <= VDiscreteDesc->adwFrameInterval[iCurFrame - 1])) - { - //@@TestCase B31.2 (descript.c line 1067) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] - AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ - "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); - OOPS(); - } - } - - return TRUE; -} - -//***************************************************************************** -// -// DisplayFramePayloadFormat() -// -//***************************************************************************** - -BOOL -DisplayFramePayloadFormat ( - PVIDEO_FORMAT_FRAME FramePayloadFormatDesc - ) -{ - //@@DisplayFramePayloadFormat - FrameBased Payload Format - PCHAR pStr = NULL; - OLECHAR szGUID[256]; - int i = 0; - - // Initialize the default Frame - g_chFrameBasedFrameDefault = FramePayloadFormatDesc->bDefaultFrameIndex; - - memset((LPOLESTR) szGUID, 0, sizeof(OLECHAR) * 256); - i = StringFromGUID2((REFGUID) &FramePayloadFormatDesc->guidFormat, (LPOLESTR) szGUID, 255); - i++; - - AppendTextBuffer("\r\n ===>Video Streaming Frame Based Payload Format Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X\r\n", FramePayloadFormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", FramePayloadFormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", FramePayloadFormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X\r\n", FramePayloadFormatDesc->bFormatIndex); - AppendTextBuffer("bNumFrameDescriptors: 0x%02X\r\n", FramePayloadFormatDesc->bNumFrameDescriptors); - AppendTextBuffer("guidFormat: %S", szGUID); - - pStr = VidFormatGUIDCodeToName((REFGUID) &FramePayloadFormatDesc->guidFormat); - if ( pStr ) - { - if ( gDoAnnotation ) - { - AppendTextBuffer(" = %s Format", pStr); - } - } - AppendTextBuffer("\r\n"); - AppendTextBuffer("bBitsPerPixel: 0x%02X\r\n", FramePayloadFormatDesc->bBitsPerPixel); - AppendTextBuffer("bDefaultFrameIndex: 0x%02X\r\n", FramePayloadFormatDesc->bDefaultFrameIndex); - - if (FramePayloadFormatDesc->bLength != sizeof(VIDEO_FORMAT_FRAME)) - { - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required - //@@length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - FramePayloadFormatDesc->bLength, - sizeof(VIDEO_FORMAT_FRAME)); - OOPS(); - } - - if (FramePayloadFormatDesc->bFormatIndex == 0 ) - { - //@@ERROR - //@@Descriptor Field - bFormatIndex - //@@bFormatIndex is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bFormatIndex = 0, this is a 1 based index\r\n"); - OOPS(); - } - - if (FramePayloadFormatDesc->bNumFrameDescriptors == 0 ) - { - //@@ERROR - //@@Descriptor Field - bNumFrameDescriptors - //@@bNumFrameDescriptors is set to zero which is not in accordance with the - //@@USB Video Device Specification - AppendTextBuffer("*!*ERROR: bNumFrameDescriptors = 0, must have at least 1 Frame descriptor\r\n"); - OOPS(); - } - - if(!(pStr)) - { - //@@WARNING - //@@Descriptor Field - guidFormat - //@@guidFormat is set to unknown or undefined format - AppendTextBuffer("\r\n*!*WARNING: guidFormat is an unknown format\r\n"); - OOPS(); - } - - if (FramePayloadFormatDesc->bBitsPerPixel == 0 ) - { - //@@ERROR - //@@Descriptor Field - bBitsPerPixel - //@@bBitsPerPixel is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bBitsPerPixel = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (FramePayloadFormatDesc->bDefaultFrameIndex == 0 || FramePayloadFormatDesc->bDefaultFrameIndex > - FramePayloadFormatDesc->bNumFrameDescriptors) - { - //@@ERROR - //@@Descriptor Field - bDefaultFrameIndex - //@@The value for bDefaultFrameIndex is not greater than 0 or less than or equal to bNumFrameDescriptors - AppendTextBuffer("*!*ERROR: The value %d for the bDefaultFrameIndex is out of range, this invalidates the descriptor\r\n*!*The proper range is 1 to %d)", - FramePayloadFormatDesc->bDefaultFrameIndex, - FramePayloadFormatDesc->bNumFrameDescriptors); - OOPS(); - } - - AppendTextBuffer("bAspectRatioX: 0x%02X\r\n", - FramePayloadFormatDesc->bAspectRatioX); - AppendTextBuffer("bAspectRatioY: 0x%02X", - FramePayloadFormatDesc->bAspectRatioY); - - if (((FramePayloadFormatDesc->bmInterlaceFlags & 0x01) && - (FramePayloadFormatDesc->bAspectRatioY != 0 && - FramePayloadFormatDesc->bAspectRatioX != 0))) - { - if(gDoAnnotation) - { - AppendTextBuffer(" -> Aspect Ratio is set for a %d:%d display", - (FramePayloadFormatDesc->bAspectRatioX),(FramePayloadFormatDesc->bAspectRatioY)); - } - else - { - if (FramePayloadFormatDesc->bAspectRatioY != 0 || FramePayloadFormatDesc->bAspectRatioX != 0) - { - //@@ERROR - //@@Descriptor Field - bAspectRatioX, bAspectRatioY - //@@Verify that that bAspectRatioX and bAspectRatioY are set to zero - //@@ if stream is non-interlaced - AppendTextBuffer("\r\n*!*ERROR: Both bAspectRatioX and bAspectRatioY "\ - "must equal 0 if stream is non-interlaced"); - OOPS(); - } - } - } - AppendTextBuffer("\r\nbmInterlaceFlags: 0x%02X\r\n", - FramePayloadFormatDesc->bmInterlaceFlags); - - if (gDoAnnotation) - { - AppendTextBuffer(" D0 = 0x%02X Interlaced stream or variable: %s\r\n", - (FramePayloadFormatDesc->bmInterlaceFlags & 1), - (FramePayloadFormatDesc->bmInterlaceFlags & 1) ? "Yes" : "No"); - AppendTextBuffer(" D1 = 0x%02X Fields per frame: %s\r\n", - ((FramePayloadFormatDesc->bmInterlaceFlags >> 1) & 1), - ((FramePayloadFormatDesc->bmInterlaceFlags >> 1) & 1) ? "1 field" : "2 fields"); - AppendTextBuffer(" D2 = 0x%02X Field 1 first: %s\r\n", - ((FramePayloadFormatDesc->bmInterlaceFlags >> 2) & 1), - ((FramePayloadFormatDesc->bmInterlaceFlags >> 2) & 1) ? "Yes" : "No"); - //@@Descriptor Field - bmInterlaceFlags - //@@Validate that reserved bits (D3) are set to zero. - AppendTextBuffer(" D3 = 0x%02X Reserved%s\r\n", - ((FramePayloadFormatDesc->bmInterlaceFlags >> 3) & 1), - ((FramePayloadFormatDesc->bmInterlaceFlags >> 3) & 1) ? - "\r\n*!*ERROR: Reserved to 0" : "" ); - AppendTextBuffer(" D4..5 = 0x%02X Field patterns ->", - ((FramePayloadFormatDesc->bmInterlaceFlags >> 4) & 3)); - switch(FramePayloadFormatDesc->bmInterlaceFlags & 0x30) - { - case 0x00: - AppendTextBuffer(" Field 1 only"); - break; - case 0x10: - AppendTextBuffer(" Field 2 only"); - break; - case 0x20: - AppendTextBuffer(" Regular Pattern of fields 1 and 2"); - break; - case 0x30: - AppendTextBuffer(" Random Pattern of fields 1 and 2"); - break; - } - AppendTextBuffer("\r\n D6..7 = 0x%02X Display Mode ->", - ((FramePayloadFormatDesc->bmInterlaceFlags >> 6) & 3)); - - switch(FramePayloadFormatDesc->bmInterlaceFlags & 0xC0) - { - case 0x00: - AppendTextBuffer(" Bob only"); - break; - case 0x40: - AppendTextBuffer(" Weave only"); - break; - case 0x80: - AppendTextBuffer(" Bob or weave"); - break; - case 0xC0: - //@@Descriptor Field - bmInterlaceFlags - //@@Question - Should we validate that reserved bits are set to zero? - AppendTextBuffer(" Reserved"); - break; - } - } - - //@@Descriptor Field - bCopyProtect - //@@Question - Are their reserved bits and should we validate that - //@@ reserved bits are set to zero? - AppendTextBuffer("\r\nbCopyProtect: 0x%02X", - FramePayloadFormatDesc->bCopyProtect); - if (gDoAnnotation) - { - if (FramePayloadFormatDesc->bCopyProtect) - AppendTextBuffer(" -> Duplication Restricted"); - else - AppendTextBuffer(" -> Duplication Unrestricted"); - } - - //@@Descriptor Field - bVariableSize - AppendTextBuffer("\r\nbVariableSize: 0x%02X", - FramePayloadFormatDesc->bVariableSize); - if (gDoAnnotation) - { - if (FramePayloadFormatDesc->bVariableSize) - AppendTextBuffer(" -> Variable Size"); - else - AppendTextBuffer(" -> Fixed Size"); - } - AppendTextBuffer("\r\n"); - - // Check that the correct number of Frame Descriptors and one Color Matching - // descriptor follow - CheckForColorMatchingDesc ((PVIDEO_SPECIFIC) FramePayloadFormatDesc, - FramePayloadFormatDesc->bNumFrameDescriptors, VS_FRAME_FRAME_BASED); - - // This descriptor is new for UVC 1.1 - if (UVC10 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.0 devices\r\n"); - } - return TRUE; - } - - -//***************************************************************************** -// -// DisplayFramePayloadFrame() -// -//***************************************************************************** - -BOOL -DisplayFramePayloadFrame ( - PVIDEO_FRAME_FRAME FramePayloadFrameDesc - ) -{ - size_t bLength = 0; - bLength = SizeOfVideoFrameFrame(FramePayloadFrameDesc); - - //@@DisplayFramePayloadFrame -Frame Based Payload Frame - - AppendTextBuffer("\r\n ===>Video Streaming Frame Based Payload Frame Type Descriptor<===\r\n"); - if (gDoAnnotation) - { - if(FramePayloadFrameDesc->bFrameIndex == g_chFrameBasedFrameDefault) - { - AppendTextBuffer(" --->This is the Default (optimum) Frame index\r\n"); - } - } - AppendTextBuffer("bLength: 0x%02X\r\n", FramePayloadFrameDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", FramePayloadFrameDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", FramePayloadFrameDesc->bDescriptorSubtype); - AppendTextBuffer("bFrameIndex: 0x%02X\r\n", FramePayloadFrameDesc->bFrameIndex); - AppendTextBuffer("bmCapabilities: 0x%02X\r\n", FramePayloadFrameDesc->bmCapabilities); - AppendTextBuffer("wWidth: 0x%04X = %d\r\n", FramePayloadFrameDesc->wWidth, FramePayloadFrameDesc->wWidth); - AppendTextBuffer("wHeight: 0x%04X = %d\r\n", FramePayloadFrameDesc->wHeight, FramePayloadFrameDesc->wHeight); - AppendTextBuffer("dwMinBitRate: 0x%08X\r\n", FramePayloadFrameDesc->dwMinBitRate); - AppendTextBuffer("dwMaxBitRate: 0x%08X\r\n", FramePayloadFrameDesc->dwMaxBitRate); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - FramePayloadFrameDesc->dwDefaultFrameInterval, - ((double)FramePayloadFrameDesc->dwDefaultFrameInterval)/10000.0, - (10000000.0/((double)FramePayloadFrameDesc->dwDefaultFrameInterval)) - ); - AppendTextBuffer("bFrameIntervalType: 0x%02X\r\n", FramePayloadFrameDesc->bFrameIntervalType); - - if (FramePayloadFrameDesc->bLength != bLength) - { - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required - //@@length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d\r\n", - FramePayloadFrameDesc->bLength, bLength); - OOPS(); - } - - if (FramePayloadFrameDesc->bFrameIndex == 0 ) - { - //@@ERROR - //@@Descriptor Field - bFrameIndex - //@@bFrameIndex must be nonzero - AppendTextBuffer("*!*ERROR: bFrameIndex = 0, this is a 1 based index\r\n"); - OOPS(); - } - - //@@Descriptor Field - bmCapabilities - //@@Question: Should we try to verify that bmCapabilities is valid? - // AppendTextBuffer("bmCapabilities: 0x%02X\r\n", UnCompFrameDesc->bmCapabilities); - - if (FramePayloadFrameDesc->wWidth == 0 ) - { - //@@ERROR - //@@Descriptor Field - wWidth - //@@wWidth must be nonzero - AppendTextBuffer("*!*ERROR: wWidth must be nonzero\r\n"); - OOPS(); - } - - if (FramePayloadFrameDesc->wHeight == 0 ) - { - //@@ERROR - //@@Descriptor Field - wHeight - //@@wHeight must be nonzero - AppendTextBuffer("*!*ERROR: wHeight must be nonzero\r\n"); - OOPS(); - } - - if (FramePayloadFrameDesc->dwMinBitRate == 0 ) - { - //@@ERROR - //@@Descriptor Field - dwMinBitRate - //@@dwMinBitRate must be nonzero - AppendTextBuffer("*!*ERROR: dwMinBitRate must be nonzero\r\n"); - OOPS(); - } - - if (FramePayloadFrameDesc->dwMaxBitRate == 0 ) - { - //@@ERROR - //@@Descriptor Field - dwMaxBitRate - //@@dwMaxBitRate must be nonzero - AppendTextBuffer("*!*ERROR: dwMaxBitRate must be nonzero\r\n"); - OOPS(); - } - - if(FramePayloadFrameDesc->dwMinBitRate > FramePayloadFrameDesc->dwMaxBitRate) - { - //@@ERROR - //@@Descriptor Field - dwMinBitRate and dwMaxBitRate - //@@Verify that dwMaxBitRate is greater than dwMinBitRate - AppendTextBuffer("*!*ERROR: dwMinBitRate should be less than dwMaxBitRate\r\n"); - OOPS(); - } - else - { - if (FramePayloadFrameDesc->bFrameIntervalType == 1 && - FramePayloadFrameDesc->dwMinBitRate != FramePayloadFrameDesc->dwMaxBitRate) - { - //@@WARNING - //@@Descriptor Field - bFrameIntervalType, dwMinBitRate, and dwMaxBitRate - //@@Verify that dwMaxBitRate is equal to dwMinBitRate if bFrameIntervalType is 1 - AppendTextBuffer("*!*WARNING: if bFrameIntervalType is 1 then dwMinBitRate "\ - "should equal dwMaxBitRate\r\n"); - OOPS(); - } - } - - if (FramePayloadFrameDesc->dwDefaultFrameInterval == 0 ) - { - //@@TestCase B16.11 (descript.c line 1020) - //@@WARNING - //@@Descriptor Field - dwDefaultFrameInterval - //@@dwDefaultFrameInterval must be nonzero - AppendTextBuffer("*!*WARNING: dwDefaultFrameInterval must be nonzero\r\n"); - OOPS(); - } - - if (0 == FramePayloadFrameDesc->bFrameIntervalType) - { - DisplayFramePayloadContinuousFrameType(FramePayloadFrameDesc); - } - else - { - DisplayFramePayloadDiscreteFrameType(FramePayloadFrameDesc); - } - // This descriptor is new for UVC 1.1 - if (UVC10 == g_chUVCversion) - { - AppendTextBuffer("*!*ERROR: This format is NOT ALLOWED for UVC 1.0 devices\r\n"); - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayFramePayloadContinuousFrameType() -// -//***************************************************************************** - -BOOL -DisplayFramePayloadContinuousFrameType( - PVIDEO_FRAME_FRAME FContinuousDesc - ) -{ - //@@DisplayFramePayloadContinuousFrameType -Frame Payload Continuous Frame - ULONG dwMinFrameInterval = FContinuousDesc->adwFrameInterval[0]; - ULONG dwMaxFrameInterval = FContinuousDesc->adwFrameInterval[1]; - ULONG dwFrameIntervalStep = FContinuousDesc->adwFrameInterval[2]; - - AppendTextBuffer("===>Additional Continuous Frame Type Data\r\n"); - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - - AppendTextBuffer("dwMinFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMinFrameInterval, - ((double)dwMinFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMinFrameInterval) + 0.5)); - - AppendTextBuffer("dwMaxFrameInterval: 0x%08X = %lf mSec (%d Hz)\r\n", - dwMaxFrameInterval, - ((double)dwMaxFrameInterval)/10000.0, - (ULONG)(10000000.0/((double)dwMaxFrameInterval) + 0.5)); - - AppendTextBuffer("dwFrameIntervalStep: 0x%08X\r\n", dwFrameIntervalStep); - - if (dwMinFrameInterval == 0 ) - { - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval - //@@dwMinFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMinFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if (dwMaxFrameInterval == 0 ) - { - //@@ERROR - //@@Descriptor Field - dwMaxFrameInterval - //@@dwMaxFrameInterval is set to zero which is not in accordance with the USB Video Device Specification - AppendTextBuffer("*!*ERROR: dwMaxFrameInterval = 0, this invalidates the descriptor\r\n"); - OOPS(); - } - - if(dwMinFrameInterval > dwMaxFrameInterval) - { - //@@ERROR - //@@Descriptor Field - dwMinFrameInterval and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval - AppendTextBuffer("*!*ERROR: dwMinFrameInterval is larger that dwMaxFrameInterval, this invalidates the descriptor\r\n"); - OOPS(); - } - else if ((dwMinFrameInterval + dwFrameIntervalStep) > dwMaxFrameInterval) - { - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that dwMaxFrameInterval is greater than dwMinFrameInterval combined with dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMinFrameInterval + dwFrameIntervalStep is greater than dwMaxFrameInterval, this could cause problems\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) == 0 ) - { - //@@CAUTION - //@@Descriptor Field - dwFrameIntervalStep - //@@Suggestion to use descrite frames if dwFrameIntervalStep is zero - AppendTextBuffer("*!*CAUTION: dwFrameIntervalStep equals zero, consider using discrete frames\r\n"); - OOPS(); - } - else if ((dwMaxFrameInterval - dwMinFrameInterval) % dwFrameIntervalStep ) - { - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the difference between dwMaxFrameInterval and dwMinFrameInterval is evenly divisible by dwFrameIntervalStep - AppendTextBuffer("*!*WARNING: dwMaxFrameInterval minus dwMinFrameInterval is not evenly divisible by dwFrameIntervalStep, this could cause problems\r\n"); - OOPS(); - } - - if (dwFrameIntervalStep == 0 && (dwMaxFrameInterval - dwMinFrameInterval)) - { - //@@WARNING - //@@Descriptor Field - dwFrameIntervalStep, dwMinFrameInterval, and dwMaxFrameInterval - //@@Verify that the dwFrameIntervalStep is not zero if there is a difference between dwMaxFrameInterval and dwMinFrameInterval - AppendTextBuffer("*!*WARNING: dwFrameIntervalStep = 0, this invalidates the descriptor when there is a difference between dwMinFrameInterval and dwMaxFrameInterval\r\n"); - OOPS(); - } - - return TRUE; -} - -//***************************************************************************** -// -// DisplayFramePayloadDiscreteFrameType() -// -//***************************************************************************** - -BOOL -DisplayFramePayloadDiscreteFrameType( - PVIDEO_FRAME_FRAME FDiscreteDesc - ) -{ - //@@DisplayFramePayloadDiscreteFrameType -Frame Based Payload Discrete Frame - UINT iNdex = 1; - UINT iCurFrame = 0; - ULONG * ulFrameInterval = NULL; - - AppendTextBuffer("===>Additional Discrete Frame Type Data\r\n"); - - // There are (UDiscreteDesc->bFrameIntervalType) dwFrameIntervals (1 based index) - for (; iNdex <= FDiscreteDesc->bFrameIntervalType; iNdex++, iCurFrame++) - { - ulFrameInterval = &FDiscreteDesc->adwFrameInterval[iCurFrame]; - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - AppendTextBuffer("dwFrameInterval[%d]: 0x%08X = %lf mSec (%4.2f Hz)\r\n", - iNdex, *ulFrameInterval, - ((double)*ulFrameInterval)/10000.0, - (10000000.0/((double)*ulFrameInterval)) - ); - if (0 == *ulFrameInterval) - { - //@@TestCase B18.1 (descript.c line 1061) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[x] must be non-zero - AppendTextBuffer("*!*ERROR: dwFrameInterval[%d] must be non-zero\r\n", iNdex); - OOPS(); - } - if ((iNdex > 1)&&(*ulFrameInterval <= FDiscreteDesc->adwFrameInterval[iCurFrame - 1])) - { - //@@TestCase B18.2 (descript.c line 1067) - //@@ERROR - //@@Descriptor Field - dwFrameInterval[x] - //@@dwFrameInterval[n] must be greater than dwFrameInterval[n - 1] - AppendTextBuffer("*!*ERROR: dwFrameInterval[0x%02X] must be "\ - "greater than preceding dwFrameInterval[0x%02X]\r\n", iNdex, iNdex - 1); - OOPS(); - } - } - return TRUE; -} - -//***************************************************************************** -// -// DisplayVSEndpoint() -// -//***************************************************************************** - -BOOL -DisplayVSEndpoint ( - PVIDEO_CS_INTERRUPT VidEndpointDesc - ) -{ - //@@DisplayVSEndpoint - Video Streaming Endpoint - AppendTextBuffer("\r\n ===>Class-specific VC Interrupt Endpoint Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X \r\n", VidEndpointDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X\r\n", VidEndpointDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X\r\n", VidEndpointDesc->bDescriptorSubtype); - AppendTextBuffer("wMaxTransferSize: 0x%04X", VidEndpointDesc->wMaxTransferSize); - if(gDoAnnotation) { - AppendTextBuffer(" = (%d) Bytes\r\n", VidEndpointDesc->wMaxTransferSize);} - else {AppendTextBuffer("\r\n");} - - if (VidEndpointDesc->bLength != sizeof(VIDEO_CS_INTERRUPT)) - { - //@@TestCase B32.1 (descript.c line 1616) - //@@ERROR - //@@Descriptor Field - bLength - //@@The declared length in the device descriptor is not equal to the required length in the USB Video Device Specification - AppendTextBuffer("*!*ERROR: bLength of %d incorrect, should be %d. USBView cannot correctly display descriptor\r\n", - VidEndpointDesc->bLength, - sizeof(VIDEO_CS_INTERRUPT)); - OOPS(); - } - - return TRUE; -} - -//***************************************************************************** -// -// VDisplayBytes() -// -//***************************************************************************** - -VOID -VDisplayBytes ( - PUCHAR Data, - USHORT Len - ) -{ - USHORT i = 0; - - for (i = 0; i < Len; i++) - { - AppendTextBuffer("0x%02X ", Data[i]); - - if (i % 16 == 15) - { - AppendTextBuffer("\r\n"); - } - } - - if (i % 16 != 0) - { - AppendTextBuffer("\r\n"); - } -} - -//***************************************************************************** -// -// VidFormatGUIDCodeToName() -// -//***************************************************************************** - - -PCHAR -VidFormatGUIDCodeToName ( - REFGUID VidFormatGUIDCode - ) -{ - // GUID pYUY2 = YUY2_Format; - // GUID pNV12 = NV12_Format; - if (IsEqualGUID(VidFormatGUIDCode, (REFGUID) &YUY2_Format)) - { - return (PCHAR) &"YUY2"; - } - if (IsEqualGUID(VidFormatGUIDCode, (REFGUID) &NV12_Format)) - { - return (PCHAR) &"NV12"; - } -#ifdef H264_SUPPORT - // GUID pH264 = H264_Format; - if (IsEqualGUID(VidFormatGUIDCode, (REFGUID) &H264_Format)) - { - return (PCHAR) &"H.264"; - } -#endif - - return FALSE; -} - -/***************************************************************************** - -GetVCInterfaceSize() - -*****************************************************************************/ - -UINT -GetVCInterfaceSize ( - PVIDEO_CONTROL_HEADER_UNIT VCInterfaceDesc - ) -{ - PUSB_COMMON_DESCRIPTOR commonDesc = (PUSB_COMMON_DESCRIPTOR) VCInterfaceDesc; - PUCHAR descEnd = (PUCHAR) VCInterfaceDesc + VCInterfaceDesc->wTotalLength; - UINT uCount = 0; - - // return this interface's sum of descriptor lengths - // starting from this header until (and not including) the first endpoint - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - if (commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) - break; - uCount += commonDesc->bLength; - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - return (uCount); -} - -/***************************************************************************** - -CheckForColorMatchingDesc () - -Given starting address of format descriptor; -number of frame descriptors; -subtype of frame to look for; - -1) walk through each descriptor -= if desc is frame of given subtype, update counter -= if desc is still frame, update counter -= if desc is color matching descriptor, update counter -! if frame is something else, break (all these frames should be consecutive) -! if next frame is beyond ending address of configuration, break - -PASS -frame count == numframes passed in -color match == 1 -still frames are handled in the video stream input header and the frame displays - -*****************************************************************************/ - -UINT -CheckForColorMatchingDesc ( - PVIDEO_SPECIFIC pFormatDesc, - UCHAR bNumFrameDescriptors, - UCHAR bDescriptorSubtype - ) -{ - UINT uFrameCount = 0; - UINT uStillFrameCount = 0; - UINT uColorCount = 0; - - // DONE if the descriptor address is beyond the configuration range - for ( ; ValidateDescAddress ((PUSB_COMMON_DESCRIPTOR) pFormatDesc); ) - { - // DONE if it's not an interface desc - if (CS_INTERFACE != pFormatDesc->bDescriptorType) - { - break; - } - switch (pFormatDesc->bDescriptorSubtype) - { - case VS_STILL_IMAGE_FRAME: - uStillFrameCount++; - break; - case VS_COLORFORMAT: - uColorCount++; - break; - default: - if (bDescriptorSubtype == pFormatDesc->bDescriptorSubtype) - { - uFrameCount++; - } - break; - } - pFormatDesc = (PVIDEO_SPECIFIC) ((PUCHAR) pFormatDesc + pFormatDesc->bLength); - } - if (uFrameCount != bNumFrameDescriptors) - { - AppendTextBuffer("*!*ERROR: Found %d frame descriptors (should be %d)\r\n", - uFrameCount, bNumFrameDescriptors); - } - // We already check Still Frames in the Video Info Header and Still Frames displays - if (0 == uColorCount) - { - AppendTextBuffer("*!*ERROR: no Color Matching Descriptor for this format\r\n"); - } - return (uColorCount); -} - -/***************************************************************************** - -GetVSInterfaceSize() - -*****************************************************************************/ - -UINT -GetVSInterfaceSize ( - PUSB_COMMON_DESCRIPTOR VidInHeaderDesc, - USHORT wTotalLength - ) -{ - PUSB_COMMON_DESCRIPTOR commonDesc = (PUSB_COMMON_DESCRIPTOR) VidInHeaderDesc; - PUCHAR descEnd = (PUCHAR) VidInHeaderDesc + wTotalLength; - UINT uCount = 0; - - // return this interface's sum of descriptor lengths - // starting from this header until (and not including) the first endpoint - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - if (commonDesc->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) - break; - uCount += commonDesc->bLength; - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - return (uCount); -} - -/***************************************************************************** - -ValidateTerminalID() - -*****************************************************************************/ - -BOOL -ValidateTerminalID( - UINT uTerminalID - ) -{ - UNREFERENCED_PARAMETER(uTerminalID); - return (TRUE); -} diff --git a/tests/projects/winsdk/usbview/enum.c b/tests/projects/winsdk/usbview/enum.c deleted file mode 100644 index 314a08806..000000000 --- a/tests/projects/winsdk/usbview/enum.c +++ /dev/null @@ -1,3366 +0,0 @@ -/*++ - -Copyright (c) 1997-2011 Microsoft Corporation - -Module Name: - - ENUM.C - -Abstract: - - This source file contains the routines which enumerate the USB bus - and populate the TreeView control. - - The enumeration process goes like this: - - (1) Enumerate Host Controllers and Root Hubs - EnumerateHostControllers() - EnumerateHostController() - Host controllers currently have symbolic link names of the form HCDx, - where x starts at 0. Use CreateFile() to open each host controller - symbolic link. Create a node in the TreeView to represent each host - controller. - - GetRootHubName() - After a host controller has been opened, send the host controller an - IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of - the root hub that is part of the host controller. - - (2) Enumerate Hubs (Root Hubs and External Hubs) - EnumerateHub() - Given the name of a hub, use CreateFile() to map the hub. Send the - hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the - hub, such as the number of downstream ports. Create a node in the - TreeView to represent each hub. - - (3) Enumerate Downstream Ports - EnumerateHubPorts() - Given an handle to an open hub and the number of downstream ports on - the hub, send the hub an IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX - request for each downstream port of the hub to get info about the - device (if any) attached to each port. If there is a device attached - to a port, send the hub an IOCTL_USB_GET_NODE_CONNECTION_NAME request - to get the symbolic link name of the hub attached to the downstream - port. If there is a hub attached to the downstream port, recurse to - step (2). - - GetAllStringDescriptors() - GetConfigDescriptor() - Create a node in the TreeView to represent each hub port - and attached device. - - -Environment: - - user mode - -Revision History: - - 04-25-97 : created - ---*/ - -//***************************************************************************** -// I N C L U D E S -//***************************************************************************** - -#include "uvcview.h" - -//***************************************************************************** -// D E F I N E S -//***************************************************************************** - -#define NUM_STRING_DESC_TO_GET 32 - -//***************************************************************************** -// L O C A L F U N C T I O N P R O T O T Y P E S -//***************************************************************************** - -VOID -EnumerateHostControllers ( - HTREEITEM hTreeParent, - ULONG *DevicesConnected -); - -VOID -EnumerateHostController ( - HTREEITEM hTreeParent, - HANDLE hHCDev, - _Inout_ PCHAR leafName, - _In_ HANDLE deviceInfo, - _In_ PSP_DEVINFO_DATA deviceInfoData -); - -VOID -EnumerateHub ( - HTREEITEM hTreeParent, - _In_reads_(cbHubName) PCHAR HubName, - _In_ size_t cbHubName, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2, - _In_opt_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, - _In_opt_ PUSB_DESCRIPTOR_REQUEST ConfigDesc, - _In_opt_ PUSB_DESCRIPTOR_REQUEST BosDesc, - _In_opt_ PSTRING_DESCRIPTOR_NODE StringDescs, - _In_opt_ PUSB_DEVICE_PNP_STRINGS DevProps -); - -VOID -EnumerateHubPorts ( - HTREEITEM hTreeParent, - HANDLE hHubDevice, - ULONG NumPorts -); - -PCHAR GetRootHubName ( - HANDLE HostController -); - -PCHAR GetExternalHubName ( - HANDLE Hub, - ULONG ConnectionIndex -); - -PCHAR GetHCDDriverKeyName ( - HANDLE HCD -); - -PCHAR GetDriverKeyName ( - HANDLE Hub, - ULONG ConnectionIndex -); - -PUSB_DESCRIPTOR_REQUEST -GetConfigDescriptor ( - HANDLE hHubDevice, - ULONG ConnectionIndex, - UCHAR DescriptorIndex - ); - -PUSB_DESCRIPTOR_REQUEST -GetBOSDescriptor ( - HANDLE hHubDevice, - ULONG ConnectionIndex - ); - -DWORD -GetHostControllerPowerMap( - HANDLE hHCDev, - PUSBHOSTCONTROLLERINFO hcInfo); - -DWORD -GetHostControllerInfo( - HANDLE hHCDev, - PUSBHOSTCONTROLLERINFO hcInfo); - -PCHAR WideStrToMultiStr ( - _In_reads_bytes_(cbWideStr) PWCHAR WideStr, - _In_ size_t cbWideStr - ); - -BOOL -AreThereStringDescriptors ( - PUSB_DEVICE_DESCRIPTOR DeviceDesc, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc -); - -PSTRING_DESCRIPTOR_NODE -GetAllStringDescriptors ( - HANDLE hHubDevice, - ULONG ConnectionIndex, - PUSB_DEVICE_DESCRIPTOR DeviceDesc, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc -); - -PSTRING_DESCRIPTOR_NODE -GetStringDescriptor ( - HANDLE hHubDevice, - ULONG ConnectionIndex, - UCHAR DescriptorIndex, - USHORT LanguageID -); - -HRESULT -GetStringDescriptors ( - _In_ HANDLE hHubDevice, - _In_ ULONG ConnectionIndex, - _In_ UCHAR DescriptorIndex, - _In_ ULONG NumLanguageIDs, - _In_reads_(NumLanguageIDs) USHORT *LanguageIDs, - _In_ PSTRING_DESCRIPTOR_NODE StringDescNodeHead -); - -void -EnumerateAllDevices(); - - -void -EnumerateAllDevicesWithGuid( - PDEVICE_GUID_LIST DeviceList, - LPGUID Guid - ); - -void -FreeDeviceInfoNode( - _In_ PDEVICE_INFO_NODE *ppNode - ); - -PDEVICE_INFO_NODE -FindMatchingDeviceNodeForDriverName( - _In_ PSTR DriverKeyName, - _In_ BOOLEAN IsHub - ); - - -//***************************************************************************** -// G L O B A L S -//***************************************************************************** - -// List of enumerated host controllers. -// -LIST_ENTRY EnumeratedHCListHead = -{ - &EnumeratedHCListHead, - &EnumeratedHCListHead -}; - -DEVICE_GUID_LIST gHubList; -DEVICE_GUID_LIST gDeviceList; - - -//***************************************************************************** -// G L O B A L S P R I V A T E T O T H I S F I L E -//***************************************************************************** - -PCHAR ConnectionStatuses[] = -{ - "", // 0 - NoDeviceConnected - "", // 1 - DeviceConnected - "FailedEnumeration", // 2 - DeviceFailedEnumeration - "GeneralFailure", // 3 - DeviceGeneralFailure - "Overcurrent", // 4 - DeviceCausedOvercurrent - "NotEnoughPower", // 5 - DeviceNotEnoughPower - "NotEnoughBandwidth", // 6 - DeviceNotEnoughBandwidth - "HubNestedTooDeeply", // 7 - DeviceHubNestedTooDeeply - "InLegacyHub", // 8 - DeviceInLegacyHub - "Enumerating", // 9 - DeviceEnumerating - "Reset" // 10 - DeviceReset -}; - -ULONG TotalDevicesConnected; - - -//***************************************************************************** -// -// EnumerateHostControllers() -// -// hTreeParent - Handle of the TreeView item under which host controllers -// should be added. -// -//***************************************************************************** - -VOID -EnumerateHostControllers ( - HTREEITEM hTreeParent, - ULONG *DevicesConnected -) -{ - HANDLE hHCDev = NULL; - HDEVINFO deviceInfo = NULL; - SP_DEVINFO_DATA deviceInfoData; - SP_DEVICE_INTERFACE_DATA deviceInterfaceData; - PSP_DEVICE_INTERFACE_DETAIL_DATA deviceDetailData = NULL; - ULONG index = 0; - ULONG requiredLength = 0; - BOOL success; - - TotalDevicesConnected = 0; - TotalHubs = 0; - - EnumerateAllDevices(); - - // Iterate over host controllers using the new GUID based interface - // - deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER, - NULL, - NULL, - (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); - - deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - for (index=0; - SetupDiEnumDeviceInfo(deviceInfo, - index, - &deviceInfoData); - index++) - { - deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - success = SetupDiEnumDeviceInterfaces(deviceInfo, - 0, - (LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER, - index, - &deviceInterfaceData); - - if (!success) - { - OOPS(); - break; - } - - success = SetupDiGetDeviceInterfaceDetail(deviceInfo, - &deviceInterfaceData, - NULL, - 0, - &requiredLength, - NULL); - - if (!success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) - { - OOPS(); - break; - } - - deviceDetailData = ALLOC(requiredLength); - if (deviceDetailData == NULL) - { - OOPS(); - break; - } - - deviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - - success = SetupDiGetDeviceInterfaceDetail(deviceInfo, - &deviceInterfaceData, - deviceDetailData, - requiredLength, - &requiredLength, - NULL); - - if (!success) - { - OOPS(); - break; - } - - hHCDev = CreateFile(deviceDetailData->DevicePath, - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL); - - // If the handle is valid, then we've successfully opened a Host - // Controller. Display some info about the Host Controller itself, - // then enumerate the Root Hub attached to the Host Controller. - // - if (hHCDev != INVALID_HANDLE_VALUE) - { - EnumerateHostController(hTreeParent, - hHCDev, - deviceDetailData->DevicePath, - deviceInfo, - &deviceInfoData); - - CloseHandle(hHCDev); - } - - FREE(deviceDetailData); - } - - SetupDiDestroyDeviceInfoList(deviceInfo); - - *DevicesConnected = TotalDevicesConnected; - - return; -} - -//***************************************************************************** -// -// EnumerateHostController() -// -// hTreeParent - Handle of the TreeView item under which host controllers -// should be added. -// -//***************************************************************************** - -VOID -EnumerateHostController ( - HTREEITEM hTreeParent, - HANDLE hHCDev, _Inout_ PCHAR leafName, - _In_ HANDLE deviceInfo, - _In_ PSP_DEVINFO_DATA deviceInfoData -) -{ - PCHAR driverKeyName = NULL; - HTREEITEM hHCItem = NULL; - PCHAR rootHubName = NULL; - PLIST_ENTRY listEntry = NULL; - PUSBHOSTCONTROLLERINFO hcInfo = NULL; - PUSBHOSTCONTROLLERINFO hcInfoInList = NULL; - DWORD dwSuccess; - BOOL success = FALSE; - ULONG deviceAndFunction = 0; - PUSB_DEVICE_PNP_STRINGS DevProps = NULL; - - - // Allocate a structure to hold information about this host controller. - // - hcInfo = (PUSBHOSTCONTROLLERINFO)ALLOC(sizeof(USBHOSTCONTROLLERINFO)); - - // just return if could not alloc memory - if (NULL == hcInfo) - return; - - hcInfo->DeviceInfoType = HostControllerInfo; - - // Obtain the driver key name for this host controller. - // - driverKeyName = GetHCDDriverKeyName(hHCDev); - - if (NULL == driverKeyName) - { - // Failure obtaining driver key name. - OOPS(); - FREE(hcInfo); - return; - } - - // Don't enumerate this host controller again if it already - // on the list of enumerated host controllers. - // - listEntry = EnumeratedHCListHead.Flink; - - while (listEntry != &EnumeratedHCListHead) - { - hcInfoInList = CONTAINING_RECORD(listEntry, - USBHOSTCONTROLLERINFO, - ListEntry); - - if (strcmp(driverKeyName, hcInfoInList->DriverKey) == 0) - { - // Already on the list, exit - // - FREE(driverKeyName); - FREE(hcInfo); - return; - } - - listEntry = listEntry->Flink; - } - - // Obtain host controller device properties - { - size_t cbDriverName = 0; - HRESULT hr = S_OK; - - hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName); - if (SUCCEEDED(hr)) - { - DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName); - } - } - - hcInfo->DriverKey = driverKeyName; - - if (DevProps) - { - ULONG ven, dev, subsys, rev; - ven = dev = subsys = rev = 0; - - if (sscanf_s(DevProps->DeviceId, - "PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", - &ven, &dev, &subsys, &rev) != 4) - { - OOPS(); - } - - hcInfo->VendorID = ven; - hcInfo->DeviceID = dev; - hcInfo->SubSysID = subsys; - hcInfo->Revision = rev; - hcInfo->UsbDeviceProperties = DevProps; - } - else - { - OOPS(); - } - - if (DevProps != NULL && DevProps->DeviceDesc != NULL) - { - leafName = DevProps->DeviceDesc; - } - else - { - OOPS(); - } - - // Get the USB Host Controller power map - dwSuccess = GetHostControllerPowerMap(hHCDev, hcInfo); - - if (ERROR_SUCCESS != dwSuccess) - { - OOPS(); - } - - - // Get bus, device, and function - // - hcInfo->BusDeviceFunctionValid = FALSE; - - success = SetupDiGetDeviceRegistryProperty(deviceInfo, - deviceInfoData, - SPDRP_BUSNUMBER, - NULL, - (PBYTE)&hcInfo->BusNumber, - sizeof(hcInfo->BusNumber), - NULL); - - if (success) - { - success = SetupDiGetDeviceRegistryProperty(deviceInfo, - deviceInfoData, - SPDRP_ADDRESS, - NULL, - (PBYTE)&deviceAndFunction, - sizeof(deviceAndFunction), - NULL); - } - - if (success) - { - hcInfo->BusDevice = deviceAndFunction >> 16; - hcInfo->BusFunction = deviceAndFunction & 0xffff; - hcInfo->BusDeviceFunctionValid = TRUE; - } - - // Get the USB Host Controller info - dwSuccess = GetHostControllerInfo(hHCDev, hcInfo); - - if (ERROR_SUCCESS != dwSuccess) - { - OOPS(); - } - - // Add this host controller to the USB device tree view. - // - hHCItem = AddLeaf(hTreeParent, - (LPARAM)hcInfo, - leafName, - hcInfo->Revision == UsbSuperSpeed ? GoodSsDeviceIcon : GoodDeviceIcon); - - if (NULL == hHCItem) - { - // Failure adding host controller to USB device tree - // view. - - OOPS(); - FREE(driverKeyName); - FREE(hcInfo); - return; - } - - // Add this host controller to the list of enumerated - // host controllers. - // - InsertTailList(&EnumeratedHCListHead, - &hcInfo->ListEntry); - - // Get the name of the root hub for this host - // controller and then enumerate the root hub. - // - rootHubName = GetRootHubName(hHCDev); - - if (rootHubName != NULL) - { - size_t cbHubName = 0; - HRESULT hr = S_OK; - - hr = StringCbLength(rootHubName, MAX_DRIVER_KEY_NAME, &cbHubName); - if (SUCCEEDED(hr)) - { - EnumerateHub(hHCItem, - rootHubName, - cbHubName, - NULL, // ConnectionInfo - NULL, // ConnectionInfoV2 - NULL, // PortConnectorProps - NULL, // ConfigDesc - NULL, // BosDesc - NULL, // StringDescs - NULL); // We do not pass DevProps for RootHub - } - } - else - { - // Failure obtaining root hub name. - - OOPS(); - } - - return; -} - - -//***************************************************************************** -// -// EnumerateHub() -// -// hTreeParent - Handle of the TreeView item under which this hub should be -// added. -// -// HubName - Name of this hub. This pointer is kept so the caller can neither -// free nor reuse this memory. -// -// ConnectionInfo - NULL if this is a root hub, else this is the connection -// info for an external hub. This pointer is kept so the caller can neither -// free nor reuse this memory. -// -// ConfigDesc - NULL if this is a root hub, else this is the Configuration -// Descriptor for an external hub. This pointer is kept so the caller can -// neither free nor reuse this memory. -// -// StringDescs - NULL if this is a root hub. -// -// DevProps - Device properties of the hub -// -//***************************************************************************** - -VOID -EnumerateHub ( - HTREEITEM hTreeParent, - _In_reads_(cbHubName) PCHAR HubName, - _In_ size_t cbHubName, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo, - _In_opt_ PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2, - _In_opt_ PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps, - _In_opt_ PUSB_DESCRIPTOR_REQUEST ConfigDesc, - _In_opt_ PUSB_DESCRIPTOR_REQUEST BosDesc, - _In_opt_ PSTRING_DESCRIPTOR_NODE StringDescs, - _In_opt_ PUSB_DEVICE_PNP_STRINGS DevProps - ) -{ - // Initialize locals to not allocated state so the error cleanup routine - // only tries to cleanup things that were successfully allocated. - // - PUSB_NODE_INFORMATION hubInfo = NULL; - PUSB_HUB_INFORMATION_EX hubInfoEx = NULL; - PUSB_HUB_CAPABILITIES_EX hubCapabilityEx = NULL; - HANDLE hHubDevice = INVALID_HANDLE_VALUE; - HTREEITEM hItem = NULL; - PVOID info = NULL; - PCHAR deviceName = NULL; - ULONG nBytes = 0; - BOOL success = 0; - DWORD dwSizeOfLeafName = 0; - CHAR leafName[512] = {0}; - HRESULT hr = S_OK; - size_t cchHeader = 0; - size_t cchFullHubName = 0; - - // Allocate some space for a USBDEVICEINFO structure to hold the - // hub info, hub name, and connection info pointers. GPTR zero - // initializes the structure for us. - // - info = ALLOC(sizeof(USBEXTERNALHUBINFO)); - if (info == NULL) - { - OOPS(); - goto EnumerateHubError; - } - - // Allocate some space for a USB_NODE_INFORMATION structure for this Hub - // - hubInfo = (PUSB_NODE_INFORMATION)ALLOC(sizeof(USB_NODE_INFORMATION)); - if (hubInfo == NULL) - { - OOPS(); - goto EnumerateHubError; - } - - hubInfoEx = (PUSB_HUB_INFORMATION_EX)ALLOC(sizeof(USB_HUB_INFORMATION_EX)); - if (hubInfoEx == NULL) - { - OOPS(); - goto EnumerateHubError; - } - - hubCapabilityEx = (PUSB_HUB_CAPABILITIES_EX)ALLOC(sizeof(USB_HUB_CAPABILITIES_EX)); - if(hubCapabilityEx == NULL) - { - OOPS(); - goto EnumerateHubError; - } - - // Keep copies of the Hub Name, Connection Info, and Configuration - // Descriptor pointers - // - ((PUSBROOTHUBINFO)info)->HubInfo = hubInfo; - ((PUSBROOTHUBINFO)info)->HubName = HubName; - - if (ConnectionInfo != NULL) - { - ((PUSBEXTERNALHUBINFO)info)->DeviceInfoType = ExternalHubInfo; - ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo = ConnectionInfo; - ((PUSBEXTERNALHUBINFO)info)->ConfigDesc = ConfigDesc; - ((PUSBEXTERNALHUBINFO)info)->StringDescs = StringDescs; - ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps = PortConnectorProps; - ((PUSBEXTERNALHUBINFO)info)->HubInfoEx = hubInfoEx; - ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx = hubCapabilityEx; - ((PUSBEXTERNALHUBINFO)info)->BosDesc = BosDesc; - ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2 = ConnectionInfoV2; - ((PUSBEXTERNALHUBINFO)info)->UsbDeviceProperties = DevProps; - } - else - { - ((PUSBROOTHUBINFO)info)->DeviceInfoType = RootHubInfo; - ((PUSBROOTHUBINFO)info)->HubInfoEx = hubInfoEx; - ((PUSBROOTHUBINFO)info)->HubCapabilityEx = hubCapabilityEx; - ((PUSBROOTHUBINFO)info)->PortConnectorProps = PortConnectorProps; - ((PUSBROOTHUBINFO)info)->UsbDeviceProperties = DevProps; - } - - // Allocate a temp buffer for the full hub device name. - // - hr = StringCbLength("\\\\.\\", MAX_DEVICE_PROP, &cchHeader); - if (FAILED(hr)) - { - goto EnumerateHubError; - } - cchFullHubName = cchHeader + cbHubName + 1; - deviceName = (PCHAR)ALLOC((DWORD) cchFullHubName); - if (deviceName == NULL) - { - OOPS(); - goto EnumerateHubError; - } - - // Create the full hub device name - // - hr = StringCchCopyN(deviceName, cchFullHubName, "\\\\.\\", cchHeader); - if (FAILED(hr)) - { - goto EnumerateHubError; - } - hr = StringCchCatN(deviceName, cchFullHubName, HubName, cbHubName); - if (FAILED(hr)) - { - goto EnumerateHubError; - } - - // Try to hub the open device - // - hHubDevice = CreateFile(deviceName, - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL); - - // Done with temp buffer for full hub device name - // - FREE(deviceName); - - if (hHubDevice == INVALID_HANDLE_VALUE) - { - OOPS(); - goto EnumerateHubError; - } - - // - // Now query USBHUB for the USB_NODE_INFORMATION structure for this hub. - // This will tell us the number of downstream ports to enumerate, among - // other things. - // - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_NODE_INFORMATION, - hubInfo, - sizeof(USB_NODE_INFORMATION), - hubInfo, - sizeof(USB_NODE_INFORMATION), - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto EnumerateHubError; - } - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_HUB_INFORMATION_EX, - hubInfoEx, - sizeof(USB_HUB_INFORMATION_EX), - hubInfoEx, - sizeof(USB_HUB_INFORMATION_EX), - &nBytes, - NULL); - - // - // Fail gracefully for downlevel OS's from Win8 - // - if (!success || nBytes < sizeof(USB_HUB_INFORMATION_EX)) - { - FREE(hubInfoEx); - hubInfoEx = NULL; - if (ConnectionInfo != NULL) - { - ((PUSBEXTERNALHUBINFO)info)->HubInfoEx = NULL; - } - else - { - ((PUSBROOTHUBINFO)info)->HubInfoEx = NULL; - } - } - - // - // Obtain Hub Capabilities - // - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_HUB_CAPABILITIES_EX, - hubCapabilityEx, - sizeof(USB_HUB_CAPABILITIES_EX), - hubCapabilityEx, - sizeof(USB_HUB_CAPABILITIES_EX), - &nBytes, - NULL); - - // - // Fail gracefully - // - if (!success || nBytes < sizeof(USB_HUB_CAPABILITIES_EX)) - { - FREE(hubCapabilityEx); - hubCapabilityEx = NULL; - if (ConnectionInfo != NULL) - { - ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx = NULL; - } - else - { - ((PUSBROOTHUBINFO)info)->HubCapabilityEx = NULL; - } - } - - // Build the leaf name from the port number and the device description - // - dwSizeOfLeafName = sizeof(leafName); - if (ConnectionInfo) - { - StringCchPrintf(leafName, dwSizeOfLeafName, "[Port%d] ", ConnectionInfo->ConnectionIndex); - StringCchCat(leafName, - dwSizeOfLeafName, - ConnectionStatuses[ConnectionInfo->ConnectionStatus]); - StringCchCatN(leafName, - dwSizeOfLeafName, - " : ", - sizeof(" : ")); - } - - if (DevProps) - { - size_t cbDeviceDesc = 0; - hr = StringCbLength(DevProps->DeviceDesc, MAX_DRIVER_KEY_NAME, &cbDeviceDesc); - if(SUCCEEDED(hr)) - { - StringCchCatN(leafName, - dwSizeOfLeafName, - DevProps->DeviceDesc, - cbDeviceDesc); - } - } - else - { - if(ConnectionInfo != NULL) - { - // External hub - StringCchCatN(leafName, - dwSizeOfLeafName, - HubName, - cbHubName); - } - else - { - // Root hub - StringCchCatN(leafName, - dwSizeOfLeafName, - "RootHub", - sizeof("RootHub")); - } - } - - // Now add an item to the TreeView with the PUSBDEVICEINFO pointer info - // as the LPARAM reference value containing everything we know about the - // hub. - // - hItem = AddLeaf(hTreeParent, - (LPARAM)info, - leafName, - HubIcon); - - if (hItem == NULL) - { - OOPS(); - goto EnumerateHubError; - } - - // Now recursively enumerate the ports of this hub. - // - EnumerateHubPorts( - hItem, - hHubDevice, - hubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts - ); - - - CloseHandle(hHubDevice); - return; - -EnumerateHubError: - // - // Clean up any stuff that got allocated - // - - if (hHubDevice != INVALID_HANDLE_VALUE) - { - CloseHandle(hHubDevice); - hHubDevice = INVALID_HANDLE_VALUE; - } - - if (hubInfo) - { - FREE(hubInfo); - } - - if (hubInfoEx) - { - FREE(hubInfoEx); - } - - if (info) - { - FREE(info); - } - - if (HubName) - { - FREE(HubName); - } - - if (ConnectionInfo) - { - FREE(ConnectionInfo); - } - - if (ConfigDesc) - { - FREE(ConfigDesc); - } - - if (BosDesc) - { - FREE(BosDesc); - } - - if (StringDescs != NULL) - { - PSTRING_DESCRIPTOR_NODE Next; - - do { - - Next = StringDescs->Next; - FREE(StringDescs); - StringDescs = Next; - - } while (StringDescs != NULL); - } -} - -//***************************************************************************** -// -// EnumerateHubPorts() -// -// hTreeParent - Handle of the TreeView item under which the hub port should -// be added. -// -// hHubDevice - Handle of the hub device to enumerate. -// -// NumPorts - Number of ports on the hub. -// -//***************************************************************************** - -VOID -EnumerateHubPorts ( - HTREEITEM hTreeParent, - HANDLE hHubDevice, - ULONG NumPorts -) -{ - ULONG index = 0; - BOOL success = 0; - HRESULT hr = S_OK; - PCHAR driverKeyName = NULL; - PUSB_DEVICE_PNP_STRINGS DevProps; - DWORD dwSizeOfLeafName = 0; - CHAR leafName[512]; - int icon = 0; - - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfoEx; - PUSB_PORT_CONNECTOR_PROPERTIES pPortConnectorProps; - USB_PORT_CONNECTOR_PROPERTIES portConnectorProps; - PUSB_DESCRIPTOR_REQUEST configDesc; - PUSB_DESCRIPTOR_REQUEST bosDesc; - PSTRING_DESCRIPTOR_NODE stringDescs; - PUSBDEVICEINFO info; - PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfoExV2; - PDEVICE_INFO_NODE pNode; - - // Loop over all ports of the hub. - // - // Port indices are 1 based, not 0 based. - // - for (index = 1; index <= NumPorts; index++) - { - ULONG nBytesEx; - ULONG nBytes = 0; - - connectionInfoEx = NULL; - pPortConnectorProps = NULL; - ZeroMemory(&portConnectorProps, sizeof(portConnectorProps)); - configDesc = NULL; - bosDesc = NULL; - stringDescs = NULL; - info = NULL; - connectionInfoExV2 = NULL; - pNode = NULL; - DevProps = NULL; - ZeroMemory(leafName, sizeof(leafName)); - - // - // Allocate space to hold the connection info for this port. - // For now, allocate it big enough to hold info for 30 pipes. - // - // Endpoint numbers are 0-15. Endpoint number 0 is the standard - // control endpoint which is not explicitly listed in the Configuration - // Descriptor. There can be an IN endpoint and an OUT endpoint at - // endpoint numbers 1-15 so there can be a maximum of 30 endpoints - // per device configuration. - // - // Should probably size this dynamically at some point. - // - - nBytesEx = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) + - (sizeof(USB_PIPE_INFO) * 30); - - connectionInfoEx = (PUSB_NODE_CONNECTION_INFORMATION_EX)ALLOC(nBytesEx); - - if (connectionInfoEx == NULL) - { - OOPS(); - break; - } - - connectionInfoExV2 = (PUSB_NODE_CONNECTION_INFORMATION_EX_V2) - ALLOC(sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2)); - - if (connectionInfoExV2 == NULL) - { - OOPS(); - FREE(connectionInfoEx); - break; - } - - // - // Now query USBHUB for the structures - // for this port. This will tell us if a device is attached to this - // port, among other things. - // The fault tolerate code is executed first. - // - - portConnectorProps.ConnectionIndex = index; - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES, - &portConnectorProps, - sizeof(USB_PORT_CONNECTOR_PROPERTIES), - &portConnectorProps, - sizeof(USB_PORT_CONNECTOR_PROPERTIES), - &nBytes, - NULL); - - if (success && nBytes == sizeof(USB_PORT_CONNECTOR_PROPERTIES)) - { - pPortConnectorProps = (PUSB_PORT_CONNECTOR_PROPERTIES) - ALLOC(portConnectorProps.ActualLength); - - if (pPortConnectorProps != NULL) - { - pPortConnectorProps->ConnectionIndex = index; - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_PORT_CONNECTOR_PROPERTIES, - pPortConnectorProps, - portConnectorProps.ActualLength, - pPortConnectorProps, - portConnectorProps.ActualLength, - &nBytes, - NULL); - - if (!success || nBytes < portConnectorProps.ActualLength) - { - FREE(pPortConnectorProps); - pPortConnectorProps = NULL; - } - } - } - - connectionInfoExV2->ConnectionIndex = index; - connectionInfoExV2->Length = sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2); - connectionInfoExV2->SupportedUsbProtocols.Usb300 = 1; - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, - connectionInfoExV2, - sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2), - connectionInfoExV2, - sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2), - &nBytes, - NULL); - - if (!success || nBytes < sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2)) - { - FREE(connectionInfoExV2); - connectionInfoExV2 = NULL; - } - - connectionInfoEx->ConnectionIndex = index; - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, - connectionInfoEx, - nBytesEx, - connectionInfoEx, - nBytesEx, - &nBytesEx, - NULL); - - if (success) - { - // - // Since the USB_NODE_CONNECTION_INFORMATION_EX is used to display - // the device speed, but the hub driver doesn't support indication - // of superspeed, we overwrite the value if the super speed - // data structures are available and indicate the device is operating - // at SuperSpeed. - // - - if (connectionInfoEx->Speed == UsbHighSpeed - && connectionInfoExV2 != NULL - && (connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher || - connectionInfoExV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher)) - { - connectionInfoEx->Speed = UsbSuperSpeed; - } - } - else - { - PUSB_NODE_CONNECTION_INFORMATION connectionInfo = NULL; - - // Try using IOCTL_USB_GET_NODE_CONNECTION_INFORMATION - // instead of IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX - // - - nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) + - sizeof(USB_PIPE_INFO) * 30; - - connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)ALLOC(nBytes); - - if (connectionInfo == NULL) - { - OOPS(); - - FREE(connectionInfoEx); - if (pPortConnectorProps != NULL) - { - FREE(pPortConnectorProps); - } - if (connectionInfoExV2 != NULL) - { - FREE(connectionInfoExV2); - } - continue; - } - - connectionInfo->ConnectionIndex = index; - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, - connectionInfo, - nBytes, - connectionInfo, - nBytes, - &nBytes, - NULL); - - if (!success) - { - OOPS(); - - FREE(connectionInfo); - FREE(connectionInfoEx); - if (pPortConnectorProps != NULL) - { - FREE(pPortConnectorProps); - } - if (connectionInfoExV2 != NULL) - { - FREE(connectionInfoExV2); - } - continue; - } - - // Copy IOCTL_USB_GET_NODE_CONNECTION_INFORMATION into - // IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX structure. - // - connectionInfoEx->ConnectionIndex = connectionInfo->ConnectionIndex; - connectionInfoEx->DeviceDescriptor = connectionInfo->DeviceDescriptor; - connectionInfoEx->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue; - connectionInfoEx->Speed = connectionInfo->LowSpeed ? UsbLowSpeed : UsbFullSpeed; - connectionInfoEx->DeviceIsHub = connectionInfo->DeviceIsHub; - connectionInfoEx->DeviceAddress = connectionInfo->DeviceAddress; - connectionInfoEx->NumberOfOpenPipes = connectionInfo->NumberOfOpenPipes; - connectionInfoEx->ConnectionStatus = connectionInfo->ConnectionStatus; - - memcpy(&connectionInfoEx->PipeList[0], - &connectionInfo->PipeList[0], - sizeof(USB_PIPE_INFO) * 30); - - FREE(connectionInfo); - } - - // Update the count of connected devices - // - if (connectionInfoEx->ConnectionStatus == DeviceConnected) - { - TotalDevicesConnected++; - } - - if (connectionInfoEx->DeviceIsHub) - { - TotalHubs++; - } - - // If there is a device connected, get the Device Description - // - if (connectionInfoEx->ConnectionStatus != NoDeviceConnected) - { - driverKeyName = GetDriverKeyName(hHubDevice, index); - - if (driverKeyName) - { - size_t cbDriverName = 0; - - hr = StringCbLength(driverKeyName, MAX_DRIVER_KEY_NAME, &cbDriverName); - if (SUCCEEDED(hr)) - { - DevProps = DriverNameToDeviceProperties(driverKeyName, cbDriverName); - pNode = FindMatchingDeviceNodeForDriverName(driverKeyName, connectionInfoEx->DeviceIsHub); - } - FREE(driverKeyName); - } - - } - - // If there is a device connected to the port, try to retrieve the - // Configuration Descriptor from the device. - // - if (gDoConfigDesc && - connectionInfoEx->ConnectionStatus == DeviceConnected) - { - configDesc = GetConfigDescriptor(hHubDevice, - index, - 0); - } - else - { - configDesc = NULL; - } - - if (configDesc != NULL && - connectionInfoEx->DeviceDescriptor.bcdUSB > 0x0200) - { - bosDesc = GetBOSDescriptor(hHubDevice, - index); - } - else - { - bosDesc = NULL; - } - - if (configDesc != NULL && - AreThereStringDescriptors(&connectionInfoEx->DeviceDescriptor, - (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1))) - { - stringDescs = GetAllStringDescriptors ( - hHubDevice, - index, - &connectionInfoEx->DeviceDescriptor, - (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1)); - } - else - { - stringDescs = NULL; - } - - // If the device connected to the port is an external hub, get the - // name of the external hub and recursively enumerate it. - // - if (connectionInfoEx->DeviceIsHub) - { - PCHAR extHubName; - size_t cbHubName = 0; - - extHubName = GetExternalHubName(hHubDevice, index); - if (extHubName != NULL) - { - hr = StringCbLength(extHubName, MAX_DRIVER_KEY_NAME, &cbHubName); - if (SUCCEEDED(hr)) - { - EnumerateHub(hTreeParent, //hPortItem, - extHubName, - cbHubName, - connectionInfoEx, - connectionInfoExV2, - pPortConnectorProps, - configDesc, - bosDesc, - stringDescs, - DevProps); - } - } - } - else - { - // Allocate some space for a USBDEVICEINFO structure to hold the - // hub info, hub name, and connection info pointers. GPTR zero - // initializes the structure for us. - // - info = (PUSBDEVICEINFO) ALLOC(sizeof(USBDEVICEINFO)); - - if (info == NULL) - { - OOPS(); - if (configDesc != NULL) - { - FREE(configDesc); - } - if (bosDesc != NULL) - { - FREE(bosDesc); - } - FREE(connectionInfoEx); - - if (pPortConnectorProps != NULL) - { - FREE(pPortConnectorProps); - } - if (connectionInfoExV2 != NULL) - { - FREE(connectionInfoExV2); - } - break; - } - - info->DeviceInfoType = DeviceInfo; - info->ConnectionInfo = connectionInfoEx; - info->PortConnectorProps = pPortConnectorProps; - info->ConfigDesc = configDesc; - info->StringDescs = stringDescs; - info->BosDesc = bosDesc; - info->ConnectionInfoV2 = connectionInfoExV2; - info->UsbDeviceProperties = DevProps; - info->DeviceInfoNode = pNode; - - StringCchPrintf(leafName, sizeof(leafName), "[Port%d] ", index); - - // Add error description if ConnectionStatus is other than NoDeviceConnected / DeviceConnected - StringCchCat(leafName, - sizeof(leafName), - ConnectionStatuses[connectionInfoEx->ConnectionStatus]); - - if (DevProps) - { - size_t cchDeviceDesc = 0; - - hr = StringCbLength(DevProps->DeviceDesc, MAX_DEVICE_PROP, &cchDeviceDesc); - if (FAILED(hr)) - { - OOPS(); - } - dwSizeOfLeafName = sizeof(leafName); - StringCchCatN(leafName, - dwSizeOfLeafName - 1, - " : ", - sizeof(" : ")); - StringCchCatN(leafName, - dwSizeOfLeafName - 1, - DevProps->DeviceDesc, - cchDeviceDesc ); - } - - if (connectionInfoEx->ConnectionStatus == NoDeviceConnected) - { - if (connectionInfoExV2 != NULL && - connectionInfoExV2->SupportedUsbProtocols.Usb300 == 1) - { - icon = NoSsDeviceIcon; - } - else - { - icon = NoDeviceIcon; - } - } - else if (connectionInfoEx->CurrentConfigurationValue) - { - if (connectionInfoEx->Speed == UsbSuperSpeed) - { - icon = GoodSsDeviceIcon; - } - else - { - icon = GoodDeviceIcon; - } - } - else - { - icon = BadDeviceIcon; - } - - AddLeaf(hTreeParent, //hPortItem, - (LPARAM)info, - leafName, - icon); - } - } // for -} - - -//***************************************************************************** -// -// WideStrToMultiStr() -// -//***************************************************************************** - -PCHAR WideStrToMultiStr ( - _In_reads_bytes_(cbWideStr) PWCHAR WideStr, - _In_ size_t cbWideStr - ) -{ - ULONG nBytes = 0; - PCHAR MultiStr = NULL; - PWCHAR pWideStr = NULL; - - // Use local string to guarantee zero termination - pWideStr = (PWCHAR) ALLOC((DWORD) cbWideStr + sizeof(WCHAR)); - if (NULL == pWideStr) - { - return NULL; - } - memset(pWideStr, 0, cbWideStr + sizeof(WCHAR)); - memcpy(pWideStr, WideStr, cbWideStr); - - // Get the length of the converted string - // - nBytes = WideCharToMultiByte( - CP_ACP, - WC_NO_BEST_FIT_CHARS, - pWideStr, - -1, - NULL, - 0, - NULL, - NULL); - - if (nBytes == 0) - { - FREE(pWideStr); - return NULL; - } - - // Allocate space to hold the converted string - // - MultiStr = ALLOC(nBytes); - if (MultiStr == NULL) - { - FREE(pWideStr); - return NULL; - } - - // Convert the string - // - nBytes = WideCharToMultiByte( - CP_ACP, - WC_NO_BEST_FIT_CHARS, - pWideStr, - -1, - MultiStr, - nBytes, - NULL, - NULL); - - if (nBytes == 0) - { - FREE(MultiStr); - FREE(pWideStr); - return NULL; - } - - FREE(pWideStr); - return MultiStr; -} - -//***************************************************************************** -// -// GetRootHubName() -// -//***************************************************************************** - -PCHAR GetRootHubName ( - HANDLE HostController -) -{ - BOOL success = 0; - ULONG nBytes = 0; - USB_ROOT_HUB_NAME rootHubName; - PUSB_ROOT_HUB_NAME rootHubNameW = NULL; - PCHAR rootHubNameA = NULL; - - // Get the length of the name of the Root Hub attached to the - // Host Controller - // - success = DeviceIoControl(HostController, - IOCTL_USB_GET_ROOT_HUB_NAME, - 0, - 0, - &rootHubName, - sizeof(rootHubName), - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto GetRootHubNameError; - } - - // Allocate space to hold the Root Hub name - // - nBytes = rootHubName.ActualLength; - - rootHubNameW = ALLOC(nBytes); - if (rootHubNameW == NULL) - { - OOPS(); - goto GetRootHubNameError; - } - - // Get the name of the Root Hub attached to the Host Controller - // - success = DeviceIoControl(HostController, - IOCTL_USB_GET_ROOT_HUB_NAME, - NULL, - 0, - rootHubNameW, - nBytes, - &nBytes, - NULL); - if (!success) - { - OOPS(); - goto GetRootHubNameError; - } - - // Convert the Root Hub name - // - rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName, nBytes - sizeof(USB_ROOT_HUB_NAME) + sizeof(WCHAR)); - - // All done, free the uncoverted Root Hub name and return the - // converted Root Hub name - // - FREE(rootHubNameW); - - return rootHubNameA; - -GetRootHubNameError: - // There was an error, free anything that was allocated - // - if (rootHubNameW != NULL) - { - FREE(rootHubNameW); - rootHubNameW = NULL; - } - return NULL; -} - - -//***************************************************************************** -// -// GetExternalHubName() -// -//***************************************************************************** - -PCHAR GetExternalHubName ( - HANDLE Hub, - ULONG ConnectionIndex -) -{ - BOOL success = 0; - ULONG nBytes = 0; - USB_NODE_CONNECTION_NAME extHubName; - PUSB_NODE_CONNECTION_NAME extHubNameW = NULL; - PCHAR extHubNameA = NULL; - - // Get the length of the name of the external hub attached to the - // specified port. - // - extHubName.ConnectionIndex = ConnectionIndex; - - success = DeviceIoControl(Hub, - IOCTL_USB_GET_NODE_CONNECTION_NAME, - &extHubName, - sizeof(extHubName), - &extHubName, - sizeof(extHubName), - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto GetExternalHubNameError; - } - - // Allocate space to hold the external hub name - // - nBytes = extHubName.ActualLength; - - if (nBytes <= sizeof(extHubName)) - { - OOPS(); - goto GetExternalHubNameError; - } - - extHubNameW = ALLOC(nBytes); - - if (extHubNameW == NULL) - { - OOPS(); - goto GetExternalHubNameError; - } - - // Get the name of the external hub attached to the specified port - // - extHubNameW->ConnectionIndex = ConnectionIndex; - - success = DeviceIoControl(Hub, - IOCTL_USB_GET_NODE_CONNECTION_NAME, - extHubNameW, - nBytes, - extHubNameW, - nBytes, - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto GetExternalHubNameError; - } - - // Convert the External Hub name - // - extHubNameA = WideStrToMultiStr(extHubNameW->NodeName, nBytes - sizeof(USB_NODE_CONNECTION_NAME) + sizeof(WCHAR)); - - // All done, free the uncoverted external hub name and return the - // converted external hub name - // - FREE(extHubNameW); - - return extHubNameA; - - -GetExternalHubNameError: - // There was an error, free anything that was allocated - // - if (extHubNameW != NULL) - { - FREE(extHubNameW); - extHubNameW = NULL; - } - - return NULL; -} - - -//***************************************************************************** -// -// GetDriverKeyName() -// -//***************************************************************************** - -PCHAR GetDriverKeyName ( - HANDLE Hub, - ULONG ConnectionIndex -) -{ - BOOL success = 0; - ULONG nBytes = 0; - USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName; - PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW = NULL; - PCHAR driverKeyNameA = NULL; - - // Get the length of the name of the driver key of the device attached to - // the specified port. - // - driverKeyName.ConnectionIndex = ConnectionIndex; - - success = DeviceIoControl(Hub, - IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, - &driverKeyName, - sizeof(driverKeyName), - &driverKeyName, - sizeof(driverKeyName), - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto GetDriverKeyNameError; - } - - // Allocate space to hold the driver key name - // - nBytes = driverKeyName.ActualLength; - - if (nBytes <= sizeof(driverKeyName)) - { - OOPS(); - goto GetDriverKeyNameError; - } - - driverKeyNameW = ALLOC(nBytes); - if (driverKeyNameW == NULL) - { - OOPS(); - goto GetDriverKeyNameError; - } - - // Get the name of the driver key of the device attached to - // the specified port. - // - driverKeyNameW->ConnectionIndex = ConnectionIndex; - - success = DeviceIoControl(Hub, - IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, - driverKeyNameW, - nBytes, - driverKeyNameW, - nBytes, - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto GetDriverKeyNameError; - } - - // Convert the driver key name - // - driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName, nBytes - sizeof(USB_NODE_CONNECTION_DRIVERKEY_NAME) + sizeof(WCHAR)); - - // All done, free the uncoverted driver key name and return the - // converted driver key name - // - FREE(driverKeyNameW); - - return driverKeyNameA; - - -GetDriverKeyNameError: - // There was an error, free anything that was allocated - // - if (driverKeyNameW != NULL) - { - FREE(driverKeyNameW); - driverKeyNameW = NULL; - } - - return NULL; -} - - -//***************************************************************************** -// -// GetHCDDriverKeyName() -// -//***************************************************************************** - -PCHAR GetHCDDriverKeyName ( - HANDLE HCD -) -{ - BOOL success = 0; - ULONG nBytes = 0; - USB_HCD_DRIVERKEY_NAME driverKeyName = {0}; - PUSB_HCD_DRIVERKEY_NAME driverKeyNameW = NULL; - PCHAR driverKeyNameA = NULL; - - ZeroMemory(&driverKeyName, sizeof(driverKeyName)); - - // Get the length of the name of the driver key of the HCD - // - success = DeviceIoControl(HCD, - IOCTL_GET_HCD_DRIVERKEY_NAME, - &driverKeyName, - sizeof(driverKeyName), - &driverKeyName, - sizeof(driverKeyName), - &nBytes, - NULL); - - if (!success) - { - OOPS(); - goto GetHCDDriverKeyNameError; - } - - // Allocate space to hold the driver key name - // - nBytes = driverKeyName.ActualLength; - if (nBytes <= sizeof(driverKeyName)) - { - OOPS(); - goto GetHCDDriverKeyNameError; - } - - driverKeyNameW = ALLOC(nBytes); - if (driverKeyNameW == NULL) - { - OOPS(); - goto GetHCDDriverKeyNameError; - } - - // Get the name of the driver key of the device attached to - // the specified port. - // - - success = DeviceIoControl(HCD, - IOCTL_GET_HCD_DRIVERKEY_NAME, - driverKeyNameW, - nBytes, - driverKeyNameW, - nBytes, - &nBytes, - NULL); - if (!success) - { - OOPS(); - goto GetHCDDriverKeyNameError; - } - - // - // Convert the driver key name - // Pass the length of the DriverKeyName string - // - - driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName, nBytes - sizeof(USB_HCD_DRIVERKEY_NAME) + sizeof(WCHAR)); - - // All done, free the uncoverted driver key name and return the - // converted driver key name - // - FREE(driverKeyNameW); - - return driverKeyNameA; - -GetHCDDriverKeyNameError: - // There was an error, free anything that was allocated - // - if (driverKeyNameW != NULL) - { - FREE(driverKeyNameW); - driverKeyNameW = NULL; - } - - return NULL; -} - - -//***************************************************************************** -// -// GetConfigDescriptor() -// -// hHubDevice - Handle of the hub device containing the port from which the -// Configuration Descriptor will be requested. -// -// ConnectionIndex - Identifies the port on the hub to which a device is -// attached from which the Configuration Descriptor will be requested. -// -// DescriptorIndex - Configuration Descriptor index, zero based. -// -//***************************************************************************** - -PUSB_DESCRIPTOR_REQUEST -GetConfigDescriptor ( - HANDLE hHubDevice, - ULONG ConnectionIndex, - UCHAR DescriptorIndex -) -{ - BOOL success = 0; - ULONG nBytes = 0; - ULONG nBytesReturned = 0; - - UCHAR configDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + - sizeof(USB_CONFIGURATION_DESCRIPTOR)]; - - PUSB_DESCRIPTOR_REQUEST configDescReq = NULL; - PUSB_CONFIGURATION_DESCRIPTOR configDesc = NULL; - - - // Request the Configuration Descriptor the first time using our - // local buffer, which is just big enough for the Cofiguration - // Descriptor itself. - // - nBytes = sizeof(configDescReqBuf); - - configDescReq = (PUSB_DESCRIPTOR_REQUEST)configDescReqBuf; - configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1); - - // Zero fill the entire request structure - // - memset(configDescReq, 0, nBytes); - - // Indicate the port from which the descriptor will be requested - // - configDescReq->ConnectionIndex = ConnectionIndex; - - // - // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this - // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. - // - // USBD will automatically initialize these fields: - // bmRequest = 0x80 - // bRequest = 0x06 - // - // We must inititialize these fields: - // wValue = Descriptor Type (high) and Descriptor Index (low byte) - // wIndex = Zero (or Language ID for String Descriptors) - // wLength = Length of descriptor buffer - // - configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) - | DescriptorIndex; - - configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Now issue the get descriptor request. - // - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, - configDescReq, - nBytes, - configDescReq, - nBytes, - &nBytesReturned, - NULL); - - if (!success) - { - OOPS(); - return NULL; - } - - if (nBytes != nBytesReturned) - { - OOPS(); - return NULL; - } - - if (configDesc->wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - OOPS(); - return NULL; - } - - // Now request the entire Configuration Descriptor using a dynamically - // allocated buffer which is sized big enough to hold the entire descriptor - // - nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + configDesc->wTotalLength; - - configDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes); - - if (configDescReq == NULL) - { - OOPS(); - return NULL; - } - - configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1); - - // Indicate the port from which the descriptor will be requested - // - configDescReq->ConnectionIndex = ConnectionIndex; - - // - // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this - // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. - // - // USBD will automatically initialize these fields: - // bmRequest = 0x80 - // bRequest = 0x06 - // - // We must inititialize these fields: - // wValue = Descriptor Type (high) and Descriptor Index (low byte) - // wIndex = Zero (or Language ID for String Descriptors) - // wLength = Length of descriptor buffer - // - configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) - | DescriptorIndex; - - configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Now issue the get descriptor request. - // - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, - configDescReq, - nBytes, - configDescReq, - nBytes, - &nBytesReturned, - NULL); - - if (!success) - { - OOPS(); - FREE(configDescReq); - return NULL; - } - - if (nBytes != nBytesReturned) - { - OOPS(); - FREE(configDescReq); - return NULL; - } - - if (configDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST))) - { - OOPS(); - FREE(configDescReq); - return NULL; - } - - return configDescReq; -} - - - -//***************************************************************************** -// -// GetBOSDescriptor() -// -// hHubDevice - Handle of the hub device containing the port from which the -// Configuration Descriptor will be requested. -// -// ConnectionIndex - Identifies the port on the hub to which a device is -// attached from which the BOS Descriptor will be requested. -// -//***************************************************************************** - -PUSB_DESCRIPTOR_REQUEST -GetBOSDescriptor ( - HANDLE hHubDevice, - ULONG ConnectionIndex -) -{ - BOOL success = 0; - ULONG nBytes = 0; - ULONG nBytesReturned = 0; - - UCHAR bosDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + - sizeof(USB_BOS_DESCRIPTOR)]; - - PUSB_DESCRIPTOR_REQUEST bosDescReq = NULL; - PUSB_BOS_DESCRIPTOR bosDesc = NULL; - - - // Request the BOS Descriptor the first time using our - // local buffer, which is just big enough for the BOS - // Descriptor itself. - // - nBytes = sizeof(bosDescReqBuf); - - bosDescReq = (PUSB_DESCRIPTOR_REQUEST)bosDescReqBuf; - bosDesc = (PUSB_BOS_DESCRIPTOR)(bosDescReq+1); - - // Zero fill the entire request structure - // - memset(bosDescReq, 0, nBytes); - - // Indicate the port from which the descriptor will be requested - // - bosDescReq->ConnectionIndex = ConnectionIndex; - - // - // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this - // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. - // - // USBD will automatically initialize these fields: - // bmRequest = 0x80 - // bRequest = 0x06 - // - // We must inititialize these fields: - // wValue = Descriptor Type (high) and Descriptor Index (low byte) - // wIndex = Zero (or Language ID for String Descriptors) - // wLength = Length of descriptor buffer - // - bosDescReq->SetupPacket.wValue = (USB_BOS_DESCRIPTOR_TYPE << 8); - - bosDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Now issue the get descriptor request. - // - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, - bosDescReq, - nBytes, - bosDescReq, - nBytes, - &nBytesReturned, - NULL); - - if (!success) - { - OOPS(); - return NULL; - } - - if (nBytes != nBytesReturned) - { - OOPS(); - return NULL; - } - - if (bosDesc->wTotalLength < sizeof(USB_BOS_DESCRIPTOR)) - { - OOPS(); - return NULL; - } - - // Now request the entire BOS Descriptor using a dynamically - // allocated buffer which is sized big enough to hold the entire descriptor - // - nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + bosDesc->wTotalLength; - - bosDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes); - - if (bosDescReq == NULL) - { - OOPS(); - return NULL; - } - - bosDesc = (PUSB_BOS_DESCRIPTOR)(bosDescReq+1); - - // Indicate the port from which the descriptor will be requested - // - bosDescReq->ConnectionIndex = ConnectionIndex; - - // - // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this - // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. - // - // USBD will automatically initialize these fields: - // bmRequest = 0x80 - // bRequest = 0x06 - // - // We must inititialize these fields: - // wValue = Descriptor Type (high) and Descriptor Index (low byte) - // wIndex = Zero (or Language ID for String Descriptors) - // wLength = Length of descriptor buffer - // - bosDescReq->SetupPacket.wValue = (USB_BOS_DESCRIPTOR_TYPE << 8); - - bosDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Now issue the get descriptor request. - // - - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, - bosDescReq, - nBytes, - bosDescReq, - nBytes, - &nBytesReturned, - NULL); - - if (!success) - { - OOPS(); - FREE(bosDescReq); - return NULL; - } - - if (nBytes != nBytesReturned) - { - OOPS(); - FREE(bosDescReq); - return NULL; - } - - if (bosDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST))) - { - OOPS(); - FREE(bosDescReq); - return NULL; - } - - return bosDescReq; -} - - -//***************************************************************************** -// -// AreThereStringDescriptors() -// -// DeviceDesc - Device Descriptor for which String Descriptors should be -// checked. -// -// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor) -// for which String Descriptors should be checked. -// -//***************************************************************************** - -BOOL -AreThereStringDescriptors ( - PUSB_DEVICE_DESCRIPTOR DeviceDesc, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc -) -{ - PUCHAR descEnd = NULL; - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - - // - // Check Device Descriptor strings - // - - if (DeviceDesc->iManufacturer || - DeviceDesc->iProduct || - DeviceDesc->iSerialNumber - ) - { - return TRUE; - } - - - // - // Check the Configuration and Interface Descriptor strings - // - - descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - switch (commonDesc->bDescriptorType) - { - case USB_CONFIGURATION_DESCRIPTOR_TYPE: - case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - OOPS(); - break; - } - if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration) - { - return TRUE; - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - - case USB_INTERFACE_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) && - commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2)) - { - OOPS(); - break; - } - if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface) - { - return TRUE; - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - - default: - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - } - break; - } - - return FALSE; -} - - -//***************************************************************************** -// -// GetAllStringDescriptors() -// -// hHubDevice - Handle of the hub device containing the port from which the -// String Descriptors will be requested. -// -// ConnectionIndex - Identifies the port on the hub to which a device is -// attached from which the String Descriptors will be requested. -// -// DeviceDesc - Device Descriptor for which String Descriptors should be -// requested. -// -// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor) -// for which String Descriptors should be requested. -// -//***************************************************************************** - -PSTRING_DESCRIPTOR_NODE -GetAllStringDescriptors ( - HANDLE hHubDevice, - ULONG ConnectionIndex, - PUSB_DEVICE_DESCRIPTOR DeviceDesc, - PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc -) -{ - PSTRING_DESCRIPTOR_NODE supportedLanguagesString = NULL; - ULONG numLanguageIDs = 0; - USHORT *languageIDs = NULL; - - PUCHAR descEnd = NULL; - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - UCHAR uIndex = 1; - UCHAR bInterfaceClass = 0; - BOOL getMoreStrings = FALSE; - HRESULT hr = S_OK; - - // - // Get the array of supported Language IDs, which is returned - // in String Descriptor 0 - // - supportedLanguagesString = GetStringDescriptor(hHubDevice, - ConnectionIndex, - 0, - 0); - - if (supportedLanguagesString == NULL) - { - return NULL; - } - - numLanguageIDs = (supportedLanguagesString->StringDescriptor->bLength - 2) / 2; - - languageIDs = &supportedLanguagesString->StringDescriptor->bString[0]; - - // - // Get the Device Descriptor strings - // - - if (DeviceDesc->iManufacturer) - { - GetStringDescriptors(hHubDevice, - ConnectionIndex, - DeviceDesc->iManufacturer, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - - if (DeviceDesc->iProduct) - { - GetStringDescriptors(hHubDevice, - ConnectionIndex, - DeviceDesc->iProduct, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - - if (DeviceDesc->iSerialNumber) - { - GetStringDescriptors(hHubDevice, - ConnectionIndex, - DeviceDesc->iSerialNumber, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - - // - // Get the Configuration and Interface Descriptor strings - // - - descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength; - - commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc; - - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - switch (commonDesc->bDescriptorType) - { - case USB_CONFIGURATION_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - OOPS(); - break; - } - if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration) - { - GetStringDescriptors(hHubDevice, - ConnectionIndex, - ((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - - case USB_IAD_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR)) - { - OOPS(); - break; - } - if (((PUSB_IAD_DESCRIPTOR)commonDesc)->iFunction) - { - GetStringDescriptors(hHubDevice, - ConnectionIndex, - ((PUSB_IAD_DESCRIPTOR)commonDesc)->iFunction, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - - case USB_INTERFACE_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) && - commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2)) - { - OOPS(); - break; - } - if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface) - { - GetStringDescriptors(hHubDevice, - ConnectionIndex, - ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - - // - // We need to display more string descriptors for the following - // interface classes - // - bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass; - if (bInterfaceClass == USB_DEVICE_CLASS_VIDEO) - { - getMoreStrings = TRUE; - } - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - - default: - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - continue; - } - break; - } - - if (getMoreStrings) - { - // - // We might need to display strings later that are referenced only in - // class-specific descriptors. Get String Descriptors 1 through 32 (an - // arbitrary upper limit for Strings needed due to "bad devices" - // returning an infinite repeat of Strings 0 through 4) until one is not - // found. - // - // There are also "bad devices" that have issues even querying 1-32, but - // historically USBView made this query, so the query should be safe for - // video devices. - // - for (uIndex = 1; SUCCEEDED(hr) && (uIndex < NUM_STRING_DESC_TO_GET); uIndex++) - { - hr = GetStringDescriptors(hHubDevice, - ConnectionIndex, - uIndex, - numLanguageIDs, - languageIDs, - supportedLanguagesString); - } - } - - return supportedLanguagesString; -} - - - -//***************************************************************************** -// -// GetStringDescriptor() -// -// hHubDevice - Handle of the hub device containing the port from which the -// String Descriptor will be requested. -// -// ConnectionIndex - Identifies the port on the hub to which a device is -// attached from which the String Descriptor will be requested. -// -// DescriptorIndex - String Descriptor index. -// -// LanguageID - Language in which the string should be requested. -// -//***************************************************************************** - -PSTRING_DESCRIPTOR_NODE -GetStringDescriptor ( - HANDLE hHubDevice, - ULONG ConnectionIndex, - UCHAR DescriptorIndex, - USHORT LanguageID -) -{ - BOOL success = 0; - ULONG nBytes = 0; - ULONG nBytesReturned = 0; - - UCHAR stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + - MAXIMUM_USB_STRING_LENGTH]; - - PUSB_DESCRIPTOR_REQUEST stringDescReq = NULL; - PUSB_STRING_DESCRIPTOR stringDesc = NULL; - PSTRING_DESCRIPTOR_NODE stringDescNode = NULL; - - nBytes = sizeof(stringDescReqBuf); - - stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf; - stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1); - - // Zero fill the entire request structure - // - memset(stringDescReq, 0, nBytes); - - // Indicate the port from which the descriptor will be requested - // - stringDescReq->ConnectionIndex = ConnectionIndex; - - // - // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this - // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request. - // - // USBD will automatically initialize these fields: - // bmRequest = 0x80 - // bRequest = 0x06 - // - // We must inititialize these fields: - // wValue = Descriptor Type (high) and Descriptor Index (low byte) - // wIndex = Zero (or Language ID for String Descriptors) - // wLength = Length of descriptor buffer - // - stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) - | DescriptorIndex; - - stringDescReq->SetupPacket.wIndex = LanguageID; - - stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST)); - - // Now issue the get descriptor request. - // - success = DeviceIoControl(hHubDevice, - IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, - stringDescReq, - nBytes, - stringDescReq, - nBytes, - &nBytesReturned, - NULL); - - // - // Do some sanity checks on the return from the get descriptor request. - // - - if (!success) - { - OOPS(); - return NULL; - } - - if (nBytesReturned < 2) - { - OOPS(); - return NULL; - } - - if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE) - { - OOPS(); - return NULL; - } - - if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST)) - { - OOPS(); - return NULL; - } - - if (stringDesc->bLength % 2 != 0) - { - OOPS(); - return NULL; - } - - // - // Looks good, allocate some (zero filled) space for the string descriptor - // node and copy the string descriptor to it. - // - - stringDescNode = (PSTRING_DESCRIPTOR_NODE)ALLOC(sizeof(STRING_DESCRIPTOR_NODE) + - stringDesc->bLength); - - if (stringDescNode == NULL) - { - OOPS(); - return NULL; - } - - stringDescNode->DescriptorIndex = DescriptorIndex; - stringDescNode->LanguageID = LanguageID; - - memcpy(stringDescNode->StringDescriptor, - stringDesc, - stringDesc->bLength); - - return stringDescNode; -} - - -//***************************************************************************** -// -// GetStringDescriptors() -// -// hHubDevice - Handle of the hub device containing the port from which the -// String Descriptor will be requested. -// -// ConnectionIndex - Identifies the port on the hub to which a device is -// attached from which the String Descriptor will be requested. -// -// DescriptorIndex - String Descriptor index. -// -// NumLanguageIDs - Number of languages in which the string should be -// requested. -// -// LanguageIDs - Languages in which the string should be requested. -// -// StringDescNodeHead - First node in linked list of device's string descriptors -// -// Return Value: HRESULT indicating whether the string is on the list -// -//***************************************************************************** - -HRESULT -GetStringDescriptors ( - _In_ HANDLE hHubDevice, - _In_ ULONG ConnectionIndex, - _In_ UCHAR DescriptorIndex, - _In_ ULONG NumLanguageIDs, - _In_reads_(NumLanguageIDs) USHORT *LanguageIDs, - _In_ PSTRING_DESCRIPTOR_NODE StringDescNodeHead -) -{ - PSTRING_DESCRIPTOR_NODE tail = NULL; - PSTRING_DESCRIPTOR_NODE trailing = NULL; - ULONG i = 0; - - // - // Go to the end of the linked list, searching for the requested index to - // see if we've already retrieved it - // - for (tail = StringDescNodeHead; tail != NULL; tail = tail->Next) - { - if (tail->DescriptorIndex == DescriptorIndex) - { - return S_OK; - } - - trailing = tail; - } - - tail = trailing; - - // - // Get the next String Descriptor. If this is NULL, then we're done (return) - // Otherwise, loop through all Language IDs - // - for (i = 0; (tail != NULL) && (i < NumLanguageIDs); i++) - { - tail->Next = GetStringDescriptor(hHubDevice, - ConnectionIndex, - DescriptorIndex, - LanguageIDs[i]); - - tail = tail->Next; - } - - if (tail == NULL) - { - return E_FAIL; - } else { - return S_OK; - } -} - - -//***************************************************************************** -// -// CleanupItem() -// -//***************************************************************************** - -VOID -CleanupItem ( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext -) -{ - TV_ITEM tvi; - PVOID info = NULL; - - UNREFERENCED_PARAMETER(pContext); - - tvi.mask = TVIF_HANDLE | TVIF_PARAM; - tvi.hItem = hTreeItem; - - TreeView_GetItem(hTreeWnd, - &tvi); - - info = (PVOID)tvi.lParam; - - if (info) - { - PCHAR DriverKey = NULL; - PUSB_NODE_INFORMATION HubInfo = NULL; - PCHAR HubName = NULL; - PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfoEx = NULL; - PUSB_DESCRIPTOR_REQUEST ConfigDesc = NULL; - PUSB_DESCRIPTOR_REQUEST BosDesc = NULL; - PSTRING_DESCRIPTOR_NODE StringDescs = NULL; - PUSB_HUB_INFORMATION_EX HubInfoEx = NULL; - PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps = NULL; - PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2 = NULL; - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx = NULL; - PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties = NULL; - PUSB_CONTROLLER_INFO_0 ControllerInfo = NULL; - - // - // All structures except DEVICE_INFO_NODE are free'd up here. DEVICE_INFO_NODE structures are free'd while - // destroying device info lists (ClearDeviceList()) - // - switch (*(PUSBDEVICEINFOTYPE)info) - { - case HostControllerInfo: - // - // Remove this host controller from the list of enumerated - // host controllers. - // - RemoveEntryList(&((PUSBHOSTCONTROLLERINFO)info)->ListEntry); - DriverKey = ((PUSBHOSTCONTROLLERINFO)info)->DriverKey; - ControllerInfo = ((PUSBHOSTCONTROLLERINFO)info)->ControllerInfo; - UsbDeviceProperties = ((PUSBHOSTCONTROLLERINFO)info)->UsbDeviceProperties; - break; - - case RootHubInfo: - HubInfo = ((PUSBROOTHUBINFO)info)->HubInfo; - HubInfoEx = ((PUSBROOTHUBINFO)info)->HubInfoEx; - HubName = ((PUSBROOTHUBINFO)info)->HubName; - PortConnectorProps = ((PUSBROOTHUBINFO)info)->PortConnectorProps; - UsbDeviceProperties = ((PUSBROOTHUBINFO)info)->UsbDeviceProperties; - HubCapabilityEx = ((PUSBROOTHUBINFO)info)->HubCapabilityEx; - break; - - case ExternalHubInfo: - HubInfo = ((PUSBEXTERNALHUBINFO)info)->HubInfo; - HubInfoEx = ((PUSBEXTERNALHUBINFO)info)->HubInfoEx; - HubName = ((PUSBEXTERNALHUBINFO)info)->HubName; - ConnectionInfoEx = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfo; - PortConnectorProps = ((PUSBEXTERNALHUBINFO)info)->PortConnectorProps; - ConfigDesc = ((PUSBEXTERNALHUBINFO)info)->ConfigDesc; - BosDesc = ((PUSBEXTERNALHUBINFO)info)->BosDesc; - StringDescs = ((PUSBEXTERNALHUBINFO)info)->StringDescs; - ConnectionInfoV2 = ((PUSBEXTERNALHUBINFO)info)->ConnectionInfoV2; - UsbDeviceProperties = ((PUSBEXTERNALHUBINFO)info)->UsbDeviceProperties; - HubCapabilityEx = ((PUSBEXTERNALHUBINFO)info)->HubCapabilityEx; - break; - - case DeviceInfo: - ConnectionInfoEx = ((PUSBDEVICEINFO)info)->ConnectionInfo; - PortConnectorProps = ((PUSBDEVICEINFO)info)->PortConnectorProps; - ConfigDesc = ((PUSBDEVICEINFO)info)->ConfigDesc; - BosDesc = ((PUSBDEVICEINFO)info)->BosDesc; - StringDescs = ((PUSBDEVICEINFO)info)->StringDescs; - ConnectionInfoV2 = ((PUSBDEVICEINFO)info)->ConnectionInfoV2; - UsbDeviceProperties = ((PUSBDEVICEINFO)info)->UsbDeviceProperties; - break; - } - - if(UsbDeviceProperties) - { - FreeDeviceProperties(&UsbDeviceProperties); - } - - if(ControllerInfo) - { - FREE(ControllerInfo); - } - - if(HubCapabilityEx) - { - FREE(HubCapabilityEx); - } - - if (DriverKey) - { - FREE(DriverKey); - } - - if (HubInfo) - { - FREE(HubInfo); - } - - if (HubName) - { - FREE(HubName); - } - - if (ConfigDesc) - { - FREE(ConfigDesc); - } - - if (BosDesc) - { - FREE(BosDesc); - } - - if (StringDescs) - { - PSTRING_DESCRIPTOR_NODE Next; - - do { - - Next = StringDescs->Next; - FREE(StringDescs); - StringDescs = Next; - - } while (StringDescs); - } - - if (ConnectionInfoEx) - { - FREE(ConnectionInfoEx); - } - - if (HubInfoEx) - { - FREE(HubInfoEx); - } - - if (PortConnectorProps) - { - FREE(PortConnectorProps); - } - - if (ConnectionInfoV2) - { - FREE(ConnectionInfoV2); - } - - FREE(info); - } -} - -//***************************************************************************** -// -// GetHostControllerPowerMap() -// -// HANDLE hHCDev -// - handle to USB Host Controller -// -// PUSBHOSTCONTROLLERINFO hcInfo -// - data structure to receive the Power Map Info -// -// return DWORD dwError -// - return ERROR_SUCCESS or last error -// -//***************************************************************************** - -DWORD -GetHostControllerPowerMap( - HANDLE hHCDev, - PUSBHOSTCONTROLLERINFO hcInfo) -{ - USBUSER_POWER_INFO_REQUEST UsbPowerInfoRequest; - PUSB_POWER_INFO pUPI = &UsbPowerInfoRequest.PowerInformation ; - DWORD dwError = 0; - DWORD dwBytes = 0; - BOOL bSuccess = FALSE; - int nIndex = 0; - int nPowerState = WdmUsbPowerSystemWorking; - - for ( ; nPowerState <= WdmUsbPowerSystemShutdown; nIndex++, nPowerState++) - { - // zero initialize our request - memset(&UsbPowerInfoRequest, 0, sizeof(UsbPowerInfoRequest)); - - // set the header and request sizes - UsbPowerInfoRequest.Header.UsbUserRequest = USBUSER_GET_POWER_STATE_MAP; - UsbPowerInfoRequest.Header.RequestBufferLength = sizeof(UsbPowerInfoRequest); - UsbPowerInfoRequest.PowerInformation.SystemState = nPowerState; - - // - // Now query USBHUB for the USB_POWER_INFO structure for this hub. - // For Selective Suspend support - // - bSuccess = DeviceIoControl(hHCDev, - IOCTL_USB_USER_REQUEST, - &UsbPowerInfoRequest, - sizeof(UsbPowerInfoRequest), - &UsbPowerInfoRequest, - sizeof(UsbPowerInfoRequest), - &dwBytes, - NULL); - - if (!bSuccess) - { - dwError = GetLastError(); - OOPS(); - } - else - { - // copy the data into our USB Host Controller's info structure - memcpy( &(hcInfo->USBPowerInfo[nIndex]), pUPI, sizeof(USB_POWER_INFO)); - } - } - - return dwError; -} - -void -EnumerateAllDevices() -{ - EnumerateAllDevicesWithGuid(&gDeviceList, - (LPGUID)&GUID_DEVINTERFACE_USB_DEVICE); - - EnumerateAllDevicesWithGuid(&gHubList, - (LPGUID)&GUID_DEVINTERFACE_USB_HUB); -} - - -//***************************************************************************** -// -// GetHostControllerInfo() -// -// HANDLE hHCDev -// - handle to USB Host Controller -// -// PUSBHOSTCONTROLLERINFO hcInfo -// - data structure to receive the Power Map Info -// -// return DWORD dwError -// - return ERROR_SUCCESS or last error -// -//***************************************************************************** - -DWORD -GetHostControllerInfo( - HANDLE hHCDev, - PUSBHOSTCONTROLLERINFO hcInfo) -{ - USBUSER_CONTROLLER_INFO_0 UsbControllerInfo; - DWORD dwError = 0; - DWORD dwBytes = 0; - BOOL bSuccess = FALSE; - - memset(&UsbControllerInfo, 0, sizeof(UsbControllerInfo)); - - // set the header and request sizes - UsbControllerInfo.Header.UsbUserRequest = USBUSER_GET_CONTROLLER_INFO_0; - UsbControllerInfo.Header.RequestBufferLength = sizeof(UsbControllerInfo); - - // - // Query for the USB_CONTROLLER_INFO_0 structure - // - bSuccess = DeviceIoControl(hHCDev, - IOCTL_USB_USER_REQUEST, - &UsbControllerInfo, - sizeof(UsbControllerInfo), - &UsbControllerInfo, - sizeof(UsbControllerInfo), - &dwBytes, - NULL); - - if (!bSuccess) - { - dwError = GetLastError(); - OOPS(); - } - else - { - hcInfo->ControllerInfo = (PUSB_CONTROLLER_INFO_0) ALLOC(sizeof(USB_CONTROLLER_INFO_0)); - if(NULL == hcInfo->ControllerInfo) - { - dwError = GetLastError(); - OOPS(); - } - else - { - // copy the data into our USB Host Controller's info structure - memcpy(hcInfo->ControllerInfo, &UsbControllerInfo.Info0, sizeof(USB_CONTROLLER_INFO_0)); - } - } - return dwError; -} - -_Success_(return == TRUE) -BOOL -GetDeviceProperty( - _In_ HDEVINFO DeviceInfoSet, - _In_ PSP_DEVINFO_DATA DeviceInfoData, - _In_ DWORD Property, - _Outptr_ LPTSTR *ppBuffer - ) -{ - BOOL bResult; - DWORD requiredLength = 0; - DWORD lastError; - - if (ppBuffer == NULL) - { - return FALSE; - } - - *ppBuffer = NULL; - - bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet, - DeviceInfoData, - Property , - NULL, - NULL, - 0, - &requiredLength); - lastError = GetLastError(); - - if ((requiredLength == 0) || (bResult != FALSE && lastError != ERROR_INSUFFICIENT_BUFFER)) - { - return FALSE; - } - - *ppBuffer = ALLOC(requiredLength); - - if (*ppBuffer == NULL) - { - return FALSE; - } - - bResult = SetupDiGetDeviceRegistryProperty(DeviceInfoSet, - DeviceInfoData, - Property , - NULL, - (PBYTE) *ppBuffer, - requiredLength, - &requiredLength); - if(bResult == FALSE) - { - FREE(*ppBuffer); - *ppBuffer = NULL; - return FALSE; - } - - return TRUE; -} - - -void -EnumerateAllDevicesWithGuid( - PDEVICE_GUID_LIST DeviceList, - LPGUID Guid - ) -{ - if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE) - { - ClearDeviceList(DeviceList); - } - - DeviceList->DeviceInfo = SetupDiGetClassDevs(Guid, - NULL, - NULL, - (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); - - if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE) - { - ULONG index; - DWORD error; - - error = 0; - index = 0; - - while (error != ERROR_NO_MORE_ITEMS) - { - BOOL success; - PDEVICE_INFO_NODE pNode; - - pNode = ALLOC(sizeof(DEVICE_INFO_NODE)); - if (pNode == NULL) - { - OOPS(); - break; - } - pNode->DeviceInfo = DeviceList->DeviceInfo; - pNode->DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - pNode->DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - success = SetupDiEnumDeviceInfo(DeviceList->DeviceInfo, - index, - &pNode->DeviceInfoData); - - index++; - - if (success == FALSE) - { - error = GetLastError(); - - if (error != ERROR_NO_MORE_ITEMS) - { - OOPS(); - } - - FreeDeviceInfoNode(&pNode); - } - else - { - BOOL bResult; - ULONG requiredLength; - - bResult = GetDeviceProperty(DeviceList->DeviceInfo, - &pNode->DeviceInfoData, - SPDRP_DEVICEDESC, - &pNode->DeviceDescName); - if (bResult == FALSE) - { - FreeDeviceInfoNode(&pNode); - OOPS(); - break; - } - - bResult = GetDeviceProperty(DeviceList->DeviceInfo, - &pNode->DeviceInfoData, - SPDRP_DRIVER, - &pNode->DeviceDriverName); - if (bResult == FALSE) - { - FreeDeviceInfoNode(&pNode); - OOPS(); - break; - } - - pNode->DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - success = SetupDiEnumDeviceInterfaces(DeviceList->DeviceInfo, - 0, - Guid, - index-1, - &pNode->DeviceInterfaceData); - if (!success) - { - FreeDeviceInfoNode(&pNode); - OOPS(); - break; - } - - success = SetupDiGetDeviceInterfaceDetail(DeviceList->DeviceInfo, - &pNode->DeviceInterfaceData, - NULL, - 0, - &requiredLength, - NULL); - - error = GetLastError(); - - if (!success && error != ERROR_INSUFFICIENT_BUFFER) - { - FreeDeviceInfoNode(&pNode); - OOPS(); - break; - } - - pNode->DeviceDetailData = ALLOC(requiredLength); - - if (pNode->DeviceDetailData == NULL) - { - FreeDeviceInfoNode(&pNode); - OOPS(); - break; - } - - pNode->DeviceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); - - success = SetupDiGetDeviceInterfaceDetail(DeviceList->DeviceInfo, - &pNode->DeviceInterfaceData, - pNode->DeviceDetailData, - requiredLength, - &requiredLength, - NULL); - if (!success) - { - FreeDeviceInfoNode(&pNode); - OOPS(); - break; - } - - InsertTailList(&DeviceList->ListHead, &pNode->ListEntry); - } - } - } -} - -DEVICE_POWER_STATE -AcquireDevicePowerState( - _Inout_ PDEVICE_INFO_NODE pNode - ) -{ - CM_POWER_DATA cmPowerData = {0}; - BOOL bResult; - - bResult = SetupDiGetDeviceRegistryProperty(pNode->DeviceInfo, - &pNode->DeviceInfoData, - SPDRP_DEVICE_POWER_DATA, - NULL, - (PBYTE)&cmPowerData, - sizeof(cmPowerData), - NULL); - - pNode->LatestDevicePowerState = bResult ? cmPowerData.PD_MostRecentPowerState : PowerDeviceUnspecified; - - return pNode->LatestDevicePowerState; -} - - -void -ClearDeviceList( - PDEVICE_GUID_LIST DeviceList - ) -{ - if (DeviceList->DeviceInfo != INVALID_HANDLE_VALUE) - { - SetupDiDestroyDeviceInfoList(DeviceList->DeviceInfo); - DeviceList->DeviceInfo = INVALID_HANDLE_VALUE; - } - - while (!IsListEmpty(&DeviceList->ListHead)) - { - PDEVICE_INFO_NODE pNode = NULL; - PLIST_ENTRY pEntry; - - pEntry = RemoveHeadList(&DeviceList->ListHead); - - pNode = CONTAINING_RECORD(pEntry, - DEVICE_INFO_NODE, - ListEntry); - - FreeDeviceInfoNode(&pNode); - } -} - -VOID -FreeDeviceInfoNode( - _In_ PDEVICE_INFO_NODE *ppNode - ) -{ - if (ppNode == NULL) - { - return; - } - - if (*ppNode == NULL) - { - return; - } - - if ((*ppNode)->DeviceDetailData != NULL) - { - FREE((*ppNode)->DeviceDetailData); - } - - if ((*ppNode)->DeviceDescName != NULL) - { - FREE((*ppNode)->DeviceDescName); - } - - if ((*ppNode)->DeviceDriverName != NULL) - { - FREE((*ppNode)->DeviceDriverName); - } - - FREE(*ppNode); - *ppNode = NULL; -} - -PDEVICE_INFO_NODE -FindMatchingDeviceNodeForDriverName( - _In_ PSTR DriverKeyName, - _In_ BOOLEAN IsHub - ) -{ - PDEVICE_INFO_NODE pNode = NULL; - PDEVICE_GUID_LIST pList = NULL; - PLIST_ENTRY pEntry = NULL; - - pList = IsHub ? &gHubList : &gDeviceList; - - pEntry = pList->ListHead.Flink; - - while (pEntry != &pList->ListHead) - { - pNode = CONTAINING_RECORD(pEntry, - DEVICE_INFO_NODE, - ListEntry); - if (_stricmp(DriverKeyName, pNode->DeviceDriverName) == 0) - { - return pNode; - } - - pEntry = pEntry->Flink; - } - - return NULL; -} - diff --git a/tests/projects/winsdk/usbview/h264.c b/tests/projects/winsdk/usbview/h264.c deleted file mode 100644 index 108a1d540..000000000 --- a/tests/projects/winsdk/usbview/h264.c +++ /dev/null @@ -1,750 +0,0 @@ -//***************************************************************************** -// I N C L U D E S -//***************************************************************************** - -#include "uvcview.h" -#include "h264.h" - -#ifdef H264_SUPPORT - -//***************************************************************************** -// G L O B A L S -//***************************************************************************** -// H.264 format -UCHAR g_expectedNumberOfH264FrameDescriptors = 0; -UCHAR g_numberOfH264FrameDescriptors = 0; - -// MJPEG format -UCHAR g_expectedNumberOfMJPEGFrameDescriptors = 0; -UCHAR g_numberOfMJPEGFrameDescriptors = 0; - -// Uncompressed frame format -UCHAR g_expectedNumberOfUncompressedFrameFrameDescriptors = 0; -UCHAR g_numberOfUncompressedFrameFrameDescriptors = 0; - -//***************************************************************************** -// -// external function prototypes -// -//***************************************************************************** -extern VOID VDisplayBytes (PUCHAR Data, USHORT Len ); - -//***************************************************************************** -// -// H.264 video format descriptor string tables -// -//***************************************************************************** -STRINGLIST slSliceModes[]= -{ - {1, "Maximum number of Macroblocks per slice mode", ""}, - {2, "Target compressed size per slice mode", ""}, - {4, "Number of slices per frame mode", ""}, - {8, "Number of Macroblock rows per slice mode", ""}, - {0x10, "Reserved", ""}, - {0x20, "Reserved", ""}, - {0x40, "Reserved", ""}, - {0x80, "Reserved", ""}, -}; - - -STRINGLIST slSyncFrameTypes[]= -{ - {1, "Reset" , ""}, - {2, "IDR frame with SPS and PPS", ""}, - {4, "IDR frame (with SPS and PPS) that is a long-term reference frame", ""}, - {8, "Non-IDR random-access I frame (with SPS and PPS)", ""}, - {0x10, "Non-IDR random-access I frame (with SPS and PPS) that is a long-term reference frame", ""}, - {0x20, "P frame that is a long-term reference frame", ""}, - {0x40, "Gradual Decoder Refresh frames", ""}, - {0x80, "Reserved", ""}, -}; - - -//***************************************************************************** -// -// H.264 video frame rate descriptor string tables -// -//***************************************************************************** -STRINGLIST slUsage[]= -{ - {0x00000001, "Real-time/UCConfig mode 0", ""}, // 0 - {0x00000002, "Real-time/UCConfig mode 1", ""}, - {0x00000004, "Real-time/UCConfig mode 2Q" ""}, - {0x00000008, "Real-time/UCConfig mode 2S" ""}, - {0x00000010, "Real-time/UCConfig mode 3", ""}, - {0x00000020, "Reserved", ""}, - {0x00000040, "Reserved", ""}, - {0x00000080, "Reserved", ""}, - - {0x00000100, "Broadcast mode 0", ""}, // 8 - {0x00000200, "Broadcast mode 1", ""}, - {0x00000400, "Broadcast mode 2", ""}, - {0x00000800, "Broadcast mode 3", ""}, - {0x00001000, "Broadcast mode 4", ""}, - {0x00002000, "Broadcast mode 5", ""}, - {0x00004000, "Broadcast mode 6", ""}, - {0x00008000, "Broadcast mode 7", ""}, - - {0x00010000, "File Storage mode with I and P slices (e.g. IPPP)", ""}, // 16 - {0x00020000, "File Storage mode with I, P, and B slices (e.g. IB...BP)", ""}, // 17 - {0x00040000, "File storage all I frame mode", ""}, // 18 - {0x00080000, "Reserved", ""}, // 19 - {0x00100000, "Reserved", ""}, // 20 - {0x00200000, "Reserved", ""}, // 21 - {0x00400000, "Reserved", ""}, // 22 - {0x00800000, "Reserved", ""}, // 23 - - {0x01000000, "MVC Stereo High Mode", ""}, // 24 - {0x02000000, "MVC Multiview Mode", ""}, // 25 - {0x04000000, "Reserved", ""}, // 26 - {0x08000000, "Reserved", ""}, // 27 - {0x10000000, "Reserved", ""}, // 28 - {0x20000000, "Reserved", ""}, // 29 - {0x40000000, "Reserved", ""}, // 30 - {0x80000000, "Reserved", ""}, // 31 - - }; -STRINGLIST slCapabilities[]= -{ - {0x0001, "CAVLC only", ""}, - {0x0002, "CABAC only", ""}, - {0x0004, "Constant frame rate", ""}, - {0x0008, "Separate QP for luma/chroma", ""}, - {0x0010, "Separate QP for Cb/Cr", ""}, - {0x0020, "No picture reordering", ""}, - {0x0040, "Long-term reference frame", ""}, - {0x0080, "Reserved", ""}, - {0x0100, "Reserved", ""}, - {0x0200, "Reserved", ""}, - {0x0400, "Reserved", ""}, - {0x0800, "Reserved", ""}, - {0x1000, "Reserved", ""}, - {0x2000, "Reserved", ""}, - {0x4000, "Reserved", ""}, - {0x8000, "Reserved", ""}, - }; - - - -STRINGLIST slRateControlModes[]= -{ - {1, "Variable Bit Rate (VBR) with underflow allowed (H.264 low_delay_hrd_flag = 1)", ""}, - {2, "Constant Bit Rate (CBR) (H.264 low_delay_hrd_flag = 0)", ""}, - {4, "Constant QP", ""}, - {8, "Global VBR with underflow allowed (H.264 low_delay_hrd_flag = 1)", ""}, - {0x10, "VBR without underflow (H.264 low_delay_hrd_flag = 0)", ""}, - {0x20, "Global VBR without underflow (H.264 low_delay_hrd_flag = 0)", ""}, - {0x40, "Reserved", ""}, - {0x80, "Reserved", ""}, -}; - - -STRINGLIST slProfiles[]= -{ - {0x4200, "Baseline Profile", ""}, - {0x4240, "Constrained Baseline Profile", ""}, - {0x4D00, "Main Profile", ""}, - {0x5300, "Scalable Baseline Profile", ""}, - {0x5304, "Scalable Constrained Baseline Profile", ""}, - {0x5600, "Scalable High Profile", ""}, - {0x5604, "Scalable Constrained High Profile", ""}, - {0x6400, "High Profile", ""}, - {0x640C, "Constrained High Profile", ""}, - {0x7600, "Multiview High Profile", ""}, - {0x8000, "Stereo High Profile", ""}, - }; - -//***************************************************************************** -// -// H.264 video encoding unit descriptor string tables -// -//***************************************************************************** - -STRINGLIST slEncodingUnitControls[]= -{ - {0x000001, "Select Layer", ""}, // D0 - {0x000002, "Profile and Toolset", ""}, // D1 - {0x000004, "Video Resolution", ""}, // D2 - {0x000008, "Minimum Frame Interval", ""}, // D3 - {0x000010, "Slice Mode", ""}, // D4 - {0x000020, "Rate Control Mode", ""}, // D5 - {0x000040, "Average Bit Rate", ""}, // D6 - {0x000080, "CPB Size ", ""}, // D7 - {0x000100, "Peak Bit Rate", ""}, // D8 - {0x000200, "Quantization Parameter", ""}, // D9 - {0x000400, "Synchronization and Long-Term Reference Frame", ""}, // D10 - {0x000800, "Long-Term Buffer Size", ""}, // D11 - {0x001000, "Picture Long-Term Reference", ""}, // D12 - {0x002000, "Valid LTR", ""}, // D13 - {0x004000, "Level IDC", ""}, // D14 - {0x008000, "SEI Message", ""}, // D15 - {0x010000, "QP Range", ""}, // D16 - {0x020000, "Priority ID", ""}, // D17 - {0x040000, "Start or Stop Layer/View", ""}, // D18 - {0x080000, "Error Resiliency", ""}, // D19 - {0x100000, "Reserved", ""}, // D20 - {0x200000, "Reserved", ""}, // D21 - {0x400000, "Reserved", ""}, // D22 - {0x800000, "Reserved", ""}, // D23 - }; - -//***************************************************************************** -// -// commaPrintNumber() -// -//***************************************************************************** -char * commaPrintNumber( ULONG number ) -{ - static char comma = ','; - static char retbuf[30]; - int digitCount = 0; - - // null-terminate the string - char * pOutputString = &retbuf[ sizeof(retbuf)-1 ]; - *pOutputString = '\0'; - - do - { - // for every 3rd digit, add a comma to the output string - if ( ( digitCount%3 ) == 0 && ( digitCount != 0 ) ) - { - *--pOutputString = comma; - } - *--pOutputString = '0' + number % 10; - number /= 10; - digitCount++; - } - while( number != 0 ); - - return pOutputString; -} - -//***************************************************************************** -// -// DisplayBitmapData() -// -// Note that USB is always oriented Little Endian (least significant byte -// at the lowest address). -// -// Inputs: -// PUCHAR pData - pointer to least significant byte of the data -// UCHAR byteCount - number of bytes to print in the pData data buffer -// char * stringLabel - string label to print for user's to identify the data type -// -//***************************************************************************** -void DisplayBitmapData(_In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, _In_ char * stringLabel) -{ - UCHAR byteIndex; - UCHAR data; - UCHAR mask; - UCHAR bitIndex; - UCHAR checkBit = 0; // the bit we want to print - - // print the label and all the bytes on the first line - AppendTextBuffer("%s : ", stringLabel); - VDisplayBytes( pData, byteCount ); - - for ( byteIndex = 0; byteIndex < byteCount; byteIndex++ ) - { - data = pData[ byteIndex ]; - checkBit = 0; // the control bit value we are going to print - for ( mask = 1, bitIndex = 0; bitIndex < 8; bitIndex++ ) - { - checkBit = data & mask; - AppendTextBuffer(" D%02d = %d %s\r\n", - bitIndex + 8 * byteIndex, // increment bit count - checkBit ? 1 : 0, - checkBit ? "yes" : " no"); - mask = mask << 1; - } - - } -} - -//***************************************************************************** -// -// DisplayBitmapDataWithStrings() -// -// Note that USB is always oriented Little Endian (least significant byte -// at the lowest address). -// -// This calls GetSTringFromList() to insert a string that corresonds to -// the bit value being print. -// -// Inputs: -// PUCHAR pData - pointer to least significant byte of the data -// UCHAR byteCount - number of bytes to print in the pData data buffer -// char * stringLabel - string label to print for user's to identify the data type -// STRINGLIST stringList - string table in which to look up bitmap strings -// ULONG numEntriesInTable - number of entrys (strings) in the table -//***************************************************************************** -void DisplayBitmapDataWithStrings( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, - _In_ char * stringLabel, _In_ PSTRINGLIST stringList, - ULONG numEntriesInTable) -{ - - UCHAR byteIndex; - UCHAR data; - UCHAR byteMask; - ULONGLONG stringMask; - UCHAR bitIndex; - UCHAR checkBit = 0; // the bit we want to print - - // print the label and all the bytes on the first line - AppendTextBuffer("%s : ", stringLabel); - VDisplayBytes( pData, byteCount ); - - for ( stringMask = 1, byteIndex = 0; byteIndex < byteCount; byteIndex++ ) - { - data = pData[ byteIndex ]; - checkBit = 0; // the control bit value we are going to print - for ( byteMask = 1, bitIndex = 0; bitIndex < 8; bitIndex++ ) - { - checkBit = data & byteMask; - AppendTextBuffer(" D%02d = %d %s %s\r\n", - bitIndex + 8 * byteIndex, // increment bit count - checkBit ? 1 : 0, - checkBit ? "yes - " : " no - ", - GetStringFromList(stringList, - numEntriesInTable, - stringMask, - "Reserved")); - - byteMask = byteMask << 1; - stringMask = stringMask << 1; - } - - } -} - -//***************************************************************************** -// -// DisplayVCH264Format() -// -//***************************************************************************** -BOOL DisplayVCH264Format( _In_reads_(sizeof(VIDEO_FORMAT_H264)) PVIDEO_FORMAT_H264 H264FormatDesc ) -{ - if ( H264FormatDesc->bSimulcastSupport == 0 ) - { - AppendTextBuffer("\r\n ===>Video Streaming H.264 Format Type Descriptor<===\r\n"); - } - else - { - AppendTextBuffer("\r\n ===>Video Streaming H.264 Simulcast Format Type Descriptor<===\r\n"); - } - AppendTextBuffer("bLength: 0x%02X = %d\r\n", H264FormatDesc->bLength, H264FormatDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X \r\n", H264FormatDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X \r\n", H264FormatDesc->bDescriptorSubtype); - AppendTextBuffer("bFormatIndex: 0x%02X = %d\r\n", H264FormatDesc->bFormatIndex, H264FormatDesc->bFormatIndex); - AppendTextBuffer("bNumFrameDescriptors: 0x%02X = %d\r\n", H264FormatDesc->bNumFrameDescriptors, H264FormatDesc->bNumFrameDescriptors); - AppendTextBuffer("bDefaultFrameIndex: 0x%02X = %d\r\n", H264FormatDesc->bDefaultFrameIndex, H264FormatDesc->bDefaultFrameIndex); - AppendTextBuffer("bMaxCodecConfigDelay: 0x%02X = %d frames\r\n", H264FormatDesc->bMaxCodecConfigDelay, H264FormatDesc->bMaxCodecConfigDelay); - DisplayBitmapDataWithStrings( H264FormatDesc->bmSupportedSliceModes, sizeof(H264FormatDesc->bmSupportedSliceModes), "bmSupportedSliceModes", slSliceModes, sizeof(slSliceModes)/sizeof(STRINGLIST) ); - DisplayBitmapDataWithStrings( H264FormatDesc->bmSupportedSyncFrameTypes, sizeof(H264FormatDesc->bmSupportedSyncFrameTypes), "bmSupportedSyncFrameTypes", slSyncFrameTypes, sizeof(slSyncFrameTypes)/sizeof(STRINGLIST) ); - - // handle bResolutionScaling - if ( H264FormatDesc->bResolutionScaling == 0 ) - { - AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Not Supported\r\n", - H264FormatDesc->bResolutionScaling, - H264FormatDesc->bResolutionScaling ); - } - else if ( H264FormatDesc->bResolutionScaling == 1 ) - { - AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Limited to 1.5 or 2.0 scaling in both directions, while maintaining the aspect ratio.\r\n", - H264FormatDesc->bResolutionScaling, - H264FormatDesc->bResolutionScaling ); - } - else if ( H264FormatDesc->bResolutionScaling == 2 ) - { - AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Limited to 1.0, 1.5 or 2.0 scaling in either direction.\r\n", - H264FormatDesc->bResolutionScaling, - H264FormatDesc->bResolutionScaling ); - } - else if ( H264FormatDesc->bResolutionScaling == 3 ) - { - AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Limited to resolutions reported by the associated Frame Descriptors\r\n", - H264FormatDesc->bResolutionScaling, - H264FormatDesc->bResolutionScaling ); - } - else if ( H264FormatDesc->bResolutionScaling == 4 ) - { - AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Arbitrary scaling\r\n", - H264FormatDesc->bResolutionScaling, - H264FormatDesc->bResolutionScaling ); - } - else // 5 ... 255 - { - AppendTextBuffer("bResolutionScaling: 0x%02X = %d, Reserved \r\n", - H264FormatDesc->bResolutionScaling, - H264FormatDesc->bResolutionScaling ); - } - - // handle bSimulcastSupport - if ( H264FormatDesc->bSimulcastSupport == 0 ) - { - AppendTextBuffer("bSimulcastSupport: 0x%02X = %d, one stream\r\n", - H264FormatDesc->bSimulcastSupport, - H264FormatDesc->bSimulcastSupport ); - } - else if ( H264FormatDesc->bSimulcastSupport == 1 ) - { - AppendTextBuffer("bSimulcastSupport: 0x%02X = %d, multiple streams\r\n", - H264FormatDesc->bSimulcastSupport, - H264FormatDesc->bSimulcastSupport ); - } - else // ( H264FormatDesc->bSimulcastSupport > 1 ) - { - AppendTextBuffer("bSimulcastSupport: 0x%02X = %d *!*ERROR: unknown bSimulcastSupport \r\n", - H264FormatDesc->bSimulcastSupport, - H264FormatDesc->bSimulcastSupport, - H264FormatDesc->bSimulcastSupport ); - } - - - DisplayBitmapDataWithStrings( &(H264FormatDesc->bmSupportedRateControlModes), sizeof(H264FormatDesc->bmSupportedRateControlModes), "bmSupportedRateControlModes", slRateControlModes, sizeof(slRateControlModes)/sizeof(STRINGLIST) ); - - // Note that USB is Little Endian according to the UVC 2.0 spec - - - // Resolutions with no scalability - AppendTextBuffer("wMaxMBperSecOneResolutionNoScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecOneResolutionNoScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionNoScalability) ); - - AppendTextBuffer("wMaxMBperSecTwoResolutionsNoScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecTwoResolutionsNoScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsNoScalability) ); - - AppendTextBuffer("wMaxMBperSecThreeResolutionsNoScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecThreeResolutionsNoScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsNoScalability) ); - - AppendTextBuffer("wMaxMBperSecFourResolutionsNoScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecFourResolutionsNoScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsNoScalability) ); - - // Resolutions with temporal scalability - AppendTextBuffer("wMaxMBperSecOneResolutionTemporalScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecOneResolutionTemporalScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalScalability) ); - - AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalScalability) ); - - AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalScalability) ); - - AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecFourResolutionsTemporalScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalScalability) ); - - // Resolutions with temporal and quality scalability - AppendTextBuffer("wMaxMBperSecOneResolutionTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecOneResolutionTemporalQualityScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalQualityScalability) ); - - AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalQualityScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalQualityScalability) ); - - - AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalQualityScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalQualityScalability) ); - - AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalQualityScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecFourResolutionsTemporalQualityScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalQualityScalability) ); - - // Resolutions with temporal and spatial scalability - AppendTextBuffer("wMaxMBperSecOneResolutionTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecOneResolutionTemporalSpatialScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionTemporalSpatialScalability) ); - - AppendTextBuffer("wMaxMBperSecTwoResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalSpatialScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsTemporalSpatialScalability) ); - - - AppendTextBuffer("wMaxMBperSecThreeResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalSpatialScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsTemporalSpatialScalability) ); - - AppendTextBuffer("wMaxMBperSecFourResolutionsTemporalSpatialScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecFourResolutionsTemporalSpatialScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsTemporalSpatialScalability) ); - - // Resolutions with full scalability - AppendTextBuffer("wMaxMBperSecOneResolutionFullScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecOneResolutionFullScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecOneResolutionFullScalability) ); - - AppendTextBuffer("wMaxMBperSecTwoResolutionsFullScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecTwoResolutionsFullScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecTwoResolutionsFullScalability) ); - - AppendTextBuffer("wMaxMBperSecThreeResolutionsFullScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecThreeResolutionsFullScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecThreeResolutionsFullScalability) ); - - AppendTextBuffer("wMaxMBperSecFourResolutionsFullScalability: 0x%04X (%s MB/sec)\r\n", - H264FormatDesc->wMaxMBperSecFourResolutionsFullScalability, - commaPrintNumber(1000*H264FormatDesc->wMaxMBperSecFourResolutionsFullScalability) ); - - - return TRUE; -} - -//***************************************************************************** -// -// DisplayVCH264FrameType() -// -//***************************************************************************** -BOOL DisplayVCH264FrameType( _In_reads_(sizeof(VIDEO_FRAME_H264)) PVIDEO_FRAME_H264 H264FrameDesc ) -{ - - ULONG frameIntervalIndex; - ULONG value; - ULONG i; - - AppendTextBuffer("\r\n ===>Video Streaming H.264 Frame Type Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X = %d\r\n", H264FrameDesc->bLength, H264FrameDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X \r\n", H264FrameDesc->bDescriptorType); - AppendTextBuffer("bDescriptorSubtype: 0x%02X \r\n", H264FrameDesc->bDescriptorSubtype); - AppendTextBuffer("bFrameIndex: 0x%02X = %d\r\n", H264FrameDesc->bFrameIndex, H264FrameDesc->bFrameIndex); - AppendTextBuffer("wWidth: 0x%04X = %d\r\n", H264FrameDesc->wWidth, H264FrameDesc->wWidth); - AppendTextBuffer("wHeight: 0x%04X = %d\r\n", H264FrameDesc->wHeight, H264FrameDesc->wHeight); - AppendTextBuffer("wSARwidth: 0x%04X = %d\r\n", H264FrameDesc->wSARwidth, H264FrameDesc->wSARwidth); - AppendTextBuffer("wSARheight: 0x%04X = %d\r\n", H264FrameDesc->wSARheight, H264FrameDesc->wSARheight); - AppendTextBuffer("wProfile: 0x%04X - %s\r\n", H264FrameDesc->wProfile, - GetStringFromList( slProfiles, // string table - sizeof(slProfiles)/sizeof(STRINGLIST), // number of strings in the table - H264FrameDesc->wProfile, // index of string we want to look up in the string table - "Unknown profile" ) ); // string to use if the lookup fails - - AppendTextBuffer("bLevelIDC: 0x%02X = %d = Level %01.01lf \r\n", - H264FrameDesc->bLevelIDC, H264FrameDesc->bLevelIDC, H264FrameDesc->bLevelIDC/10.0 ); - - AppendTextBuffer("wConstrainedToolset: 0x%04X %s\r\n", H264FrameDesc->wConstrainedToolset, - ((H264FrameDesc->wConstrainedToolset == 0) ? "- Reserved" : "*!*ERROR: field is reserved and should be zero")); - - DisplayBitmapDataWithStrings( H264FrameDesc->bmSupportedUsages, sizeof(H264FrameDesc->bmSupportedUsages), "bmSupportedUsages", slUsage, sizeof(slUsage)/sizeof(STRINGLIST) ); - DisplayBitmapDataWithStrings( H264FrameDesc->bmCapabilities, sizeof(H264FrameDesc->bmCapabilities), "bmCapabilities", slCapabilities, sizeof(slCapabilities)/sizeof(STRINGLIST) ); - - - // bmSVCCapabilities[4] - AppendTextBuffer("%s : ", "bmSVCCapabilities"); - VDisplayBytes( &(H264FrameDesc->bmSVCCapabilities[0]), sizeof(H264FrameDesc->bmSVCCapabilities) ); - AppendTextBuffer(" D2..D0 = %d Maximum number of temporal layers = %d\r\n", - H264FrameDesc->bmSVCCapabilities[0] & 0x7, - (H264FrameDesc->bmSVCCapabilities[0] & 0x7) + 1 ); - AppendTextBuffer(" D3 = %d %s - Rewrite Support\r\n", (H264FrameDesc->bmSVCCapabilities[0] & 0x8) >> 3, - ((H264FrameDesc->bmSVCCapabilities[0] & 0x8) >> 3) ? "yes" : " no" ); - AppendTextBuffer(" D6..D4 = %d Maximum number of CGS layers = %d\r\n", - (H264FrameDesc->bmSVCCapabilities[0] & 0x70) >> 4, - ((H264FrameDesc->bmSVCCapabilities[0] & 0x70) >> 4) + 1 ); - - value = ( H264FrameDesc->bmSVCCapabilities[1] << 8 ) | H264FrameDesc->bmSVCCapabilities[0]; - value >>= 7; // shift bit 7 right so that it ends up in the lsb of value - value &= 0x7; - AppendTextBuffer(" D9..D7 = %d Number of MGS sublayers\r\n", value ); - - AppendTextBuffer(" D10 = %d %s - Additional SNR scalability support in spatial enhancement layers\r\n", - (H264FrameDesc->bmSVCCapabilities[1] & 0x4) >> 2, - ((H264FrameDesc->bmSVCCapabilities[1] & 0x4) >> 2) ? "yes" : " no"); - AppendTextBuffer(" D13..D11 = %d Maximum number of spatial layers = %d\r\n", - (H264FrameDesc->bmSVCCapabilities[1] & 0x38) >> 3, - ((H264FrameDesc->bmSVCCapabilities[1] & 0x38) >> 3) + 1 ); - - value = ( H264FrameDesc->bmSVCCapabilities[3] << 16 ) | ( H264FrameDesc->bmSVCCapabilities[2] << 8 ) | H264FrameDesc->bmSVCCapabilities[1]; - value >>= 6; // get bit 14 at LSB - for ( i = 0; i < 18; i++ ) // bits 31...14 - { - AppendTextBuffer(" D%02d = %d %s - Reserved \r\n", 14 + i, value & 0x1, (value & 0x1) ? "yes" : " no" ); - value >>= 1; - } - - // bmMVCCapabilities[4] - AppendTextBuffer("%s : ", "bmMVCCapabilities"); - VDisplayBytes( &(H264FrameDesc->bmMVCCapabilities[0]), sizeof(H264FrameDesc->bmMVCCapabilities) ); - AppendTextBuffer(" D2..D0 = %d Maximum number of temporal layers = %d\r\n", - H264FrameDesc->bmMVCCapabilities[0] & 0x7, - ((H264FrameDesc->bmMVCCapabilities[0] & 0x7) + 1) ); - - value = (H264FrameDesc->bmMVCCapabilities[1] << 8) | H264FrameDesc->bmMVCCapabilities[0]; - value >>= 3; // shift bit 3 right so that it ends up in the lsb of value - value &= 0xff; - AppendTextBuffer(" D10..D3 = %d Maximum number of view components = %d\r\n", - value, value + 1); - - value = ( (H264FrameDesc->bmMVCCapabilities[3] << 16) | (H264FrameDesc->bmMVCCapabilities[2] << 8) | H264FrameDesc->bmMVCCapabilities[1] ); - value >>= 3; // shift bit 11 right so that it ends up in the lsb of value - for ( i = 0; i < 21; i++ ) // bits 31...11 - { - AppendTextBuffer(" D%02d = %d %s - Reserved \r\n", 11 + i, value & 0x1, (value & 0x1) ? "yes" : " no" ); - value >>= 1; - } - - - AppendTextBuffer("dwMinBitRate: 0x%08X = %s bps\r\n", H264FrameDesc->dwMinBitRate, commaPrintNumber(H264FrameDesc->dwMinBitRate)); - AppendTextBuffer("dwMaxBitRate: 0x%08X = %s bps\r\n", H264FrameDesc->dwMaxBitRate, commaPrintNumber(H264FrameDesc->dwMaxBitRate)); - - // To convert the default frame interval, which is in 100 ns units, to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - AppendTextBuffer("dwDefaultFrameInterval: 0x%08X = %lf mSec (%4.2f Hz) \r\n", - H264FrameDesc->dwDefaultFrameInterval, ((double)H264FrameDesc->dwDefaultFrameInterval)/10000.0, (10000000.0/((double)H264FrameDesc->dwDefaultFrameInterval))); - AppendTextBuffer("bNumFrameIntervals: 0x%02X = %d\r\n", H264FrameDesc->bNumFrameIntervals, H264FrameDesc->bNumFrameIntervals); - - - // frame interval 100 ns units. - - //To convert the frame interval to seconds we would divide by 10,000,000. - // 100 ns = 10^(-7) seconds = 1/10,000,000 - - // To convert the frame interval to Hz, we divide by 10,000,000 and then take the inverse - - // To convert the frame interval to milliseconds, we divide by 10,000. - // 100 ns = 10^(-7) seconds = 10^(-7) sec * 1000 msec/sec = 10^(-7) * 10^3 milleseconds = 10^(-4) seconds - // = 1/10,000 milliseconds - - for ( frameIntervalIndex = 0; frameIntervalIndex < H264FrameDesc->bNumFrameIntervals; frameIntervalIndex++ ) - { - value = (ULONG)H264FrameDesc->dwFrameInterval[ frameIntervalIndex ]; - AppendTextBuffer("dwFrameInterval[%d]: 0x%08x = %lf mSec (%4.2f Hz)\r\n", frameIntervalIndex, value, ((double)value)/10000.0, (10000000.0/((double)value)) ); - - } - - return TRUE; -} - - -//***************************************************************************** -// -// DisplayVCH264EncodingUnit() -// -//***************************************************************************** -BOOL DisplayVCH264EncodingUnit( - _In_reads_(sizeof(VIDEO_ENCODING_UNIT)) PVIDEO_ENCODING_UNIT VidEncodingDesc - ) -{ - - PUCHAR pControlsRunTimeData = NULL; - - AppendTextBuffer("\r\n ===>Video Control Encoding Unit Descriptor<===\r\n"); - AppendTextBuffer("bLength: 0x%02X = %d\r\n", VidEncodingDesc->bLength, VidEncodingDesc->bLength); - AppendTextBuffer("bDescriptorType: 0x%02X \r\n", VidEncodingDesc->bDescriptorType ); - AppendTextBuffer("bDescriptorSubtype: 0x%02X \r\n", VidEncodingDesc->bDescriptorSubtype ); - AppendTextBuffer("bUnitID: 0x%02X = %d\r\n", VidEncodingDesc->bUnitID, VidEncodingDesc->bUnitID); - AppendTextBuffer("bSourceID: 0x%02X = %d\r\n", VidEncodingDesc->bSourceID, VidEncodingDesc->bSourceID); - AppendTextBuffer("iEncoding: 0x%02X = %d\r\n", VidEncodingDesc->iEncoding, VidEncodingDesc->iEncoding); - AppendTextBuffer("bControlSize: 0x%02X = %d\r\n", VidEncodingDesc->bControlSize, VidEncodingDesc->bControlSize); - - if ( VidEncodingDesc->bControlSize > 0) - { - // Encoding Unit Descriptor bmControls field - DisplayBitmapDataWithStrings( VidEncodingDesc->bmControls, VidEncodingDesc->bControlSize /* print bControlSize bytes worth of bitmap info */, - "bmControls", slEncodingUnitControls, sizeof(slEncodingUnitControls)/sizeof(STRINGLIST) ); - - // Encoding Unit Descriptor bmControlsRuntime field - pControlsRunTimeData = ((UCHAR *)(&VidEncodingDesc->bmControls)) + VidEncodingDesc->bControlSize; - DisplayBitmapDataWithStrings( pControlsRunTimeData, VidEncodingDesc->bControlSize /* print bControlSize bytes worth of bitmap info */, - "bmControlsRuntime", slEncodingUnitControls, sizeof(slEncodingUnitControls)/sizeof(STRINGLIST) ); - } - return TRUE; -} - -//***************************************************************************** -// -// DoAdditionalErrorChecks() -// -// Currently this function only checks to see that the number of frame -// descriptors actually found equals the number specified in the corresponding -// format descriptor. -// -// Because this potentially involves parsing multiple frame descriptors, we -// call this routine after the video descriptor has been parsed and displayed. -// -//***************************************************************************** -void DoAdditionalErrorChecks() -{ - if( g_expectedNumberOfH264FrameDescriptors > 0 || g_numberOfH264FrameDescriptors > 0 - || g_expectedNumberOfUncompressedFrameFrameDescriptors > 0 || g_numberOfUncompressedFrameFrameDescriptors > 0 - || g_expectedNumberOfMJPEGFrameDescriptors > 0 || g_numberOfMJPEGFrameDescriptors > 0) - { - AppendTextBuffer("\r\n ===>Additional Error Checking<===\r\n"); - - // H.264 frame descriptor - if( g_expectedNumberOfH264FrameDescriptors > 0 || g_numberOfH264FrameDescriptors > 0) - { - if ( g_expectedNumberOfH264FrameDescriptors == g_numberOfH264FrameDescriptors ) - { - AppendTextBuffer("PASS: number of H.264 frame descriptors (%d) == number of frame descriptors (%d) specified in H.264 format descriptor(s)\r\n", - g_expectedNumberOfH264FrameDescriptors, g_numberOfH264FrameDescriptors ); - } - else - { - AppendTextBuffer("FAIL: number of H.264 frame descriptors (%d) != number of frame descriptors (%d) specified in H.264 format descriptor(s)\r\n", - g_expectedNumberOfH264FrameDescriptors, g_numberOfH264FrameDescriptors ); - } - } - - // uncompressed frame descriptor - if( g_expectedNumberOfUncompressedFrameFrameDescriptors > 0 || g_numberOfUncompressedFrameFrameDescriptors > 0) - { - - if ( g_expectedNumberOfUncompressedFrameFrameDescriptors == g_numberOfUncompressedFrameFrameDescriptors ) - { - AppendTextBuffer("PASS: number of uncompressed-frame frame descriptors (%d) == number of frame descriptors (%d) specified in uncompressed format descriptor(s)\r\n", - g_expectedNumberOfUncompressedFrameFrameDescriptors, g_numberOfUncompressedFrameFrameDescriptors ); - } - else - { - AppendTextBuffer("FAIL: number of uncompressed-frame frame descriptors (%d) != number of frame descriptors (%d) specified in uncompressed format descriptor(s)\r\n", - g_expectedNumberOfUncompressedFrameFrameDescriptors, g_numberOfUncompressedFrameFrameDescriptors ); - } - } - - // MJPEG frame descriptor - if( g_expectedNumberOfMJPEGFrameDescriptors > 0 || g_numberOfMJPEGFrameDescriptors > 0) - { - if ( g_expectedNumberOfMJPEGFrameDescriptors == g_numberOfMJPEGFrameDescriptors ) - { - AppendTextBuffer("PASS: number of MJPEG frame descriptors (%d) == number of frame descriptors (%d) specified in MJPEG format descriptor(s)\r\n", - g_expectedNumberOfMJPEGFrameDescriptors, g_numberOfMJPEGFrameDescriptors ); - } - else - { - AppendTextBuffer("FAIL: number of MJPEG frame descriptors (%d) != number of frame descriptors (%d) specified in MJPEG format descriptor(s)\r\n", - g_expectedNumberOfMJPEGFrameDescriptors, g_numberOfMJPEGFrameDescriptors ); - } - } - } -} - -//***************************************************************************** -// -// ResetErrorCounts() -// -//***************************************************************************** -void ResetErrorCounts() -{ - - // H.264 format - g_expectedNumberOfH264FrameDescriptors = 0; - g_numberOfH264FrameDescriptors = 0; - - // MJPEG format - g_expectedNumberOfMJPEGFrameDescriptors = 0; - g_numberOfMJPEGFrameDescriptors = 0; - - // Uncompressed frame format - g_expectedNumberOfUncompressedFrameFrameDescriptors = 0; - g_numberOfUncompressedFrameFrameDescriptors = 0; -} - -#endif //H264_SUPPORT diff --git a/tests/projects/winsdk/usbview/h264.h b/tests/projects/winsdk/usbview/h264.h deleted file mode 100644 index 841318922..000000000 --- a/tests/projects/winsdk/usbview/h264.h +++ /dev/null @@ -1,164 +0,0 @@ -#pragma once - -#ifdef H264_SUPPORT - -//***************************************************************************** -// -// external variables -// -//***************************************************************************** -extern UCHAR g_expectedNumberOfH264FrameDescriptors; -extern UCHAR g_numberOfH264FrameDescriptors; - -extern UCHAR g_expectedNumberOfMJPEGFrameDescriptors; -extern UCHAR g_numberOfMJPEGFrameDescriptors; - -extern UCHAR g_expectedNumberOfUncompressedFrameFrameDescriptors; -extern UCHAR g_numberOfUncompressedFrameFrameDescriptors; - -#endif - - - -//***************************************************************************** -// -// defines -// -//***************************************************************************** - -//Version information printed at lower left of UI Window and top of output text window -#define USBVIEW_MAJOR_VERSION 2 -#define USBVIEW_MINOR_VERSION 0 -#define UVC_SPEC_MAJOR_VERSION 1 -#define UVC_SPEC_MINOR_VERSION 5 - - -// definitions take from the proposed UVC 1.5 spec -#define VS_FORMAT_H264 0x13 -#define VS_FRAME_H264 0x14 - - -// Video Class-Specific VC Interface Descriptor Subtypes -// Note, this needs to be added to the list already in C:\nt\sdpublic\internal\drivers\inc\uvcdesc.h -// Also, note that MAX_TYPE_UNIT needs to be bumped up by 1 to account for this new subtype.. -#define H264_ENCODING_UNIT 7 - -//***************************************************************************** -// -// struct definitions -// -//***************************************************************************** - -// VideoStreaming H.264 Format Descriptor -#pragma pack(push, 1) // pack on a 1 byte boundary -typedef struct _VIDEO_FORMAT_H264 -{ // offset (in bytes): - UCHAR bLength; // 0 - UCHAR bDescriptorType; // 1 - UCHAR bDescriptorSubtype; // 2 - UCHAR bFormatIndex; // 3 - UCHAR bNumFrameDescriptors; // 4 - UCHAR bDefaultFrameIndex; // 5 - UCHAR bMaxCodecConfigDelay; // 6 - UCHAR bmSupportedSliceModes[1]; // 7 - UCHAR bmSupportedSyncFrameTypes[1]; // 8 - UCHAR bResolutionScaling; // 9 - UCHAR bSimulcastSupport; // 10 - UCHAR bmSupportedRateControlModes; // 11 - - USHORT wMaxMBperSecOneResolutionNoScalability; // 12 - USHORT wMaxMBperSecTwoResolutionsNoScalability; // 14 - USHORT wMaxMBperSecThreeResolutionsNoScalability; // 16 - USHORT wMaxMBperSecFourResolutionsNoScalability; // 18 - - USHORT wMaxMBperSecOneResolutionTemporalScalability; // 20 - USHORT wMaxMBperSecTwoResolutionsTemporalScalability; // 22 - USHORT wMaxMBperSecThreeResolutionsTemporalScalability; // 24 - USHORT wMaxMBperSecFourResolutionsTemporalScalability; // 26 - - USHORT wMaxMBperSecOneResolutionTemporalQualityScalability; // 28 - USHORT wMaxMBperSecTwoResolutionsTemporalQualityScalability; // 30 - USHORT wMaxMBperSecThreeResolutionsTemporalQualityScalability; // 32 - USHORT wMaxMBperSecFourResolutionsTemporalQualityScalability; // 34 - - USHORT wMaxMBperSecOneResolutionTemporalSpatialScalability; // 36 - USHORT wMaxMBperSecTwoResolutionsTemporalSpatialScalability; // 38 - USHORT wMaxMBperSecThreeResolutionsTemporalSpatialScalability; // 40 - USHORT wMaxMBperSecFourResolutionsTemporalSpatialScalability; // 42 - - USHORT wMaxMBperSecOneResolutionFullScalability; // 44 - USHORT wMaxMBperSecTwoResolutionsFullScalability; // 46 - USHORT wMaxMBperSecThreeResolutionsFullScalability; // 48 - USHORT wMaxMBperSecFourResolutionsFullScalability; // 50 -} VIDEO_FORMAT_H264, *PVIDEO_FORMAT_H264; -#pragma pack(pop) - - -// VideoStreaming H.264 Frame Descriptor -#pragma pack(push, 1) // pack on a 1 byte boundary - -// Disable warning on zero sized array in CPP compiler -#pragma warning(push) -#pragma warning(disable:4200) // Zero sized array - -typedef struct _VIDEO_FRAME_H264 -{ // offset (in bytes): - UCHAR bLength; // 0 - UCHAR bDescriptorType; // 1 - UCHAR bDescriptorSubtype; // 2 - UCHAR bFrameIndex; // 3 - USHORT wWidth; // 4 - USHORT wHeight; // 6 - USHORT wSARwidth; // 8 - USHORT wSARheight; // 10 - USHORT wProfile; // 12 - UCHAR bLevelIDC; // 14 - USHORT wConstrainedToolset; // 15 - UCHAR bmSupportedUsages[4]; // 17 - UCHAR bmCapabilities[2]; // 21 - UCHAR bmSVCCapabilities[4]; // 23 - UCHAR bmMVCCapabilities[4]; // 27 - ULONG dwMinBitRate; // 31 - ULONG dwMaxBitRate; // 35 - ULONG dwDefaultFrameInterval; // 39 - UCHAR bNumFrameIntervals; // 43 - ULONG dwFrameInterval[]; // 44 variable-length parameter -} VIDEO_FRAME_H264, *PVIDEO_FRAME_H264; -#pragma warning(pop) -#pragma pack(pop) - - -// VideoControl Encoding Unit Descriptor -#pragma pack(push, 1) // pack on a 1 byte boundary -#pragma warning(push) -#pragma warning(disable:4200) // Zero sized array -typedef struct //_VIDEO_ENCODING_UNIT -{ // offset (in bytes): - UCHAR bLength; // 0 - UCHAR bDescriptorType; // 1 - UCHAR bDescriptorSubtype; // 2 - UCHAR bUnitID; // 3 - UCHAR bSourceID; // 4 - UCHAR iEncoding; // 5 - UCHAR bControlSize; // 6 - UCHAR bmControls[]; // 7 - variable-length parameter (bControlSize specifies the size) -} VIDEO_ENCODING_UNIT, *PVIDEO_ENCODING_UNIT; -// after bmControls[] there is also the variable-length parameter (bControlSize specifies the size: -// UCHAR bmControlsRunTime[] -#pragma warning(pop) -#pragma pack(pop) - - - -//***************************************************************************** -// -// function prototypes -// -//***************************************************************************** -BOOL DisplayVCH264Format( _In_reads_(sizeof(VIDEO_FORMAT_H264)) PVIDEO_FORMAT_H264 H264FormatDesc ); -BOOL DisplayVCH264FrameType( _In_reads_(sizeof(VIDEO_FRAME_H264)) PVIDEO_FRAME_H264 H264FrameDesc ); -BOOL DisplayVCH264EncodingUnit( _In_reads_(sizeof(VIDEO_ENCODING_UNIT)) PVIDEO_ENCODING_UNIT VidEncodingDesc ); -void DisplayBitmapData( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, _In_ char * stringLabel); -void DisplayBitmapDataWithStrings( _In_reads_(byteCount) PUCHAR pData, UCHAR byteCount, _In_ char * stringLabel, _In_ PSTRINGLIST stringList, ULONG numEntriesInTable ); -void DoAdditionalErrorChecks(); -void ResetErrorCounts(); diff --git a/tests/projects/winsdk/usbview/hub.ico b/tests/projects/winsdk/usbview/hub.ico deleted file mode 100644 index d0620df89..000000000 Binary files a/tests/projects/winsdk/usbview/hub.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/langidlist.h b/tests/projects/winsdk/usbview/langidlist.h deleted file mode 100644 index 0f2d90621..000000000 --- a/tests/projects/winsdk/usbview/langidlist.h +++ /dev/null @@ -1,206 +0,0 @@ -/*++ - -Copyright (c) 2003-2008 Microsoft Corporation - -Module Name: - - LANGIDLIST.H - -Abstract: - - This file LANGIDLIST.H contains content from USB.org, and was reviewed - by LCA in June 2011. Per discussion with USB consortium counsel their - material is "free to any use". - - This header file contains a list of all currently known USB Language IDs - and the language name associated with each Language ID. - - - -Source: - http://www.usb.org - -Environment: - - Kernel & user mode - -Revision History: - - 03-28-03 : created - ---*/ - -#ifndef __LANGIDLIST_H__ -#define __LANGIDLIST_H__ - -// -// Language ID structure -// -typedef struct { - USHORT usLangID; - PCHAR szLanguage; -} USBLANGID, *PUSBLANGID; - -// -// This list built from information obtained on Nov-30-2000 from -// http://www.usb.org -// -// This information has not been independently verified and no claims -// are made here as to its accuracy. -// - -USBLANGID USBLangIDs[] = -{ - {1078 , /* 0x0436 */ "Afrikaans"}, - {1052 , /* 0x041c */ "Albanian"}, - {1025 , /* 0x0401 */ "Arabic (Saudi Arabia)"}, - {2049 , /* 0x0801 */ "Arabic (Iraq)"}, - {3073 , /* 0x0c01 */ "Arabic (Egypt)"}, - {4097 , /* 0x1001 */ "Arabic (Libya)"}, - {5121 , /* 0x1401 */ "Arabic (Algeria)"}, - {6145 , /* 0x1801 */ "Arabic (Morocco)"}, - {7169 , /* 0x1c01 */ "Arabic (Tunisia)"}, - {8193 , /* 0x2001 */ "Arabic (Oman)"}, - {9217 , /* 0x2401 */ "Arabic (Yemen)"}, - {10241 , /* 0x2801 */ "Arabic (Syria)"}, - {11265 , /* 0x2c01 */ "Arabic (Jordan)"}, - {12289 , /* 0x3001 */ "Arabic (Lebanon)"}, - {13313 , /* 0x3401 */ "Arabic (Kuwait)"}, - {14337 , /* 0x3801 */ "Arabic (U.A.E.)"}, - {15361 , /* 0x3c01 */ "Arabic (Bahrain)"}, - {16385 , /* 0x4001 */ "Arabic (Qatar) "}, - {1067 , /* 0x042b */ "Armenian"}, - {1101 , /* 0x044d */ "Assamese"}, - {1068 , /* 0x042c */ "Azeri (Latin)"}, - {2092 , /* 0x082c */ "Azeri (Cyrillic)"}, - {1069 , /* 0x042d */ "Basque"}, - {1059 , /* 0x0423 */ "Belarussian"}, - {1093 , /* 0x0445 */ "Bengali"}, - {1026 , /* 0x0402 */ "Bulgarian"}, - {1109 , /* 0x0455 */ "Burmese"}, - {1027 , /* 0x0403 */ "Catalan"}, - {1028 , /* 0x0404 */ "Chinese (Taiwan)"}, - {2052 , /* 0x0804 */ "Chinese (PRC)"}, - {3076 , /* 0x0c04 */ "Chinese (Hong Kong SAR, PRC)"}, - {4100 , /* 0x1004 */ "Chinese (Singapore)"}, - {5124 , /* 0x1404 */ "Chinese (MACAO SAR)"}, - {1050 , /* 0x041a */ "Croatian"}, - {1029 , /* 0x0405 */ "Czech"}, - {1030 , /* 0x0406 */ "Danish"}, - {1043 , /* 0x0413 */ "Dutch (Netherlands)"}, - {2067 , /* 0x0813 */ "Dutch (Belgium)"}, - {1033 , /* 0x0409 */ "English (United States)"}, - {2057 , /* 0x0809 */ "English (United Kingdom)"}, - {3081 , /* 0x0c09 */ "English (Australian)"}, - {4105 , /* 0x1009 */ "English (Canadian)"}, - {5129 , /* 0x1409 */ "English (New Zealand)"}, - {6153 , /* 0x1809 */ "English (Ireland)"}, - {7177 , /* 0x1c09 */ "English (South Africa)"}, - {8201 , /* 0x2009 */ "English (Jamaica)"}, - {9225 , /* 0x2409 */ "English (Caribbean)"}, - {10249 , /* 0x2809 */ "English (Belize)"}, - {11273 , /* 0x2c09 */ "English (Trinidad)"}, - {12297 , /* 0x3009 */ "English (Zimbabwe)"}, - {13321 , /* 0x3409 */ "English (Philippines)"}, - {1061 , /* 0x0425 */ "Estonian"}, - {1080 , /* 0x0438 */ "Faeroese"}, - {1065 , /* 0x0429 */ "Farsi "}, - {1035 , /* 0x040b */ "Finnish"}, - {1036 , /* 0x040c */ "French (Standard)"}, - {2060 , /* 0x080c */ "French (Belgian)"}, - {3084 , /* 0x0c0c */ "French (Canadian)"}, - {4108 , /* 0x100c */ "French (Switzerland)"}, - {5132 , /* 0x140c */ "French (Luxembourg)"}, - {6156 , /* 0x180c */ "French (Monaco)"}, - {1079 , /* 0x0437 */ "Georgian"}, - {1031 , /* 0x0407 */ "German (Standard)"}, - {2055 , /* 0x0807 */ "German (Switzerland)"}, - {3079 , /* 0x0c07 */ "German (Austria)"}, - {4103 , /* 0x1007 */ "German (Luxembourg)"}, - {5127 , /* 0x1407 */ "German (Liechtenstein)"}, - {1032 , /* 0x0408 */ "Greek"}, - {1095 , /* 0x0447 */ "Gujarati"}, - {1037 , /* 0x040d */ "Hebrew"}, - {1081 , /* 0x0439 */ "Hindi"}, - {1038 , /* 0x040e */ "Hungarian"}, - {1039 , /* 0x040f */ "Icelandic"}, - {1057 , /* 0x0421 */ "Indonesian"}, - {1040 , /* 0x0410 */ "Italian (Standard)"}, - {2064 , /* 0x0810 */ "Italian (Switzerland)"}, - {1041 , /* 0x0411 */ "Japanese"}, - {1099 , /* 0x044b */ "Kannada"}, - {2144 , /* 0x0860 */ "Kashmiri (India)"}, - {1087 , /* 0x043f */ "Kazakh"}, - {1111 , /* 0x0457 */ "Konkani"}, - {1042 , /* 0x0412 */ "Korean"}, - {2066 , /* 0x0812 */ "Korean (Johab)"}, - {1062 , /* 0x0426 */ "Latvian"}, - {1063 , /* 0x0427 */ "Lithuanian"}, - {2087 , /* 0x0827 */ "Lithuanian (Classic)"}, - {1071 , /* 0x042f */ "Macedonia, Former Yugoslav Republic of"}, - {1086 , /* 0x043e */ "Malay (Malaysian)"}, - {2110 , /* 0x083e */ "Malay (Brunei Darussalam)"}, - {1100 , /* 0x044c */ "Malayalam"}, - {1112 , /* 0x0458 */ "Manipuri"}, - {1102 , /* 0x044e */ "Marathi"}, - {2145 , /* 0x0861 */ "Nepali (India)"}, - {1044 , /* 0x0414 */ "Norwegian (Bokmal)"}, - {2068 , /* 0x0814 */ "Norwegian (Nynorsk)"}, - {1096 , /* 0x0448 */ "Odia"}, - {1045 , /* 0x0415 */ "Polish"}, - {1046 , /* 0x0416 */ "Portuguese (Brazil)"}, - {2070 , /* 0x0816 */ "Portuguese (Portugal)"}, - {1094 , /* 0x0446 */ "Punjabi"}, - {1048 , /* 0x0418 */ "Romanian"}, - {1049 , /* 0x0419 */ "Russian"}, - {1103 , /* 0x044f */ "Sanskrit"}, - {3098 , /* 0x0c1a */ "Serbian (Cyrillic)"}, - {2074 , /* 0x081a */ "Serbian (Latin)"}, - {1113 , /* 0x0459 */ "Sindhi"}, - {1051 , /* 0x041b */ "Slovak"}, - {1060 , /* 0x0424 */ "Slovenian"}, - {1034 , /* 0x040a */ "Spanish (Traditional Sort)"}, - {2058 , /* 0x080a */ "Spanish (Mexican)"}, - {3082 , /* 0x0c0a */ "Spanish (Modern Sort)"}, - {4106 , /* 0x100a */ "Spanish (Guatemala)"}, - {5130 , /* 0x140a */ "Spanish (Costa Rica)"}, - {6154 , /* 0x180a */ "Spanish (Panama)"}, - {7178 , /* 0x1c0a */ "Spanish (Dominican Republic)"}, - {8202 , /* 0x200a */ "Spanish (Venezuela)"}, - {9226 , /* 0x240a */ "Spanish (Colombia)"}, - {10250 , /* 0x280a */ "Spanish (Peru)"}, - {11274 , /* 0x2c0a */ "Spanish (Argentina)"}, - {12298 , /* 0x300a */ "Spanish (Ecuador)"}, - {13322 , /* 0x340a */ "Spanish (Chile)"}, - {14346 , /* 0x380a */ "Spanish (Uruguay)"}, - {15370 , /* 0x3c0a */ "Spanish (Paraguay)"}, - {16394 , /* 0x400a */ "Spanish (Bolivia)"}, - {17418 , /* 0x440a */ "Spanish (El Salvador)"}, - {18442 , /* 0x480a */ "Spanish (Honduras)"}, - {19466 , /* 0x4c0a */ "Spanish (Nicaragua)"}, - {20490 , /* 0x500a */ "Spanish (Puerto Rico)"}, - {1072 , /* 0x0430 */ "Sutu"}, - {1089 , /* 0x0441 */ "Swahili (Kenya)"}, - {1053 , /* 0x041d */ "Swedish"}, - {2077 , /* 0x081d */ "Swedish (Finland)"}, - {1097 , /* 0x0449 */ "Tamil"}, - {1092 , /* 0x0444 */ "Tatar (Tatarstan)"}, - {1098 , /* 0x044a */ "Telugu"}, - {1054 , /* 0x041e */ "Thai"}, - {1055 , /* 0x041f */ "Turkish"}, - {1058 , /* 0x0422 */ "Ukrainian"}, - {1056 , /* 0x0420 */ "Urdu (Pakistan)"}, - {2080 , /* 0x0820 */ "Urdu (India)"}, - {1091 , /* 0x0443 */ "Uzbek (Latin)"}, - {2115 , /* 0x0843 */ "Uzbek (Cyrillic)"}, - {1066 , /* 0x042a */ "Vietnamese"}, - {1279 , /* 0x04ff */ "HID (Usage Data Descriptor)"}, - {61695 , /* 0xf0ff */ "HID (Vendor Defined 1)"}, - {62719 , /* 0xf4ff */ "HID (Vendor Defined 2)"}, - {63743 , /* 0xf8ff */ "HID (Vendor Defined 3)"}, - {64767 , /* 0xfcff */ "HID (Vendor Defined 4)"}, - { 0x00, "End"} -}; - -#endif /* __LANGIDLIST_H__ */ - diff --git a/tests/projects/winsdk/usbview/monitor.ico b/tests/projects/winsdk/usbview/monitor.ico deleted file mode 100644 index e015959f6..000000000 Binary files a/tests/projects/winsdk/usbview/monitor.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/port.ico b/tests/projects/winsdk/usbview/port.ico deleted file mode 100644 index 98c8aa04c..000000000 Binary files a/tests/projects/winsdk/usbview/port.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/resource.h b/tests/projects/winsdk/usbview/resource.h deleted file mode 100644 index 921fa6a30..000000000 --- a/tests/projects/winsdk/usbview/resource.h +++ /dev/null @@ -1,51 +0,0 @@ -/*++ -Copyright (c) 1998-2008 Microsoft Corporation, All Rights Reserved. ---*/ - -#define IDD_MAINDIALOG 101 -#define IDR_MENU 102 -#define IDD_ABOUT 103 -#define IDI_ICON 104 -#define IDC_SPLIT 105 -#define IDACCEL 106 - -#define IDI_BADICON 107 -#define IDI_COMPUTER 108 -#define IDI_HUB 109 -#define IDI_NODEVICE 110 -#define IDI_SSICON 111 -#define IDI_NOSSDEVICE 112 - -#define IDC_TREE 1000 -#define IDC_EDIT 1001 -#define IDC_STATUS 1002 - -#define IDS_STRINGBASE 2000 -#define IDS_STANDARD_FONT 2001 -#define IDS_STANDARD_FONT_HEIGHT 2002 -#define IDS_STANDARD_FONT_WIDTH 2003 -#define IDS_USBVIEW_USAGE 2004 -#define IDS_USBVIEW_PRESSKEY 2005 -#define IDS_USBVIEW_INVALIDARG 2006 -#define IDS_USBVIEW_FILE_EXISTS_TXT 2007 -#define IDS_USBVIEW_FILE_EXISTS_XML 2008 -#define IDS_USBVIEW_INTERNAL_ERROR 2009 -#define IDS_USBVIEW_SAVED_TO 2010 -#define IDS_USBVIEW_INVALID_FILENAME 2011 - -#define IDC_VERSION 3000 -#define IDC_UVCVERSION 3001 - -#define ID_EXIT 40001 -#define ID_REFRESH 40002 -#define ID_AUTO_REFRESH 40003 -#define ID_CONFIG_DESCRIPTORS 40004 -#define ID_ABOUT 40005 -#define ID_ANNOTATION 40007 -#define ID_UNUSED 40008 -#define ID_LOG_DEBUG 40009 -#define ID_SAVE 40010 -#define ID_SAVEALL 40011 -#define ID_SAVEXML 40012 -#define IDC_STATIC 0xFFFFFFFF - diff --git a/tests/projects/winsdk/usbview/split.cur b/tests/projects/winsdk/usbview/split.cur deleted file mode 100644 index 41d65e3c5..000000000 Binary files a/tests/projects/winsdk/usbview/split.cur and /dev/null differ diff --git a/tests/projects/winsdk/usbview/ssport.ico b/tests/projects/winsdk/usbview/ssport.ico deleted file mode 100644 index e0f712ae6..000000000 Binary files a/tests/projects/winsdk/usbview/ssport.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/ssusb.ico b/tests/projects/winsdk/usbview/ssusb.ico deleted file mode 100644 index 71f0ebe1d..000000000 Binary files a/tests/projects/winsdk/usbview/ssusb.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/usb.ico b/tests/projects/winsdk/usbview/usb.ico deleted file mode 100644 index e615d3e24..000000000 Binary files a/tests/projects/winsdk/usbview/usb.ico and /dev/null differ diff --git a/tests/projects/winsdk/usbview/usbdesc.h b/tests/projects/winsdk/usbview/usbdesc.h deleted file mode 100644 index 8b78a3c39..000000000 --- a/tests/projects/winsdk/usbview/usbdesc.h +++ /dev/null @@ -1,394 +0,0 @@ -/*++ - -Copyright (c) 1997-2008 Microsoft Corporation - -Module Name: - - USBDESC.H - -Abstract: - - This is a header file for USB descriptors which are not yet in - a standard system header file. - -Environment: - - user mode - -Revision History: - - 03-06-1998 : created - 03-28-2003 : minor changes to support UVC and USB200 - ---*/ - -#pragma pack(push, 1) - -/***************************************************************************** - D E F I N E S -*****************************************************************************/ - -// -//Device Descriptor bDeviceClass values -// -#define USB_INTERFACE_CLASS_DEVICE 0x00 -#define USB_COMMUNICATION_DEVICE 0x02 -#define USB_HUB_DEVICE 0x09 -#define USB_DEVICE_CLASS_BILLBOARD 0x11 -#define USB_DIAGNOSTIC_DEVICE 0xDC -#define USB_WIRELESS_CONTROLLER_DEVICE 0xE0 -#define USB_MISCELLANEOUS_DEVICE 0xEF -#define USB_VENDOR_SPECIFIC_DEVICE 0xFF - -// -//Device Descriptor bDeviceSubClass values -// -#define USB_COMMON_SUB_CLASS 0x02 - -// -//Interface Descriptor bInterfaceClass values: -// -//#define USB_AUDIO_INTERFACE 0x01 -//#define USB_CDC_CONTROL_INTERFACE 0x02 -//#define USB_HID_INTERFACE 0x03 -//#define USB_PHYSICAL_INTERFACE 0x05 -//#define USB_IMAGE_INTERFACE 0x06 -//#define USB_PRINTER_INTERFACE 0x07 -//#define USB_MASS_STORAGE_INTERFACE 0x08 -//#define USB_HUB_INTERFACE 0x09 -#define USB_CDC_DATA_INTERFACE 0x0A -#define USB_CHIP_SMART_CARD_INTERFACE 0x0B -#define USB_CONTENT_SECURITY_INTERFACE 0x0D -#define USB_DIAGNOSTIC_DEVICE_INTERFACE 0xDC -#define USB_WIRELESS_CONTROLLER_INTERFACE 0xE0 -#define USB_APPLICATION_SPECIFIC_INTERFACE 0xFE -//#define USB_VENDOR_SPECIFIC_INTERFACE 0xFF -#define USB_HID_DESCRIPTOR_TYPE 0x21 - -// -//IAD protocol values -// -#define USB_IAD_PROTOCOL 0x01 - -// -//Device class specific values -// -#define BILLBOARD_MAX_NUM_ALT_MODE 0x34 - -// -//USB 2.0 Specification Changes - New Descriptors -// -#define USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE 0x07 -#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 0x08 -#define USB_OTG_DESCRIPTOR_TYPE 0x09 -#define USB_DEBUG_DESCRIPTOR_TYPE 0x0A -#define USB_IAD_DESCRIPTOR_TYPE 0x0B - -// -// USB Device Class Definition for Audio Devices -// Appendix A. Audio Device Class Codes -// - -// A.2 Audio Interface Subclass Codes -// -#define USB_AUDIO_SUBCLASS_UNDEFINED 0x00 -#define USB_AUDIO_SUBCLASS_AUDIOCONTROL 0x01 -#define USB_AUDIO_SUBCLASS_AUDIOSTREAMING 0x02 -#define USB_AUDIO_SUBCLASS_MIDISTREAMING 0x03 - -// A.4 Audio Class-Specific Descriptor Types -// -#define USB_AUDIO_CS_UNDEFINED 0x20 -#define USB_AUDIO_CS_DEVICE 0x21 -#define USB_AUDIO_CS_CONFIGURATION 0x22 -#define USB_AUDIO_CS_STRING 0x23 -#define USB_AUDIO_CS_INTERFACE 0x24 -#define USB_AUDIO_CS_ENDPOINT 0x25 - -// A.5 Audio Class-Specific AC (Audio Control) Interface Descriptor Subtypes -// -#define USB_AUDIO_AC_UNDEFINED 0x00 -#define USB_AUDIO_AC_HEADER 0x01 -#define USB_AUDIO_AC_INPUT_TERMINAL 0x02 -#define USB_AUDIO_AC_OUTPUT_TERMINAL 0x03 -#define USB_AUDIO_AC_MIXER_UNIT 0x04 -#define USB_AUDIO_AC_SELECTOR_UNIT 0x05 -#define USB_AUDIO_AC_FEATURE_UNIT 0x06 -#define USB_AUDIO_AC_PROCESSING_UNIT 0x07 -#define USB_AUDIO_AC_EXTENSION_UNIT 0x08 - -// A.6 Audio Class-Specific AS (Audio Streaming) Interface Descriptor Subtypes -// -#define USB_AUDIO_AS_UNDEFINED 0x00 -#define USB_AUDIO_AS_GENERAL 0x01 -#define USB_AUDIO_AS_FORMAT_TYPE 0x02 -#define USB_AUDIO_AS_FORMAT_SPECIFIC 0x03 - -// A.7 Processing Unit Process Types -// -#define USB_AUDIO_PROCESS_UNDEFINED 0x00 -#define USB_AUDIO_PROCESS_UPDOWNMIX 0x01 -#define USB_AUDIO_PROCESS_DOLBYPROLOGIC 0x02 -#define USB_AUDIO_PROCESS_3DSTEREOEXTENDER 0x03 -#define USB_AUDIO_PROCESS_REVERBERATION 0x04 -#define USB_AUDIO_PROCESS_CHORUS 0x05 -#define USB_AUDIO_PROCESS_DYNRANGECOMP 0x06 - - -/***************************************************************************** - T Y P E D E F S -*****************************************************************************/ - -// HID Class HID Descriptor -// -typedef struct _USB_HID_DESCRIPTOR -{ - UCHAR bLength; - UCHAR bDescriptorType; - USHORT bcdHID; - UCHAR bCountryCode; - UCHAR bNumDescriptors; - struct - { - UCHAR bDescriptorType; - USHORT wDescriptorLength; - } OptionalDescriptors[1]; -} USB_HID_DESCRIPTOR, *PUSB_HID_DESCRIPTOR; - - -// OTG Descriptor -// -typedef struct _USB_OTG_DESCRIPTOR -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bmAttributes; -} USB_OTG_DESCRIPTOR, *PUSB_OTG_DESCRIPTOR; - -// IAD Descriptor -// -typedef struct _USB_IAD_DESCRIPTOR -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bFirstInterface; - UCHAR bInterfaceCount; - UCHAR bFunctionClass; - UCHAR bFunctionSubClass; - UCHAR bFunctionProtocol; - UCHAR iFunction; -} USB_IAD_DESCRIPTOR, *PUSB_IAD_DESCRIPTOR; - - -// Common Class Endpoint Descriptor -// -typedef struct _USB_ENDPOINT_DESCRIPTOR2 { - UCHAR bLength; // offset 0, size 1 - UCHAR bDescriptorType; // offset 1, size 1 - UCHAR bEndpointAddress; // offset 2, size 1 - UCHAR bmAttributes; // offset 3, size 1 - USHORT wMaxPacketSize; // offset 4, size 2 - USHORT wInterval; // offset 6, size 2 - UCHAR bSyncAddress; // offset 8, size 1 -} USB_ENDPOINT_DESCRIPTOR2, *PUSB_ENDPOINT_DESCRIPTOR2; - -// Common Class Interface Descriptor -// -typedef struct _USB_INTERFACE_DESCRIPTOR2 { - UCHAR bLength; // offset 0, size 1 - UCHAR bDescriptorType; // offset 1, size 1 - UCHAR bInterfaceNumber; // offset 2, size 1 - UCHAR bAlternateSetting; // offset 3, size 1 - UCHAR bNumEndpoints; // offset 4, size 1 - UCHAR bInterfaceClass; // offset 5, size 1 - UCHAR bInterfaceSubClass; // offset 6, size 1 - UCHAR bInterfaceProtocol; // offset 7, size 1 - UCHAR iInterface; // offset 8, size 1 - USHORT wNumClasses; // offset 9, size 2 -} USB_INTERFACE_DESCRIPTOR2, *PUSB_INTERFACE_DESCRIPTOR2; - - -// -// USB Device Class Definition for Audio Devices -// - -typedef struct _USB_AUDIO_COMMON_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; -} USB_AUDIO_COMMON_DESCRIPTOR, -*PUSB_AUDIO_COMMON_DESCRIPTOR; - -// 4.3.2 Class-Specific AC (Audio Control) Interface Descriptor -// -typedef struct _USB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - USHORT bcdADC; - USHORT wTotalLength; - UCHAR bInCollection; - UCHAR baInterfaceNr[1]; -} USB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR, -*PUSB_AUDIO_AC_INTERFACE_HEADER_DESCRIPTOR; - -// 4.3.2.1 Input Terminal Descriptor -// -typedef struct _USB_AUDIO_INPUT_TERMINAL_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR bNrChannels; - USHORT wChannelConfig; - UCHAR iChannelNames; - UCHAR iTerminal; -} USB_AUDIO_INPUT_TERMINAL_DESCRIPTOR, -*PUSB_AUDIO_INPUT_TERMINAL_DESCRIPTOR; - -// 4.3.2.2 Output Terminal Descriptor -// -typedef struct _USB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR bSourceID; - UCHAR iTerminal; -} USB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR, -*PUSB_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR; - -// 4.3.2.3 Mixer Unit Descriptor -// -typedef struct _USB_AUDIO_MIXER_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - UCHAR bNrInPins; - UCHAR baSourceID[1]; -} USB_AUDIO_MIXER_UNIT_DESCRIPTOR, -*PUSB_AUDIO_MIXER_UNIT_DESCRIPTOR; - -// 4.3.2.4 Selector Unit Descriptor -// -typedef struct _USB_AUDIO_SELECTOR_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - UCHAR bNrInPins; - UCHAR baSourceID[1]; -} USB_AUDIO_SELECTOR_UNIT_DESCRIPTOR, -*PUSB_AUDIO_SELECTOR_UNIT_DESCRIPTOR; - -// 4.3.2.5 Feature Unit Descriptor -// -typedef struct _USB_AUDIO_FEATURE_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - UCHAR bSourceID; - UCHAR bControlSize; - UCHAR bmaControls[1]; -} USB_AUDIO_FEATURE_UNIT_DESCRIPTOR, -*PUSB_AUDIO_FEATURE_UNIT_DESCRIPTOR; - -// 4.3.2.6 Processing Unit Descriptor -// -typedef struct _USB_AUDIO_PROCESSING_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - USHORT wProcessType; - UCHAR bNrInPins; - UCHAR baSourceID[1]; -} USB_AUDIO_PROCESSING_UNIT_DESCRIPTOR, -*PUSB_AUDIO_PROCESSING_UNIT_DESCRIPTOR; - -// 4.3.2.7 Extension Unit Descriptor -// -typedef struct _USB_AUDIO_EXTENSION_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - USHORT wExtensionCode; - UCHAR bNrInPins; - UCHAR baSourceID[1]; -} USB_AUDIO_EXTENSION_UNIT_DESCRIPTOR, -*PUSB_AUDIO_EXTENSION_UNIT_DESCRIPTOR; - -// 4.5.2 Class-Specific AS Interface Descriptor -// -typedef struct _USB_AUDIO_GENERAL_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalLink; - UCHAR bDelay; - USHORT wFormatTag; -} USB_AUDIO_GENERAL_DESCRIPTOR, -*PUSB_AUDIO_GENERAL_DESCRIPTOR; - -// 4.6.1.2 Class-Specific AS Endpoint Descriptor -// -typedef struct _USB_AUDIO_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bmAttributes; - UCHAR bLockDelayUnits; - USHORT wLockDelay; -} USB_AUDIO_ENDPOINT_DESCRIPTOR, -*PUSB_AUDIO_ENDPOINT_DESCRIPTOR; - -// -// USB Device Class Definition for Audio Data Formats -// - -typedef struct _USB_AUDIO_COMMON_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatType; -} USB_AUDIO_COMMON_FORMAT_DESCRIPTOR, -*PUSB_AUDIO_COMMON_FORMAT_DESCRIPTOR; - - -// 2.1.5 Type I Format Type Descriptor -// 2.3.1 Type III Format Type Descriptor -// -typedef struct _USB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatType; - UCHAR bNrChannels; - UCHAR bSubframeSize; - UCHAR bBitResolution; - UCHAR bSamFreqType; -} USB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR, -*PUSB_AUDIO_TYPE_I_OR_III_FORMAT_DESCRIPTOR; - - -// 2.2.6 Type II Format Type Descriptor -// -typedef struct _USB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatType; - USHORT wMaxBitRate; - USHORT wSamplesPerFrame; - UCHAR bSamFreqType; -} USB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR, -*PUSB_AUDIO_TYPE_II_FORMAT_DESCRIPTOR; - -#pragma pack(pop) diff --git a/tests/projects/winsdk/usbview/usbschema.hpp b/tests/projects/winsdk/usbview/usbschema.hpp deleted file mode 100644 index 1aac6d000..000000000 --- a/tests/projects/winsdk/usbview/usbschema.hpp +++ /dev/null @@ -1,6119 +0,0 @@ -// -// This file is auto-generated from XSD using the command: -// xsd.exe /language:CPP /c /order /namespace:Microsoft.Kits.Samples.Usb -// - -#pragma once - -#using -#using -#using - -using namespace System::Security::Permissions; -// -// This source code was auto-generated by xsd, Version=4.0.30319.0. -// -namespace Microsoft { - namespace Kits { - namespace Samples { - namespace Usb { - using namespace System::Xml::Serialization; - using namespace System; - ref class UvcViewAll; - ref class UvcViewType; - ref class MachineInfoType; - ref class NoDeviceType; - ref class PortConnectorType; - ref class UsbPortPropertiesType; - ref class NodeConnectionInfoExV2Type; - ref class UsbBillboardSVIDType; - ref class UsbBillboardCapabilityDescriptorType; - ref class UsbDispContIdCapExtDescriptorType; - ref class UsbUsb20ExtensionDescriptorType; - ref class UsbSuperSpeedExtensionDescriptorType; - ref class UsbBosDescriptorType; - ref class UsbDeviceUnknownDescriptorType; - ref class UsbDeviceIADDescriptorType; - ref class UsbDeviceClassType; - ref class UsbDeviceOTGDescriptorType; - ref class UsbDeviceHidOptionalDescriptorsType; - ref class UsbDeviceHidDescriptorType; - ref class UsbDeviceInterfaceDescriptorType; - ref class UsbDeviceQualifierDescriptorType; - ref class UsbConfigurationDescriptorType; - ref class UsbDeviceConfigurationType; - ref class EndpointDescriptorType; - ref class UsbDeviceType; - ref class NodeConnectionInfoExType; - ref class NodeConnectionInfoExStructType; - ref class UsbDeviceDescriptorType; - ref class UsbPipeInfoType; - ref class UsbDeviceClassDetailsType; - ref class ExternalHubType; - ref class HubNodeInformationType; - ref class HubInformationType; - ref class HubDescriptorType; - ref class HubCharacteristicsType; - ref class HubInformationExType; - ref class Hub30DescriptorType; - ref class HubCapabilitiesExType; - ref class RootHubType; - ref class UsbHCPowerStateType; - ref class UsbHCPowerStateMappingType; - ref class UsbHCDeviceInfoType; - ref class HostControllerType; - - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public enum class UsbConnectionSpeedType { - - /// - Low, - - /// - Full, - - /// - High, - - /// - Super, - - /// - Unknown, - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public enum class UsbConnectionStatusType { - - /// - NoDeviceConnected, - - /// - DeviceConnected, - - /// - DeviceFailedEnumeration, - - /// - DeviceGeneralFailure, - - /// - DeviceCausedOvercurrent, - - /// - DeviceNotEnoughPower, - - /// - DeviceNotEnoughBandwidth, - - /// - DeviceHubNestedTooDeeply, - - /// - DeviceInLegacyHub, - - /// - DeviceEnumerating, - - /// - DeviceReset, - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public enum class DevicePowerStateType { - - /// - PowerDeviceUnspecified, - - /// - PowerDeviceD0, - - /// - PowerDeviceD1, - - /// - PowerDeviceD2, - - /// - PowerDeviceD3, - - /// - PowerDeviceMaximum, - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public enum class HubNodeType { - - /// - UsbHub, - - /// - UsbMiParent, - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public enum class HubTypeType { - - /// - UnknownHubType, - - /// - UsbRootHub, - - /// - Usb20Hub, - - /// - Usb30Hub, - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(AnonymousType=true, Namespace=L"USB"), - System::Xml::Serialization::XmlRootAttribute(Namespace=L"USB", IsNullable=false)] - public ref class UvcViewAll { - - private: Microsoft::Kits::Samples::Usb::UvcViewType^ uvcViewField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::UvcViewType^ UvcView { - Microsoft::Kits::Samples::Usb::UvcViewType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UvcViewType^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UvcViewType { - - private: Microsoft::Kits::Samples::Usb::MachineInfoType^ machineInfoField; - - private: cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ usbTreeField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::MachineInfoType^ MachineInfo { - Microsoft::Kits::Samples::Usb::MachineInfoType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::MachineInfoType^ value); - } - - /// - public: [System::Xml::Serialization::XmlArrayAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1), - System::Xml::Serialization::XmlArrayItemAttribute(L"UsbController", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, IsNullable=false)] - property cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ UsbTree { - cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class MachineInfoType { - - private: System::Byte uvcMajorVersionField; - - private: System::Byte uvcMinorVersionField; - - private: System::Byte uvcMajorSpecVersionField; - - private: System::Byte uvcMinorSpecVersionField; - - private: System::DateTime collectionTimeField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::Byte UvcMajorVersion { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::Byte UvcMinorVersion { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::Byte UvcMajorSpecVersion { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::Byte UvcMinorSpecVersion { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::DateTime CollectionTime { - System::DateTime get(); - System::Void set(System::DateTime value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class NoDeviceType { - - private: Microsoft::Kits::Samples::Usb::PortConnectorType^ portConnectorField; - - private: System::String^ usbPortNumberField; - - private: System::String^ nameField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::PortConnectorType^ PortConnector { - Microsoft::Kits::Samples::Usb::PortConnectorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ UsbPortNumber { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ Name { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class PortConnectorType { - - private: System::UInt64 connectionIndexField; - - private: System::UInt64 actualLengthField; - - private: Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ usbPortPropertiesField; - - private: System::UInt16 companionIndexField; - - private: System::UInt16 companionPortNumberField; - - private: System::String^ companionHubSymbolicLinkNameField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::UInt64 ConnectionIndex { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::UInt64 ActualLength { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ UsbPortProperties { - Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::UInt16 CompanionIndex { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::UInt16 CompanionPortNumber { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::String^ CompanionHubSymbolicLinkName { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbPortPropertiesType { - - private: System::Boolean portIsUserConnectableField; - - private: System::Boolean portIsDebugCapableField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::Boolean PortIsUserConnectable { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::Boolean PortIsDebugCapable { - System::Boolean get(); - System::Void set(System::Boolean value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class NodeConnectionInfoExV2Type { - - private: System::UInt64 connectionIndexField; - - private: System::UInt64 lengthField; - - private: System::Boolean usb110SupportedField; - - private: System::Boolean usb200SupportedField; - - private: System::Boolean usb300SupportedField; - - private: System::Boolean deviceIsOperatingAtSuperSpeedOrHigherField; - - private: System::Boolean deviceIsSuperSpeedCapableOrHigherField; - - private: System::Boolean deviceIsOperatingAtSuperSpeedPlusOrHigherField; - - private: System::Boolean deviceIsSuperSpeedPlusCapableOrHigherField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::UInt64 ConnectionIndex { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::UInt64 Length { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::Boolean Usb110Supported { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::Boolean Usb200Supported { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::Boolean Usb300Supported { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::Boolean DeviceIsOperatingAtSuperSpeedOrHigher { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::Boolean DeviceIsSuperSpeedCapableOrHigher { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] - property System::Boolean DeviceIsOperatingAtSuperSpeedPlusOrHigher { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] - property System::Boolean DeviceIsSuperSpeedPlusCapableOrHigher { - System::Boolean get(); - System::Void set(System::Boolean value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbBillboardSVIDType { - - private: System::String^ descriptionField; - - private: System::String^ alternateModeStringField; - - private: System::UInt16 wSVIDField; - - private: System::Byte bAlternateModeField; - - private: System::Byte iAlternateModeStringField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ Description { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ AlternateModeString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WSVID { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BAlternateMode { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IAlternateModeString { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbBillboardCapabilityDescriptorType { - - private: System::String^ vConnPowerField; - - private: System::String^ billboardDescriptorErrorsField; - - private: System::String^ addtionalInfoURLField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ usbBillboardSVIDField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bDevCapabilityTypeField; - - private: System::Byte iAddtionalInfoURLField; - - private: System::Byte bNumberOfAlternateModesField; - - private: System::Byte bPreferredAlternateModeField; - - private: System::Byte calculatedBLengthField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ VConnPower { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ BillboardDescriptorErrors { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ AddtionalInfoURL { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbBillboardSVID", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=3)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ UsbBillboardSVID { - cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDevCapabilityType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IAddtionalInfoURL { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BNumberOfAlternateModes { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BPreferredAlternateMode { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte CalculatedBLength { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDispContIdCapExtDescriptorType { - - private: System::String^ reservedBitErrorField; - - private: System::String^ containerIdStrField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bReservedField; - - private: System::Byte bDevCapabilityTypeField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ ReservedBitError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ ContainerIdStr { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BReserved { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDevCapabilityType { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbUsb20ExtensionDescriptorType { - - private: System::String^ reservedBitErrorField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bDevCapabilityTypeField; - - private: System::UInt64 bmAttributesField; - - private: System::Boolean supportsLinkPowerManagementField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ ReservedBitError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDevCapabilityType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt64 BmAttributes { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean SupportsLinkPowerManagement { - System::Boolean get(); - System::Void set(System::Boolean value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbSuperSpeedExtensionDescriptorType { - - private: System::String^ reservedAttributesBitErrorField; - - private: System::String^ reservedSpeedBitErrorField; - - private: System::String^ reservedSpeedErrorField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bDevCapabilityTypeField; - - private: System::UInt64 bmAttributesField; - - private: System::Boolean latencyToleranceMsgCapableField; - - private: System::Byte bFunctionalitySupportField; - - private: System::Byte bU1DevExitLatField; - - private: System::UInt16 wSpeedsSupportedField; - - private: System::UInt16 wU2DevExitLatField; - - private: System::Boolean supportsLowSpeedField; - - private: System::Boolean supportsFullSpeedField; - - private: System::Boolean supportsHighSpeedField; - - private: System::Boolean supportsSuperSpeedField; - - private: System::String^ lowestSpeedField; - - private: System::String^ u1DevExitLatencyStringField; - - private: System::String^ u2DevExitLatencyStringField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ ReservedAttributesBitError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ ReservedSpeedBitError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ ReservedSpeedError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDevCapabilityType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt64 BmAttributes { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean LatencyToleranceMsgCapable { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BFunctionalitySupport { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BU1DevExitLat { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WSpeedsSupported { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WU2DevExitLat { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean SupportsLowSpeed { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean SupportsFullSpeed { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean SupportsHighSpeed { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean SupportsSuperSpeed { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ LowestSpeed { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ U1DevExitLatencyString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ U2DevExitLatencyString { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbBosDescriptorType { - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ unknownDescriptorField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ usbSuperSpeedExtensionDescriptorField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ usbUsb20ExtensionDescriptorField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ usbDispContIdCapExtDescriptorField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ usbBillboardCapabilityDescriptorField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::UInt16 wTotalLengthField; - - private: System::Byte bNumDeviceCapsField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UnknownDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=0)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ UnknownDescriptor { - cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbSuperSpeedExtensionDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=1)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ UsbSuperSpeedExtensionDescriptor { - cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbUsb20ExtensionDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=2)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ UsbUsb20ExtensionDescriptor { - cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbDispContIdCapExtDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=3)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ UsbDispContIdCapExtDescriptor { - cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbBillboardCapabilityDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=4)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ UsbBillboardCapabilityDescriptor { - cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WTotalLength { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BNumDeviceCaps { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceUnknownDescriptorType { - - private: System::String^ unknownDescriptorField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ UnknownDescriptor { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceIADDescriptorType { - - private: Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ functionDetailsField; - - private: System::String^ interfaceErrorField; - - private: System::String^ functionClassErrorField; - - private: System::String^ protocolField; - - private: System::String^ stringDescField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bFirstInterfaceField; - - private: System::Byte bInterfaceCountField; - - private: System::Byte bFunctionClassField; - - private: System::Byte bFunctionSubclassField; - - private: System::Byte bFunctionProtocolField; - - private: System::Byte iFunctionField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ FunctionDetails { - Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ InterfaceError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ FunctionClassError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::String^ Protocol { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::String^ StringDesc { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BFirstInterface { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BInterfaceCount { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BFunctionClass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BFunctionSubclass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BFunctionProtocol { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IFunction { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceClassType { - - private: System::String^ deviceClassField; - - private: System::String^ deviceSubclassField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ DeviceClass { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ DeviceSubclass { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceOTGDescriptorType { - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bmAttributesField; - - private: System::String^ attributesStringField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BmAttributes { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ AttributesString { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceHidOptionalDescriptorsType { - - private: System::Byte bDescriptorTypeField; - - private: System::UInt16 wDescriptorLengthField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WDescriptorLength { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceHidDescriptorType { - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ optionalDescriptorField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::UInt16 bcdHIDField; - - private: System::Byte bCountryCodeField; - - private: System::Byte bNumDescriptorsField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"OptionalDescriptor", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=0)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ OptionalDescriptor { - cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 BcdHID { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BCountryCode { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BNumDescriptors { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceInterfaceDescriptorType { - - private: Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ interfaceDetailsField; - - private: System::String^ protocolErrorField; - - private: System::String^ stringDescField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::Byte bInterfaceNumberField; - - private: System::Byte bAlternateSettingField; - - private: System::Byte bNumEndpointsField; - - private: System::Byte bInterfaceClassField; - - private: System::Byte bInterfaceSubclassField; - - private: System::Byte bInterfaceProtocolField; - - private: System::Byte iInterfaceField; - - private: System::UInt16 wNumClassesField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ InterfaceDetails { - Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ ProtocolError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ StringDesc { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BInterfaceNumber { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BAlternateSetting { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BNumEndpoints { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BInterfaceClass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BInterfaceSubclass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BInterfaceProtocol { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IInterface { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WNumClasses { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceQualifierDescriptorType { - - private: System::String^ deviceClassField; - - private: System::Byte maxPacketSizeInBytesField; - - private: System::Boolean maxPacketSizeInBytesFieldSpecified; - - private: System::String^ deviceClassErrorField; - - private: System::String^ deviceSubclassErrorField; - - private: System::String^ deviceProtocolErrorField; - - private: System::String^ deviceNumConfigErrorField; - - private: System::String^ reservedErrorField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::UInt16 bcdUSBField; - - private: System::Byte bDeviceClassField; - - private: System::Byte bDeviceSubclassField; - - private: System::Byte bDeviceProtocolField; - - private: System::Byte bMaxPacketSize0Field; - - private: System::Byte numConfigurationsField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ DeviceClass { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::Byte MaxPacketSizeInBytes { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlIgnoreAttribute] - property System::Boolean MaxPacketSizeInBytesSpecified { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ DeviceClassError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::String^ DeviceSubclassError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::String^ DeviceProtocolError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::String^ DeviceNumConfigError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::String^ ReservedError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 BcdUSB { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDeviceClass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDeviceSubclass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDeviceProtocol { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BMaxPacketSize0 { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte NumConfigurations { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbConfigurationDescriptorType { - - private: System::String^ configDescErrorField; - - private: System::String^ confValueErrorField; - - private: System::String^ confStringDescField; - - private: System::String^ attributesStrField; - - private: System::String^ maxCurrentField; - - private: System::Byte bLengthField; - - private: System::Byte bDescriptorTypeField; - - private: System::UInt16 wTotalLengthField; - - private: System::Byte bNumInterfacesField; - - private: System::Byte bConfigurationValueField; - - private: System::Byte iConfigurationField; - - private: System::Byte bmAttributesField; - - private: System::Byte maxPowerField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ ConfigDescError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ ConfValueError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ ConfStringDesc { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::String^ AttributesStr { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::String^ MaxCurrent { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BDescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WTotalLength { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BNumInterfaces { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BConfigurationValue { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IConfiguration { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte BmAttributes { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte MaxPower { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceConfigurationType { - - private: System::String^ deviceQualifierErrorField; - - private: System::String^ speedConfigurationErrorField; - - private: System::String^ deviceConfigurationErrorField; - - private: System::String^ interfaceErrorField; - - private: System::String^ preReleaseErrorField; - - private: System::String^ endpointErrorField; - - private: System::String^ hidErrorField; - - private: System::String^ otgErrorField; - - private: System::String^ iadErrorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ deviceDetailsField; - - private: Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ configurationDescriptorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ deviceQualifierDescriptorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ interfaceDescriptorField; - - private: Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ endpointDescriptorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ hidDescriptorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ otgDescriptorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ iadDescriptorField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ unknownDescriptorField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ DeviceQualifierError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ SpeedConfigurationError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ DeviceConfigurationError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::String^ InterfaceError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::String^ PreReleaseError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::String^ EndpointError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::String^ HidError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] - property System::String^ OtgError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] - property System::String^ IadError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] - property Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ DeviceDetails { - Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] - property Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ ConfigurationDescriptor { - Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] - property Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ DeviceQualifierDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=12)] - property Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ InterfaceDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=13)] - property Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ EndpointDescriptor { - Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=14)] - property Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ HidDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=15)] - property Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ OtgDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=16)] - property Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ IadDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=17)] - property Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ UnknownDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class EndpointDescriptorType { - - private: System::Byte lengthField; - - private: System::Byte descriptorTypeField; - - private: System::Byte endpointAddressField; - - private: System::Byte attributesField; - - private: System::UInt16 maxPacketSizeField; - - private: System::Byte intervalField; - - private: System::UInt16 wIntervalField; - - private: System::Byte syncAddressField; - - private: System::String^ endpointDirectionField; - - private: System::Byte endpointIdField; - - private: System::String^ endpointTypeField; - - private: System::String^ endpointPacketInfoField; - - private: System::String^ endpointPacketSizeValidationField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte Length { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte EndpointAddress { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte Attributes { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 MaxPacketSize { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte Interval { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 WInterval { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte SyncAddress { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ EndpointDirection { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte EndpointId { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ EndpointType { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ EndpointPacketInfo { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ EndpointPacketSizeValidation { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceType { - - private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ connectionInfoField; - - private: Microsoft::Kits::Samples::Usb::PortConnectorType^ portConnectorField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ deviceConfigurationField; - - private: Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ bosDescriptorField; - - private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ connectionInfoV2Field; - - private: System::String^ usbPortNumberField; - - private: System::String^ serviceNameField; - - private: System::String^ hwIdField; - - private: System::String^ deviceIdField; - - private: System::String^ deviceNameField; - - private: System::String^ deviceClassField; - - private: System::String^ usbProtocolField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ ConnectionInfo { - Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property Microsoft::Kits::Samples::Usb::PortConnectorType^ PortConnector { - Microsoft::Kits::Samples::Usb::PortConnectorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"DeviceConfiguration", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=2)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ DeviceConfiguration { - cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ BosDescriptor { - Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ ConnectionInfoV2 { - Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ UsbPortNumber { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ ServiceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ HwId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceClass { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ UsbProtocol { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class NodeConnectionInfoExType { - - private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ connectionInfoStructField; - - private: System::String^ iProductStringDescEnField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ deviceClassDetailsField; - - private: System::Byte maxPacketSizeInBytesField; - - private: System::String^ vendorStringField; - - private: System::String^ manufacturerStringField; - - private: System::String^ productStringField; - - private: System::String^ langIdStringField; - - private: System::String^ serialStringField; - - private: System::String^ pipeInfoErrorField; - - private: System::String^ lengthErrorField; - - private: System::String^ deviceErrorField; - - private: System::String^ packetSizeErrorField; - - private: System::String^ configurationCountErrorField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ ConnectionInfoStruct { - Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ IProductStringDescEn { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ DeviceClassDetails { - Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::Byte MaxPacketSizeInBytes { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::String^ VendorString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::String^ ManufacturerString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::String^ ProductString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] - property System::String^ LangIdString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] - property System::String^ SerialString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] - property System::String^ PipeInfoError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] - property System::String^ LengthError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] - property System::String^ DeviceError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=12)] - property System::String^ PacketSizeError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=13)] - property System::String^ ConfigurationCountError { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class NodeConnectionInfoExStructType { - - private: System::UInt64 connectionIndexField; - - private: Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ deviceDescriptorField; - - private: System::Byte currentConfigurationValueField; - - private: System::Byte speedField; - - private: Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType speedStrField; - - private: System::Boolean deviceIsHubField; - - private: System::Byte deviceAddressField; - - private: System::UInt64 numOfOpenPipesField; - - private: Microsoft::Kits::Samples::Usb::UsbConnectionStatusType usbConnectionStatusField; - - private: Microsoft::Kits::Samples::Usb::DevicePowerStateType devicePowerStateField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ pipeField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::UInt64 ConnectionIndex { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ DeviceDescriptor { - Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::Byte CurrentConfigurationValue { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::Byte Speed { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType SpeedStr { - Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::Boolean DeviceIsHub { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::Byte DeviceAddress { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] - property System::UInt64 NumOfOpenPipes { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] - property Microsoft::Kits::Samples::Usb::UsbConnectionStatusType UsbConnectionStatus { - Microsoft::Kits::Samples::Usb::UsbConnectionStatusType get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbConnectionStatusType value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] - property Microsoft::Kits::Samples::Usb::DevicePowerStateType DevicePowerState { - Microsoft::Kits::Samples::Usb::DevicePowerStateType get(); - System::Void set(Microsoft::Kits::Samples::Usb::DevicePowerStateType value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"Pipe", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ Pipe { - cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceDescriptorType { - - private: System::Byte lengthField; - - private: System::Byte descriptorTypeField; - - private: System::UInt16 cdUSBField; - - private: System::Byte deviceClassField; - - private: System::Byte deviceSubclassField; - - private: System::Byte deviceProtocolField; - - private: System::Byte maxPacketSize0Field; - - private: System::UInt16 idVendorField; - - private: System::UInt16 idProductField; - - private: System::UInt16 cdDeviceField; - - private: System::Byte iManufacturerField; - - private: System::Byte iProductField; - - private: System::Byte iSerialNumberField; - - private: System::Byte numConfigurationsField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte Length { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 CdUSB { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DeviceClass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DeviceSubclass { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DeviceProtocol { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte MaxPacketSize0 { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 IdVendor { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 IdProduct { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 CdDevice { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IManufacturer { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte IProduct { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte ISerialNumber { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte NumConfigurations { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbPipeInfoType { - - private: Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ endpointDescriptorField; - - private: System::UInt64 scheduleOffsetField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ EndpointDescriptor { - Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::UInt64 ScheduleOffset { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbDeviceClassDetailsType { - - private: System::String^ deviceTypeField; - - private: System::String^ deviceTypeErrorField; - - private: System::String^ subclassTypeField; - - private: System::String^ subclassTypeErrorField; - - private: System::String^ deviceProtocolField; - - private: System::String^ deviceProtocolErrorField; - - private: System::UInt32 uvcVersionField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::String^ DeviceType { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ DeviceTypeError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ SubclassType { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::String^ SubclassTypeError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::String^ DeviceProtocol { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::String^ DeviceProtocolError { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::UInt32 UvcVersion { - System::UInt32 get(); - System::Void set(System::UInt32 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class ExternalHubType { - - private: Microsoft::Kits::Samples::Usb::HubNodeInformationType^ hubNodeInformationField; - - private: System::String^ hubNameField; - - private: Microsoft::Kits::Samples::Usb::HubInformationExType^ hubInformationExField; - - private: Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ hubCapabilityExField; - - private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ connectionInfoField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ usbDeviceField; - - private: cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ noDeviceField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ deviceConfigurationField; - - private: Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ bosDescriptorField; - - private: Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ connectionInfoV2Field; - - private: cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ externalHubField; - - private: Microsoft::Kits::Samples::Usb::PortConnectorType^ portConnectorField; - - private: System::String^ serviceNameField; - - private: System::String^ hwIdField; - - private: System::String^ deviceIdField; - - private: System::String^ deviceNameField; - - private: System::String^ deviceClassField; - - private: System::String^ usbProtocolField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::HubNodeInformationType^ HubNodeInformation { - Microsoft::Kits::Samples::Usb::HubNodeInformationType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ HubName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::HubInformationExType^ HubInformationEx { - Microsoft::Kits::Samples::Usb::HubInformationExType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ HubCapabilityEx { - Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ ConnectionInfo { - Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=5)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ UsbDevice { - cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"NoDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ NoDevice { - cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"DeviceConfiguration", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=7)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ DeviceConfiguration { - cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] - property Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ BosDescriptor { - Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] - property Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ ConnectionInfoV2 { - Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"ExternalHub", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=10)] - property cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ ExternalHub { - cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] - property Microsoft::Kits::Samples::Usb::PortConnectorType^ PortConnector { - Microsoft::Kits::Samples::Usb::PortConnectorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ ServiceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ HwId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceClass { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ UsbProtocol { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HubNodeInformationType { - - private: Microsoft::Kits::Samples::Usb::HubNodeType hubNodeField; - - private: Microsoft::Kits::Samples::Usb::HubInformationType^ hubInformationField; - - private: System::UInt64 miParentNumberOfInterfacesField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::HubNodeType HubNode { - Microsoft::Kits::Samples::Usb::HubNodeType get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubNodeType value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property Microsoft::Kits::Samples::Usb::HubInformationType^ HubInformation { - Microsoft::Kits::Samples::Usb::HubInformationType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubInformationType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::UInt64 MiParentNumberOfInterfaces { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HubInformationType { - - private: System::Boolean isRootHubField; - - private: System::Boolean isBusPoweredField; - - private: Microsoft::Kits::Samples::Usb::HubDescriptorType^ hubDescriptorField; - - private: Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ hubCharacteristicsField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::Boolean IsRootHub { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::Boolean IsBusPowered { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubDescriptor { - Microsoft::Kits::Samples::Usb::HubDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ HubCharacteristics { - Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HubDescriptorType { - - private: System::Byte descriptorLengthField; - - private: System::Byte descriptorTypeField; - - private: System::Byte numberOfPortsField; - - private: System::Byte powerOntoPowerGoodField; - - private: System::Byte hubControlCurrentField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DescriptorLength { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte NumberOfPorts { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte PowerOntoPowerGood { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte HubControlCurrent { - System::Byte get(); - System::Void set(System::Byte value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HubCharacteristicsType { - - private: System::UInt32 hubCharacteristicsValueField; - - private: System::String^ powerSwitchingField; - - private: System::Boolean compoundDeviceField; - - private: System::String^ overCurrentProtectionField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt32 HubCharacteristicsValue { - System::UInt32 get(); - System::Void set(System::UInt32 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ PowerSwitching { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean CompoundDevice { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ OverCurrentProtection { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HubInformationExType { - - private: Microsoft::Kits::Samples::Usb::HubTypeType hubTypeField; - - private: System::UInt16 highestPortNumberField; - - private: Microsoft::Kits::Samples::Usb::HubDescriptorType^ hubDescriptorField; - - private: Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ hub30DescriptorField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::HubTypeType HubType { - Microsoft::Kits::Samples::Usb::HubTypeType get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubTypeType value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::UInt16 HighestPortNumber { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubDescriptor { - Microsoft::Kits::Samples::Usb::HubDescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ Hub30Descriptor { - Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class Hub30DescriptorType { - - private: System::Byte lengthField; - - private: System::Byte descriptorTypeField; - - private: System::Byte numberOfPortsField; - - private: System::UInt16 hubCharacteristicsField; - - private: System::Byte powerOntoPowerGoodField; - - private: System::Byte hubControlCurrentField; - - private: System::Byte hubHdrDecLatField; - - private: System::UInt16 hubDelayField; - - private: System::UInt16 deviceRemovableField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte Length { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte DescriptorType { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte NumberOfPorts { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 HubCharacteristics { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte PowerOntoPowerGood { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte HubControlCurrent { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Byte HubHdrDecLat { - System::Byte get(); - System::Void set(System::Byte value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 HubDelay { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::UInt16 DeviceRemovable { - System::UInt16 get(); - System::Void set(System::UInt16 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HubCapabilitiesExType { - - private: System::Boolean hubIsHighSpeedCapableField; - - private: System::Boolean hubIsHighSpeedField; - - private: System::Boolean hubIsMultiTtCapableField; - - private: System::Boolean hubIsMultiTtField; - - private: System::Boolean hubIsRootField; - - private: System::Boolean hubIsArmedWakeOnConnectField; - - private: System::Boolean hubIsBusPoweredField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsHighSpeedCapable { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsHighSpeed { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsMultiTtCapable { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsMultiTt { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsRoot { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsArmedWakeOnConnect { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean HubIsBusPowered { - System::Boolean get(); - System::Void set(System::Boolean value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class RootHubType { - - private: Microsoft::Kits::Samples::Usb::HubNodeInformationType^ hubNodeInformationField; - - private: System::String^ hubNameField; - - private: Microsoft::Kits::Samples::Usb::HubInformationExType^ hubInformationExField; - - private: Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ hubCapabilityExField; - - private: cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ externalHubField; - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ usbDeviceField; - - private: cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ noDeviceField; - - private: System::String^ serviceNameField; - - private: System::String^ hwIdField; - - private: System::String^ deviceIdField; - - private: System::String^ deviceNameField; - - private: System::String^ deviceClassField; - - private: System::String^ usbProtocolField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::HubNodeInformationType^ HubNodeInformation { - Microsoft::Kits::Samples::Usb::HubNodeInformationType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ HubName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::HubInformationExType^ HubInformationEx { - Microsoft::Kits::Samples::Usb::HubInformationExType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ HubCapabilityEx { - Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"ExternalHub", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=4)] - property cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ ExternalHub { - cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"UsbDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, - Order=5)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ UsbDevice { - cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"NoDevice", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ NoDevice { - cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ ServiceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ HwId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceClass { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ UsbProtocol { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbHCPowerStateType { - - private: System::String^ systemStateField; - - private: System::String^ hostControllerStateField; - - private: System::String^ hubStateField; - - private: System::Boolean canWakeUpField; - - private: System::Boolean isPoweredField; - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ SystemState { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ HostControllerState { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ HubState { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean CanWakeUp { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::Boolean IsPowered { - System::Boolean get(); - System::Void set(System::Boolean value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbHCPowerStateMappingType { - - private: cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ powerMapField; - - private: System::String^ lastSleepStateField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(L"PowerMap", Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ PowerMap { - cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ get(); - System::Void set(cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::String^ LastSleepState { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class UsbHCDeviceInfoType { - - private: System::Int64 vendorIdField; - - private: System::Int64 deviceIdField; - - private: System::String^ driverKeyField; - - private: System::Int64 subSysIdField; - - private: System::Int64 revisionField; - - private: System::UInt64 debugPortField; - - private: System::UInt64 numberOfRootPortsField; - - private: System::UInt64 controllerFlavorField; - - private: System::String^ controllerFlavorStringField; - - private: System::Boolean portSwitchingEnabledField; - - private: System::Boolean selectiveSuspendEnabledField; - - private: System::UInt64 legacyBiosField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property System::Int64 VendorId { - System::Int64 get(); - System::Void set(System::Int64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property System::Int64 DeviceId { - System::Int64 get(); - System::Void set(System::Int64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property System::String^ DriverKey { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=3)] - property System::Int64 SubSysId { - System::Int64 get(); - System::Void set(System::Int64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=4)] - property System::Int64 Revision { - System::Int64 get(); - System::Void set(System::Int64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=5)] - property System::UInt64 DebugPort { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=6)] - property System::UInt64 NumberOfRootPorts { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=7)] - property System::UInt64 ControllerFlavor { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=8)] - property System::String^ ControllerFlavorString { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=9)] - property System::Boolean PortSwitchingEnabled { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=10)] - property System::Boolean SelectiveSuspendEnabled { - System::Boolean get(); - System::Void set(System::Boolean value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=11)] - property System::UInt64 LegacyBios { - System::UInt64 get(); - System::Void set(System::UInt64 value); - } - }; - - /// - [System::CodeDom::Compiler::GeneratedCodeAttribute(L"xsd", L"4.6.24.0"), - System::SerializableAttribute, - System::Diagnostics::DebuggerStepThroughAttribute, - System::ComponentModel::DesignerCategoryAttribute(L"code"), - System::Xml::Serialization::XmlTypeAttribute(Namespace=L"USB")] - public ref class HostControllerType { - - private: Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ controllerInfoField; - - private: Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ powerMappingField; - - private: Microsoft::Kits::Samples::Usb::RootHubType^ rootHubField; - - private: System::String^ serviceNameField; - - private: System::String^ hwIdField; - - private: System::String^ deviceIdField; - - private: System::String^ deviceNameField; - - private: System::String^ deviceClassField; - - private: System::String^ usbProtocolField; - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=0)] - property Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ ControllerInfo { - Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=1)] - property Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ PowerMapping { - Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ value); - } - - /// - public: [System::Xml::Serialization::XmlElementAttribute(Form=System::Xml::Schema::XmlSchemaForm::Unqualified, Order=2)] - property Microsoft::Kits::Samples::Usb::RootHubType^ RootHub { - Microsoft::Kits::Samples::Usb::RootHubType^ get(); - System::Void set(Microsoft::Kits::Samples::Usb::RootHubType^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ ServiceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ HwId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceId { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceName { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ DeviceClass { - System::String^ get(); - System::Void set(System::String^ value); - } - - /// - public: [System::Xml::Serialization::XmlAttributeAttribute] - property System::String^ UsbProtocol { - System::String^ get(); - System::Void set(System::String^ value); - } - }; - } - } - } -} -namespace Microsoft { - namespace Kits { - namespace Samples { - namespace Usb { - - - - - - - - inline Microsoft::Kits::Samples::Usb::UvcViewType^ UvcViewAll::UvcView::get() { - return this->uvcViewField; - } - inline System::Void UvcViewAll::UvcView::set(Microsoft::Kits::Samples::Usb::UvcViewType^ value) { - this->uvcViewField = value; - } - - - inline Microsoft::Kits::Samples::Usb::MachineInfoType^ UvcViewType::MachineInfo::get() { - return this->machineInfoField; - } - inline System::Void UvcViewType::MachineInfo::set(Microsoft::Kits::Samples::Usb::MachineInfoType^ value) { - this->machineInfoField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ UvcViewType::UsbTree::get() { - return this->usbTreeField; - } - inline System::Void UvcViewType::UsbTree::set(cli::array< Microsoft::Kits::Samples::Usb::HostControllerType^ >^ value) { - this->usbTreeField = value; - } - - - inline System::Byte MachineInfoType::UvcMajorVersion::get() { - return this->uvcMajorVersionField; - } - inline System::Void MachineInfoType::UvcMajorVersion::set(System::Byte value) { - this->uvcMajorVersionField = value; - } - - inline System::Byte MachineInfoType::UvcMinorVersion::get() { - return this->uvcMinorVersionField; - } - inline System::Void MachineInfoType::UvcMinorVersion::set(System::Byte value) { - this->uvcMinorVersionField = value; - } - - inline System::Byte MachineInfoType::UvcMajorSpecVersion::get() { - return this->uvcMajorSpecVersionField; - } - inline System::Void MachineInfoType::UvcMajorSpecVersion::set(System::Byte value) { - this->uvcMajorSpecVersionField = value; - } - - inline System::Byte MachineInfoType::UvcMinorSpecVersion::get() { - return this->uvcMinorSpecVersionField; - } - inline System::Void MachineInfoType::UvcMinorSpecVersion::set(System::Byte value) { - this->uvcMinorSpecVersionField = value; - } - - inline System::DateTime MachineInfoType::CollectionTime::get() { - return this->collectionTimeField; - } - inline System::Void MachineInfoType::CollectionTime::set(System::DateTime value) { - this->collectionTimeField = value; - } - - - inline Microsoft::Kits::Samples::Usb::PortConnectorType^ NoDeviceType::PortConnector::get() { - return this->portConnectorField; - } - inline System::Void NoDeviceType::PortConnector::set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value) { - this->portConnectorField = value; - } - - inline System::String^ NoDeviceType::UsbPortNumber::get() { - return this->usbPortNumberField; - } - inline System::Void NoDeviceType::UsbPortNumber::set(System::String^ value) { - this->usbPortNumberField = value; - } - - inline System::String^ NoDeviceType::Name::get() { - return this->nameField; - } - inline System::Void NoDeviceType::Name::set(System::String^ value) { - this->nameField = value; - } - - - inline System::UInt64 PortConnectorType::ConnectionIndex::get() { - return this->connectionIndexField; - } - inline System::Void PortConnectorType::ConnectionIndex::set(System::UInt64 value) { - this->connectionIndexField = value; - } - - inline System::UInt64 PortConnectorType::ActualLength::get() { - return this->actualLengthField; - } - inline System::Void PortConnectorType::ActualLength::set(System::UInt64 value) { - this->actualLengthField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ PortConnectorType::UsbPortProperties::get() { - return this->usbPortPropertiesField; - } - inline System::Void PortConnectorType::UsbPortProperties::set(Microsoft::Kits::Samples::Usb::UsbPortPropertiesType^ value) { - this->usbPortPropertiesField = value; - } - - inline System::UInt16 PortConnectorType::CompanionIndex::get() { - return this->companionIndexField; - } - inline System::Void PortConnectorType::CompanionIndex::set(System::UInt16 value) { - this->companionIndexField = value; - } - - inline System::UInt16 PortConnectorType::CompanionPortNumber::get() { - return this->companionPortNumberField; - } - inline System::Void PortConnectorType::CompanionPortNumber::set(System::UInt16 value) { - this->companionPortNumberField = value; - } - - inline System::String^ PortConnectorType::CompanionHubSymbolicLinkName::get() { - return this->companionHubSymbolicLinkNameField; - } - inline System::Void PortConnectorType::CompanionHubSymbolicLinkName::set(System::String^ value) { - this->companionHubSymbolicLinkNameField = value; - } - - - inline System::Boolean UsbPortPropertiesType::PortIsUserConnectable::get() { - return this->portIsUserConnectableField; - } - inline System::Void UsbPortPropertiesType::PortIsUserConnectable::set(System::Boolean value) { - this->portIsUserConnectableField = value; - } - - inline System::Boolean UsbPortPropertiesType::PortIsDebugCapable::get() { - return this->portIsDebugCapableField; - } - inline System::Void UsbPortPropertiesType::PortIsDebugCapable::set(System::Boolean value) { - this->portIsDebugCapableField = value; - } - - - inline System::UInt64 NodeConnectionInfoExV2Type::ConnectionIndex::get() { - return this->connectionIndexField; - } - inline System::Void NodeConnectionInfoExV2Type::ConnectionIndex::set(System::UInt64 value) { - this->connectionIndexField = value; - } - - inline System::UInt64 NodeConnectionInfoExV2Type::Length::get() { - return this->lengthField; - } - inline System::Void NodeConnectionInfoExV2Type::Length::set(System::UInt64 value) { - this->lengthField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::Usb110Supported::get() { - return this->usb110SupportedField; - } - inline System::Void NodeConnectionInfoExV2Type::Usb110Supported::set(System::Boolean value) { - this->usb110SupportedField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::Usb200Supported::get() { - return this->usb200SupportedField; - } - inline System::Void NodeConnectionInfoExV2Type::Usb200Supported::set(System::Boolean value) { - this->usb200SupportedField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::Usb300Supported::get() { - return this->usb300SupportedField; - } - inline System::Void NodeConnectionInfoExV2Type::Usb300Supported::set(System::Boolean value) { - this->usb300SupportedField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedOrHigher::get() { - return this->deviceIsOperatingAtSuperSpeedOrHigherField; - } - inline System::Void NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedOrHigher::set(System::Boolean value) { - this->deviceIsOperatingAtSuperSpeedOrHigherField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsSuperSpeedCapableOrHigher::get() { - return this->deviceIsSuperSpeedCapableOrHigherField; - } - inline System::Void NodeConnectionInfoExV2Type::DeviceIsSuperSpeedCapableOrHigher::set(System::Boolean value) { - this->deviceIsSuperSpeedCapableOrHigherField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedPlusOrHigher::get() { - return this->deviceIsOperatingAtSuperSpeedPlusOrHigherField; - } - inline System::Void NodeConnectionInfoExV2Type::DeviceIsOperatingAtSuperSpeedPlusOrHigher::set(System::Boolean value) { - this->deviceIsOperatingAtSuperSpeedPlusOrHigherField = value; - } - - inline System::Boolean NodeConnectionInfoExV2Type::DeviceIsSuperSpeedPlusCapableOrHigher::get() { - return this->deviceIsSuperSpeedPlusCapableOrHigherField; - } - inline System::Void NodeConnectionInfoExV2Type::DeviceIsSuperSpeedPlusCapableOrHigher::set(System::Boolean value) { - this->deviceIsSuperSpeedPlusCapableOrHigherField = value; - } - - - inline System::String^ UsbBillboardSVIDType::Description::get() { - return this->descriptionField; - } - inline System::Void UsbBillboardSVIDType::Description::set(System::String^ value) { - this->descriptionField = value; - } - - inline System::String^ UsbBillboardSVIDType::AlternateModeString::get() { - return this->alternateModeStringField; - } - inline System::Void UsbBillboardSVIDType::AlternateModeString::set(System::String^ value) { - this->alternateModeStringField = value; - } - - inline System::UInt16 UsbBillboardSVIDType::WSVID::get() { - return this->wSVIDField; - } - inline System::Void UsbBillboardSVIDType::WSVID::set(System::UInt16 value) { - this->wSVIDField = value; - } - - inline System::Byte UsbBillboardSVIDType::BAlternateMode::get() { - return this->bAlternateModeField; - } - inline System::Void UsbBillboardSVIDType::BAlternateMode::set(System::Byte value) { - this->bAlternateModeField = value; - } - - inline System::Byte UsbBillboardSVIDType::IAlternateModeString::get() { - return this->iAlternateModeStringField; - } - inline System::Void UsbBillboardSVIDType::IAlternateModeString::set(System::Byte value) { - this->iAlternateModeStringField = value; - } - - - inline System::String^ UsbBillboardCapabilityDescriptorType::VConnPower::get() { - return this->vConnPowerField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::VConnPower::set(System::String^ value) { - this->vConnPowerField = value; - } - - inline System::String^ UsbBillboardCapabilityDescriptorType::BillboardDescriptorErrors::get() { - return this->billboardDescriptorErrorsField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::BillboardDescriptorErrors::set(System::String^ value) { - this->billboardDescriptorErrorsField = value; - } - - inline System::String^ UsbBillboardCapabilityDescriptorType::AddtionalInfoURL::get() { - return this->addtionalInfoURLField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::AddtionalInfoURL::set(System::String^ value) { - this->addtionalInfoURLField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ UsbBillboardCapabilityDescriptorType::UsbBillboardSVID::get() { - return this->usbBillboardSVIDField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::UsbBillboardSVID::set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardSVIDType^ >^ value) { - this->usbBillboardSVIDField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::BDevCapabilityType::get() { - return this->bDevCapabilityTypeField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::BDevCapabilityType::set(System::Byte value) { - this->bDevCapabilityTypeField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::IAddtionalInfoURL::get() { - return this->iAddtionalInfoURLField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::IAddtionalInfoURL::set(System::Byte value) { - this->iAddtionalInfoURLField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::BNumberOfAlternateModes::get() { - return this->bNumberOfAlternateModesField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::BNumberOfAlternateModes::set(System::Byte value) { - this->bNumberOfAlternateModesField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::BPreferredAlternateMode::get() { - return this->bPreferredAlternateModeField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::BPreferredAlternateMode::set(System::Byte value) { - this->bPreferredAlternateModeField = value; - } - - inline System::Byte UsbBillboardCapabilityDescriptorType::CalculatedBLength::get() { - return this->calculatedBLengthField; - } - inline System::Void UsbBillboardCapabilityDescriptorType::CalculatedBLength::set(System::Byte value) { - this->calculatedBLengthField = value; - } - - - inline System::String^ UsbDispContIdCapExtDescriptorType::ReservedBitError::get() { - return this->reservedBitErrorField; - } - inline System::Void UsbDispContIdCapExtDescriptorType::ReservedBitError::set(System::String^ value) { - this->reservedBitErrorField = value; - } - - inline System::String^ UsbDispContIdCapExtDescriptorType::ContainerIdStr::get() { - return this->containerIdStrField; - } - inline System::Void UsbDispContIdCapExtDescriptorType::ContainerIdStr::set(System::String^ value) { - this->containerIdStrField = value; - } - - inline System::Byte UsbDispContIdCapExtDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDispContIdCapExtDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDispContIdCapExtDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDispContIdCapExtDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbDispContIdCapExtDescriptorType::BReserved::get() { - return this->bReservedField; - } - inline System::Void UsbDispContIdCapExtDescriptorType::BReserved::set(System::Byte value) { - this->bReservedField = value; - } - - inline System::Byte UsbDispContIdCapExtDescriptorType::BDevCapabilityType::get() { - return this->bDevCapabilityTypeField; - } - inline System::Void UsbDispContIdCapExtDescriptorType::BDevCapabilityType::set(System::Byte value) { - this->bDevCapabilityTypeField = value; - } - - - inline System::String^ UsbUsb20ExtensionDescriptorType::ReservedBitError::get() { - return this->reservedBitErrorField; - } - inline System::Void UsbUsb20ExtensionDescriptorType::ReservedBitError::set(System::String^ value) { - this->reservedBitErrorField = value; - } - - inline System::Byte UsbUsb20ExtensionDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbUsb20ExtensionDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbUsb20ExtensionDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbUsb20ExtensionDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbUsb20ExtensionDescriptorType::BDevCapabilityType::get() { - return this->bDevCapabilityTypeField; - } - inline System::Void UsbUsb20ExtensionDescriptorType::BDevCapabilityType::set(System::Byte value) { - this->bDevCapabilityTypeField = value; - } - - inline System::UInt64 UsbUsb20ExtensionDescriptorType::BmAttributes::get() { - return this->bmAttributesField; - } - inline System::Void UsbUsb20ExtensionDescriptorType::BmAttributes::set(System::UInt64 value) { - this->bmAttributesField = value; - } - - inline System::Boolean UsbUsb20ExtensionDescriptorType::SupportsLinkPowerManagement::get() { - return this->supportsLinkPowerManagementField; - } - inline System::Void UsbUsb20ExtensionDescriptorType::SupportsLinkPowerManagement::set(System::Boolean value) { - this->supportsLinkPowerManagementField = value; - } - - - inline System::String^ UsbSuperSpeedExtensionDescriptorType::ReservedAttributesBitError::get() { - return this->reservedAttributesBitErrorField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::ReservedAttributesBitError::set(System::String^ value) { - this->reservedAttributesBitErrorField = value; - } - - inline System::String^ UsbSuperSpeedExtensionDescriptorType::ReservedSpeedBitError::get() { - return this->reservedSpeedBitErrorField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::ReservedSpeedBitError::set(System::String^ value) { - this->reservedSpeedBitErrorField = value; - } - - inline System::String^ UsbSuperSpeedExtensionDescriptorType::ReservedSpeedError::get() { - return this->reservedSpeedErrorField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::ReservedSpeedError::set(System::String^ value) { - this->reservedSpeedErrorField = value; - } - - inline System::Byte UsbSuperSpeedExtensionDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbSuperSpeedExtensionDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbSuperSpeedExtensionDescriptorType::BDevCapabilityType::get() { - return this->bDevCapabilityTypeField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::BDevCapabilityType::set(System::Byte value) { - this->bDevCapabilityTypeField = value; - } - - inline System::UInt64 UsbSuperSpeedExtensionDescriptorType::BmAttributes::get() { - return this->bmAttributesField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::BmAttributes::set(System::UInt64 value) { - this->bmAttributesField = value; - } - - inline System::Boolean UsbSuperSpeedExtensionDescriptorType::LatencyToleranceMsgCapable::get() { - return this->latencyToleranceMsgCapableField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::LatencyToleranceMsgCapable::set(System::Boolean value) { - this->latencyToleranceMsgCapableField = value; - } - - inline System::Byte UsbSuperSpeedExtensionDescriptorType::BFunctionalitySupport::get() { - return this->bFunctionalitySupportField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::BFunctionalitySupport::set(System::Byte value) { - this->bFunctionalitySupportField = value; - } - - inline System::Byte UsbSuperSpeedExtensionDescriptorType::BU1DevExitLat::get() { - return this->bU1DevExitLatField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::BU1DevExitLat::set(System::Byte value) { - this->bU1DevExitLatField = value; - } - - inline System::UInt16 UsbSuperSpeedExtensionDescriptorType::WSpeedsSupported::get() { - return this->wSpeedsSupportedField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::WSpeedsSupported::set(System::UInt16 value) { - this->wSpeedsSupportedField = value; - } - - inline System::UInt16 UsbSuperSpeedExtensionDescriptorType::WU2DevExitLat::get() { - return this->wU2DevExitLatField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::WU2DevExitLat::set(System::UInt16 value) { - this->wU2DevExitLatField = value; - } - - inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsLowSpeed::get() { - return this->supportsLowSpeedField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsLowSpeed::set(System::Boolean value) { - this->supportsLowSpeedField = value; - } - - inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsFullSpeed::get() { - return this->supportsFullSpeedField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsFullSpeed::set(System::Boolean value) { - this->supportsFullSpeedField = value; - } - - inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsHighSpeed::get() { - return this->supportsHighSpeedField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsHighSpeed::set(System::Boolean value) { - this->supportsHighSpeedField = value; - } - - inline System::Boolean UsbSuperSpeedExtensionDescriptorType::SupportsSuperSpeed::get() { - return this->supportsSuperSpeedField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::SupportsSuperSpeed::set(System::Boolean value) { - this->supportsSuperSpeedField = value; - } - - inline System::String^ UsbSuperSpeedExtensionDescriptorType::LowestSpeed::get() { - return this->lowestSpeedField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::LowestSpeed::set(System::String^ value) { - this->lowestSpeedField = value; - } - - inline System::String^ UsbSuperSpeedExtensionDescriptorType::U1DevExitLatencyString::get() { - return this->u1DevExitLatencyStringField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::U1DevExitLatencyString::set(System::String^ value) { - this->u1DevExitLatencyStringField = value; - } - - inline System::String^ UsbSuperSpeedExtensionDescriptorType::U2DevExitLatencyString::get() { - return this->u2DevExitLatencyStringField; - } - inline System::Void UsbSuperSpeedExtensionDescriptorType::U2DevExitLatencyString::set(System::String^ value) { - this->u2DevExitLatencyStringField = value; - } - - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ UsbBosDescriptorType::UnknownDescriptor::get() { - return this->unknownDescriptorField; - } - inline System::Void UsbBosDescriptorType::UnknownDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ >^ value) { - this->unknownDescriptorField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ UsbBosDescriptorType::UsbSuperSpeedExtensionDescriptor::get() { - return this->usbSuperSpeedExtensionDescriptorField; - } - inline System::Void UsbBosDescriptorType::UsbSuperSpeedExtensionDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbSuperSpeedExtensionDescriptorType^ >^ value) { - this->usbSuperSpeedExtensionDescriptorField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ UsbBosDescriptorType::UsbUsb20ExtensionDescriptor::get() { - return this->usbUsb20ExtensionDescriptorField; - } - inline System::Void UsbBosDescriptorType::UsbUsb20ExtensionDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbUsb20ExtensionDescriptorType^ >^ value) { - this->usbUsb20ExtensionDescriptorField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ UsbBosDescriptorType::UsbDispContIdCapExtDescriptor::get() { - return this->usbDispContIdCapExtDescriptorField; - } - inline System::Void UsbBosDescriptorType::UsbDispContIdCapExtDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDispContIdCapExtDescriptorType^ >^ value) { - this->usbDispContIdCapExtDescriptorField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ UsbBosDescriptorType::UsbBillboardCapabilityDescriptor::get() { - return this->usbBillboardCapabilityDescriptorField; - } - inline System::Void UsbBosDescriptorType::UsbBillboardCapabilityDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbBillboardCapabilityDescriptorType^ >^ value) { - this->usbBillboardCapabilityDescriptorField = value; - } - - inline System::Byte UsbBosDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbBosDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbBosDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbBosDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::UInt16 UsbBosDescriptorType::WTotalLength::get() { - return this->wTotalLengthField; - } - inline System::Void UsbBosDescriptorType::WTotalLength::set(System::UInt16 value) { - this->wTotalLengthField = value; - } - - inline System::Byte UsbBosDescriptorType::BNumDeviceCaps::get() { - return this->bNumDeviceCapsField; - } - inline System::Void UsbBosDescriptorType::BNumDeviceCaps::set(System::Byte value) { - this->bNumDeviceCapsField = value; - } - - - inline System::String^ UsbDeviceUnknownDescriptorType::UnknownDescriptor::get() { - return this->unknownDescriptorField; - } - inline System::Void UsbDeviceUnknownDescriptorType::UnknownDescriptor::set(System::String^ value) { - this->unknownDescriptorField = value; - } - - inline System::Byte UsbDeviceUnknownDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDeviceUnknownDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDeviceUnknownDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceUnknownDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - - inline Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ UsbDeviceIADDescriptorType::FunctionDetails::get() { - return this->functionDetailsField; - } - inline System::Void UsbDeviceIADDescriptorType::FunctionDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value) { - this->functionDetailsField = value; - } - - inline System::String^ UsbDeviceIADDescriptorType::InterfaceError::get() { - return this->interfaceErrorField; - } - inline System::Void UsbDeviceIADDescriptorType::InterfaceError::set(System::String^ value) { - this->interfaceErrorField = value; - } - - inline System::String^ UsbDeviceIADDescriptorType::FunctionClassError::get() { - return this->functionClassErrorField; - } - inline System::Void UsbDeviceIADDescriptorType::FunctionClassError::set(System::String^ value) { - this->functionClassErrorField = value; - } - - inline System::String^ UsbDeviceIADDescriptorType::Protocol::get() { - return this->protocolField; - } - inline System::Void UsbDeviceIADDescriptorType::Protocol::set(System::String^ value) { - this->protocolField = value; - } - - inline System::String^ UsbDeviceIADDescriptorType::StringDesc::get() { - return this->stringDescField; - } - inline System::Void UsbDeviceIADDescriptorType::StringDesc::set(System::String^ value) { - this->stringDescField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDeviceIADDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceIADDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BFirstInterface::get() { - return this->bFirstInterfaceField; - } - inline System::Void UsbDeviceIADDescriptorType::BFirstInterface::set(System::Byte value) { - this->bFirstInterfaceField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BInterfaceCount::get() { - return this->bInterfaceCountField; - } - inline System::Void UsbDeviceIADDescriptorType::BInterfaceCount::set(System::Byte value) { - this->bInterfaceCountField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BFunctionClass::get() { - return this->bFunctionClassField; - } - inline System::Void UsbDeviceIADDescriptorType::BFunctionClass::set(System::Byte value) { - this->bFunctionClassField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BFunctionSubclass::get() { - return this->bFunctionSubclassField; - } - inline System::Void UsbDeviceIADDescriptorType::BFunctionSubclass::set(System::Byte value) { - this->bFunctionSubclassField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::BFunctionProtocol::get() { - return this->bFunctionProtocolField; - } - inline System::Void UsbDeviceIADDescriptorType::BFunctionProtocol::set(System::Byte value) { - this->bFunctionProtocolField = value; - } - - inline System::Byte UsbDeviceIADDescriptorType::IFunction::get() { - return this->iFunctionField; - } - inline System::Void UsbDeviceIADDescriptorType::IFunction::set(System::Byte value) { - this->iFunctionField = value; - } - - - inline System::String^ UsbDeviceClassType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void UsbDeviceClassType::DeviceClass::set(System::String^ value) { - this->deviceClassField = value; - } - - inline System::String^ UsbDeviceClassType::DeviceSubclass::get() { - return this->deviceSubclassField; - } - inline System::Void UsbDeviceClassType::DeviceSubclass::set(System::String^ value) { - this->deviceSubclassField = value; - } - - - inline System::Byte UsbDeviceOTGDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDeviceOTGDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDeviceOTGDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceOTGDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbDeviceOTGDescriptorType::BmAttributes::get() { - return this->bmAttributesField; - } - inline System::Void UsbDeviceOTGDescriptorType::BmAttributes::set(System::Byte value) { - this->bmAttributesField = value; - } - - inline System::String^ UsbDeviceOTGDescriptorType::AttributesString::get() { - return this->attributesStringField; - } - inline System::Void UsbDeviceOTGDescriptorType::AttributesString::set(System::String^ value) { - this->attributesStringField = value; - } - - - inline System::Byte UsbDeviceHidOptionalDescriptorsType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceHidOptionalDescriptorsType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::UInt16 UsbDeviceHidOptionalDescriptorsType::WDescriptorLength::get() { - return this->wDescriptorLengthField; - } - inline System::Void UsbDeviceHidOptionalDescriptorsType::WDescriptorLength::set(System::UInt16 value) { - this->wDescriptorLengthField = value; - } - - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ UsbDeviceHidDescriptorType::OptionalDescriptor::get() { - return this->optionalDescriptorField; - } - inline System::Void UsbDeviceHidDescriptorType::OptionalDescriptor::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceHidOptionalDescriptorsType^ >^ value) { - this->optionalDescriptorField = value; - } - - inline System::Byte UsbDeviceHidDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDeviceHidDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDeviceHidDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceHidDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::UInt16 UsbDeviceHidDescriptorType::BcdHID::get() { - return this->bcdHIDField; - } - inline System::Void UsbDeviceHidDescriptorType::BcdHID::set(System::UInt16 value) { - this->bcdHIDField = value; - } - - inline System::Byte UsbDeviceHidDescriptorType::BCountryCode::get() { - return this->bCountryCodeField; - } - inline System::Void UsbDeviceHidDescriptorType::BCountryCode::set(System::Byte value) { - this->bCountryCodeField = value; - } - - inline System::Byte UsbDeviceHidDescriptorType::BNumDescriptors::get() { - return this->bNumDescriptorsField; - } - inline System::Void UsbDeviceHidDescriptorType::BNumDescriptors::set(System::Byte value) { - this->bNumDescriptorsField = value; - } - - - inline Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ UsbDeviceInterfaceDescriptorType::InterfaceDetails::get() { - return this->interfaceDetailsField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::InterfaceDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value) { - this->interfaceDetailsField = value; - } - - inline System::String^ UsbDeviceInterfaceDescriptorType::ProtocolError::get() { - return this->protocolErrorField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::ProtocolError::set(System::String^ value) { - this->protocolErrorField = value; - } - - inline System::String^ UsbDeviceInterfaceDescriptorType::StringDesc::get() { - return this->stringDescField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::StringDesc::set(System::String^ value) { - this->stringDescField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceNumber::get() { - return this->bInterfaceNumberField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceNumber::set(System::Byte value) { - this->bInterfaceNumberField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BAlternateSetting::get() { - return this->bAlternateSettingField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BAlternateSetting::set(System::Byte value) { - this->bAlternateSettingField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BNumEndpoints::get() { - return this->bNumEndpointsField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BNumEndpoints::set(System::Byte value) { - this->bNumEndpointsField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceClass::get() { - return this->bInterfaceClassField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceClass::set(System::Byte value) { - this->bInterfaceClassField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceSubclass::get() { - return this->bInterfaceSubclassField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceSubclass::set(System::Byte value) { - this->bInterfaceSubclassField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::BInterfaceProtocol::get() { - return this->bInterfaceProtocolField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::BInterfaceProtocol::set(System::Byte value) { - this->bInterfaceProtocolField = value; - } - - inline System::Byte UsbDeviceInterfaceDescriptorType::IInterface::get() { - return this->iInterfaceField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::IInterface::set(System::Byte value) { - this->iInterfaceField = value; - } - - inline System::UInt16 UsbDeviceInterfaceDescriptorType::WNumClasses::get() { - return this->wNumClassesField; - } - inline System::Void UsbDeviceInterfaceDescriptorType::WNumClasses::set(System::UInt16 value) { - this->wNumClassesField = value; - } - - - inline System::String^ UsbDeviceQualifierDescriptorType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void UsbDeviceQualifierDescriptorType::DeviceClass::set(System::String^ value) { - this->deviceClassField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytes::get() { - return this->maxPacketSizeInBytesField; - } - inline System::Void UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytes::set(System::Byte value) { - this->maxPacketSizeInBytesField = value; - } - - inline System::Boolean UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytesSpecified::get() { - return this->maxPacketSizeInBytesFieldSpecified; - } - inline System::Void UsbDeviceQualifierDescriptorType::MaxPacketSizeInBytesSpecified::set(System::Boolean value) { - this->maxPacketSizeInBytesFieldSpecified = value; - } - - inline System::String^ UsbDeviceQualifierDescriptorType::DeviceClassError::get() { - return this->deviceClassErrorField; - } - inline System::Void UsbDeviceQualifierDescriptorType::DeviceClassError::set(System::String^ value) { - this->deviceClassErrorField = value; - } - - inline System::String^ UsbDeviceQualifierDescriptorType::DeviceSubclassError::get() { - return this->deviceSubclassErrorField; - } - inline System::Void UsbDeviceQualifierDescriptorType::DeviceSubclassError::set(System::String^ value) { - this->deviceSubclassErrorField = value; - } - - inline System::String^ UsbDeviceQualifierDescriptorType::DeviceProtocolError::get() { - return this->deviceProtocolErrorField; - } - inline System::Void UsbDeviceQualifierDescriptorType::DeviceProtocolError::set(System::String^ value) { - this->deviceProtocolErrorField = value; - } - - inline System::String^ UsbDeviceQualifierDescriptorType::DeviceNumConfigError::get() { - return this->deviceNumConfigErrorField; - } - inline System::Void UsbDeviceQualifierDescriptorType::DeviceNumConfigError::set(System::String^ value) { - this->deviceNumConfigErrorField = value; - } - - inline System::String^ UsbDeviceQualifierDescriptorType::ReservedError::get() { - return this->reservedErrorField; - } - inline System::Void UsbDeviceQualifierDescriptorType::ReservedError::set(System::String^ value) { - this->reservedErrorField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbDeviceQualifierDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbDeviceQualifierDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::UInt16 UsbDeviceQualifierDescriptorType::BcdUSB::get() { - return this->bcdUSBField; - } - inline System::Void UsbDeviceQualifierDescriptorType::BcdUSB::set(System::UInt16 value) { - this->bcdUSBField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::BDeviceClass::get() { - return this->bDeviceClassField; - } - inline System::Void UsbDeviceQualifierDescriptorType::BDeviceClass::set(System::Byte value) { - this->bDeviceClassField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::BDeviceSubclass::get() { - return this->bDeviceSubclassField; - } - inline System::Void UsbDeviceQualifierDescriptorType::BDeviceSubclass::set(System::Byte value) { - this->bDeviceSubclassField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::BDeviceProtocol::get() { - return this->bDeviceProtocolField; - } - inline System::Void UsbDeviceQualifierDescriptorType::BDeviceProtocol::set(System::Byte value) { - this->bDeviceProtocolField = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::BMaxPacketSize0::get() { - return this->bMaxPacketSize0Field; - } - inline System::Void UsbDeviceQualifierDescriptorType::BMaxPacketSize0::set(System::Byte value) { - this->bMaxPacketSize0Field = value; - } - - inline System::Byte UsbDeviceQualifierDescriptorType::NumConfigurations::get() { - return this->numConfigurationsField; - } - inline System::Void UsbDeviceQualifierDescriptorType::NumConfigurations::set(System::Byte value) { - this->numConfigurationsField = value; - } - - - inline System::String^ UsbConfigurationDescriptorType::ConfigDescError::get() { - return this->configDescErrorField; - } - inline System::Void UsbConfigurationDescriptorType::ConfigDescError::set(System::String^ value) { - this->configDescErrorField = value; - } - - inline System::String^ UsbConfigurationDescriptorType::ConfValueError::get() { - return this->confValueErrorField; - } - inline System::Void UsbConfigurationDescriptorType::ConfValueError::set(System::String^ value) { - this->confValueErrorField = value; - } - - inline System::String^ UsbConfigurationDescriptorType::ConfStringDesc::get() { - return this->confStringDescField; - } - inline System::Void UsbConfigurationDescriptorType::ConfStringDesc::set(System::String^ value) { - this->confStringDescField = value; - } - - inline System::String^ UsbConfigurationDescriptorType::AttributesStr::get() { - return this->attributesStrField; - } - inline System::Void UsbConfigurationDescriptorType::AttributesStr::set(System::String^ value) { - this->attributesStrField = value; - } - - inline System::String^ UsbConfigurationDescriptorType::MaxCurrent::get() { - return this->maxCurrentField; - } - inline System::Void UsbConfigurationDescriptorType::MaxCurrent::set(System::String^ value) { - this->maxCurrentField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::BLength::get() { - return this->bLengthField; - } - inline System::Void UsbConfigurationDescriptorType::BLength::set(System::Byte value) { - this->bLengthField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::BDescriptorType::get() { - return this->bDescriptorTypeField; - } - inline System::Void UsbConfigurationDescriptorType::BDescriptorType::set(System::Byte value) { - this->bDescriptorTypeField = value; - } - - inline System::UInt16 UsbConfigurationDescriptorType::WTotalLength::get() { - return this->wTotalLengthField; - } - inline System::Void UsbConfigurationDescriptorType::WTotalLength::set(System::UInt16 value) { - this->wTotalLengthField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::BNumInterfaces::get() { - return this->bNumInterfacesField; - } - inline System::Void UsbConfigurationDescriptorType::BNumInterfaces::set(System::Byte value) { - this->bNumInterfacesField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::BConfigurationValue::get() { - return this->bConfigurationValueField; - } - inline System::Void UsbConfigurationDescriptorType::BConfigurationValue::set(System::Byte value) { - this->bConfigurationValueField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::IConfiguration::get() { - return this->iConfigurationField; - } - inline System::Void UsbConfigurationDescriptorType::IConfiguration::set(System::Byte value) { - this->iConfigurationField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::BmAttributes::get() { - return this->bmAttributesField; - } - inline System::Void UsbConfigurationDescriptorType::BmAttributes::set(System::Byte value) { - this->bmAttributesField = value; - } - - inline System::Byte UsbConfigurationDescriptorType::MaxPower::get() { - return this->maxPowerField; - } - inline System::Void UsbConfigurationDescriptorType::MaxPower::set(System::Byte value) { - this->maxPowerField = value; - } - - - inline System::String^ UsbDeviceConfigurationType::DeviceQualifierError::get() { - return this->deviceQualifierErrorField; - } - inline System::Void UsbDeviceConfigurationType::DeviceQualifierError::set(System::String^ value) { - this->deviceQualifierErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::SpeedConfigurationError::get() { - return this->speedConfigurationErrorField; - } - inline System::Void UsbDeviceConfigurationType::SpeedConfigurationError::set(System::String^ value) { - this->speedConfigurationErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::DeviceConfigurationError::get() { - return this->deviceConfigurationErrorField; - } - inline System::Void UsbDeviceConfigurationType::DeviceConfigurationError::set(System::String^ value) { - this->deviceConfigurationErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::InterfaceError::get() { - return this->interfaceErrorField; - } - inline System::Void UsbDeviceConfigurationType::InterfaceError::set(System::String^ value) { - this->interfaceErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::PreReleaseError::get() { - return this->preReleaseErrorField; - } - inline System::Void UsbDeviceConfigurationType::PreReleaseError::set(System::String^ value) { - this->preReleaseErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::EndpointError::get() { - return this->endpointErrorField; - } - inline System::Void UsbDeviceConfigurationType::EndpointError::set(System::String^ value) { - this->endpointErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::HidError::get() { - return this->hidErrorField; - } - inline System::Void UsbDeviceConfigurationType::HidError::set(System::String^ value) { - this->hidErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::OtgError::get() { - return this->otgErrorField; - } - inline System::Void UsbDeviceConfigurationType::OtgError::set(System::String^ value) { - this->otgErrorField = value; - } - - inline System::String^ UsbDeviceConfigurationType::IadError::get() { - return this->iadErrorField; - } - inline System::Void UsbDeviceConfigurationType::IadError::set(System::String^ value) { - this->iadErrorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ UsbDeviceConfigurationType::DeviceDetails::get() { - return this->deviceDetailsField; - } - inline System::Void UsbDeviceConfigurationType::DeviceDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassType^ value) { - this->deviceDetailsField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ UsbDeviceConfigurationType::ConfigurationDescriptor::get() { - return this->configurationDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::ConfigurationDescriptor::set(Microsoft::Kits::Samples::Usb::UsbConfigurationDescriptorType^ value) { - this->configurationDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ UsbDeviceConfigurationType::DeviceQualifierDescriptor::get() { - return this->deviceQualifierDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::DeviceQualifierDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceQualifierDescriptorType^ value) { - this->deviceQualifierDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ UsbDeviceConfigurationType::InterfaceDescriptor::get() { - return this->interfaceDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::InterfaceDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceInterfaceDescriptorType^ value) { - this->interfaceDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ UsbDeviceConfigurationType::EndpointDescriptor::get() { - return this->endpointDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::EndpointDescriptor::set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value) { - this->endpointDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ UsbDeviceConfigurationType::HidDescriptor::get() { - return this->hidDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::HidDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceHidDescriptorType^ value) { - this->hidDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ UsbDeviceConfigurationType::OtgDescriptor::get() { - return this->otgDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::OtgDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceOTGDescriptorType^ value) { - this->otgDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ UsbDeviceConfigurationType::IadDescriptor::get() { - return this->iadDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::IadDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceIADDescriptorType^ value) { - this->iadDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ UsbDeviceConfigurationType::UnknownDescriptor::get() { - return this->unknownDescriptorField; - } - inline System::Void UsbDeviceConfigurationType::UnknownDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceUnknownDescriptorType^ value) { - this->unknownDescriptorField = value; - } - - - inline System::Byte EndpointDescriptorType::Length::get() { - return this->lengthField; - } - inline System::Void EndpointDescriptorType::Length::set(System::Byte value) { - this->lengthField = value; - } - - inline System::Byte EndpointDescriptorType::DescriptorType::get() { - return this->descriptorTypeField; - } - inline System::Void EndpointDescriptorType::DescriptorType::set(System::Byte value) { - this->descriptorTypeField = value; - } - - inline System::Byte EndpointDescriptorType::EndpointAddress::get() { - return this->endpointAddressField; - } - inline System::Void EndpointDescriptorType::EndpointAddress::set(System::Byte value) { - this->endpointAddressField = value; - } - - inline System::Byte EndpointDescriptorType::Attributes::get() { - return this->attributesField; - } - inline System::Void EndpointDescriptorType::Attributes::set(System::Byte value) { - this->attributesField = value; - } - - inline System::UInt16 EndpointDescriptorType::MaxPacketSize::get() { - return this->maxPacketSizeField; - } - inline System::Void EndpointDescriptorType::MaxPacketSize::set(System::UInt16 value) { - this->maxPacketSizeField = value; - } - - inline System::Byte EndpointDescriptorType::Interval::get() { - return this->intervalField; - } - inline System::Void EndpointDescriptorType::Interval::set(System::Byte value) { - this->intervalField = value; - } - - inline System::UInt16 EndpointDescriptorType::WInterval::get() { - return this->wIntervalField; - } - inline System::Void EndpointDescriptorType::WInterval::set(System::UInt16 value) { - this->wIntervalField = value; - } - - inline System::Byte EndpointDescriptorType::SyncAddress::get() { - return this->syncAddressField; - } - inline System::Void EndpointDescriptorType::SyncAddress::set(System::Byte value) { - this->syncAddressField = value; - } - - inline System::String^ EndpointDescriptorType::EndpointDirection::get() { - return this->endpointDirectionField; - } - inline System::Void EndpointDescriptorType::EndpointDirection::set(System::String^ value) { - this->endpointDirectionField = value; - } - - inline System::Byte EndpointDescriptorType::EndpointId::get() { - return this->endpointIdField; - } - inline System::Void EndpointDescriptorType::EndpointId::set(System::Byte value) { - this->endpointIdField = value; - } - - inline System::String^ EndpointDescriptorType::EndpointType::get() { - return this->endpointTypeField; - } - inline System::Void EndpointDescriptorType::EndpointType::set(System::String^ value) { - this->endpointTypeField = value; - } - - inline System::String^ EndpointDescriptorType::EndpointPacketInfo::get() { - return this->endpointPacketInfoField; - } - inline System::Void EndpointDescriptorType::EndpointPacketInfo::set(System::String^ value) { - this->endpointPacketInfoField = value; - } - - inline System::String^ EndpointDescriptorType::EndpointPacketSizeValidation::get() { - return this->endpointPacketSizeValidationField; - } - inline System::Void EndpointDescriptorType::EndpointPacketSizeValidation::set(System::String^ value) { - this->endpointPacketSizeValidationField = value; - } - - - inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ UsbDeviceType::ConnectionInfo::get() { - return this->connectionInfoField; - } - inline System::Void UsbDeviceType::ConnectionInfo::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value) { - this->connectionInfoField = value; - } - - inline Microsoft::Kits::Samples::Usb::PortConnectorType^ UsbDeviceType::PortConnector::get() { - return this->portConnectorField; - } - inline System::Void UsbDeviceType::PortConnector::set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value) { - this->portConnectorField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ UsbDeviceType::DeviceConfiguration::get() { - return this->deviceConfigurationField; - } - inline System::Void UsbDeviceType::DeviceConfiguration::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value) { - this->deviceConfigurationField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ UsbDeviceType::BosDescriptor::get() { - return this->bosDescriptorField; - } - inline System::Void UsbDeviceType::BosDescriptor::set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value) { - this->bosDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ UsbDeviceType::ConnectionInfoV2::get() { - return this->connectionInfoV2Field; - } - inline System::Void UsbDeviceType::ConnectionInfoV2::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value) { - this->connectionInfoV2Field = value; - } - - inline System::String^ UsbDeviceType::UsbPortNumber::get() { - return this->usbPortNumberField; - } - inline System::Void UsbDeviceType::UsbPortNumber::set(System::String^ value) { - this->usbPortNumberField = value; - } - - inline System::String^ UsbDeviceType::ServiceName::get() { - return this->serviceNameField; - } - inline System::Void UsbDeviceType::ServiceName::set(System::String^ value) { - this->serviceNameField = value; - } - - inline System::String^ UsbDeviceType::HwId::get() { - return this->hwIdField; - } - inline System::Void UsbDeviceType::HwId::set(System::String^ value) { - this->hwIdField = value; - } - - inline System::String^ UsbDeviceType::DeviceId::get() { - return this->deviceIdField; - } - inline System::Void UsbDeviceType::DeviceId::set(System::String^ value) { - this->deviceIdField = value; - } - - inline System::String^ UsbDeviceType::DeviceName::get() { - return this->deviceNameField; - } - inline System::Void UsbDeviceType::DeviceName::set(System::String^ value) { - this->deviceNameField = value; - } - - inline System::String^ UsbDeviceType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void UsbDeviceType::DeviceClass::set(System::String^ value) { - this->deviceClassField = value; - } - - inline System::String^ UsbDeviceType::UsbProtocol::get() { - return this->usbProtocolField; - } - inline System::Void UsbDeviceType::UsbProtocol::set(System::String^ value) { - this->usbProtocolField = value; - } - - - inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ NodeConnectionInfoExType::ConnectionInfoStruct::get() { - return this->connectionInfoStructField; - } - inline System::Void NodeConnectionInfoExType::ConnectionInfoStruct::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExStructType^ value) { - this->connectionInfoStructField = value; - } - - inline System::String^ NodeConnectionInfoExType::IProductStringDescEn::get() { - return this->iProductStringDescEnField; - } - inline System::Void NodeConnectionInfoExType::IProductStringDescEn::set(System::String^ value) { - this->iProductStringDescEnField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ NodeConnectionInfoExType::DeviceClassDetails::get() { - return this->deviceClassDetailsField; - } - inline System::Void NodeConnectionInfoExType::DeviceClassDetails::set(Microsoft::Kits::Samples::Usb::UsbDeviceClassDetailsType^ value) { - this->deviceClassDetailsField = value; - } - - inline System::Byte NodeConnectionInfoExType::MaxPacketSizeInBytes::get() { - return this->maxPacketSizeInBytesField; - } - inline System::Void NodeConnectionInfoExType::MaxPacketSizeInBytes::set(System::Byte value) { - this->maxPacketSizeInBytesField = value; - } - - inline System::String^ NodeConnectionInfoExType::VendorString::get() { - return this->vendorStringField; - } - inline System::Void NodeConnectionInfoExType::VendorString::set(System::String^ value) { - this->vendorStringField = value; - } - - inline System::String^ NodeConnectionInfoExType::ManufacturerString::get() { - return this->manufacturerStringField; - } - inline System::Void NodeConnectionInfoExType::ManufacturerString::set(System::String^ value) { - this->manufacturerStringField = value; - } - - inline System::String^ NodeConnectionInfoExType::ProductString::get() { - return this->productStringField; - } - inline System::Void NodeConnectionInfoExType::ProductString::set(System::String^ value) { - this->productStringField = value; - } - - inline System::String^ NodeConnectionInfoExType::LangIdString::get() { - return this->langIdStringField; - } - inline System::Void NodeConnectionInfoExType::LangIdString::set(System::String^ value) { - this->langIdStringField = value; - } - - inline System::String^ NodeConnectionInfoExType::SerialString::get() { - return this->serialStringField; - } - inline System::Void NodeConnectionInfoExType::SerialString::set(System::String^ value) { - this->serialStringField = value; - } - - inline System::String^ NodeConnectionInfoExType::PipeInfoError::get() { - return this->pipeInfoErrorField; - } - inline System::Void NodeConnectionInfoExType::PipeInfoError::set(System::String^ value) { - this->pipeInfoErrorField = value; - } - - inline System::String^ NodeConnectionInfoExType::LengthError::get() { - return this->lengthErrorField; - } - inline System::Void NodeConnectionInfoExType::LengthError::set(System::String^ value) { - this->lengthErrorField = value; - } - - inline System::String^ NodeConnectionInfoExType::DeviceError::get() { - return this->deviceErrorField; - } - inline System::Void NodeConnectionInfoExType::DeviceError::set(System::String^ value) { - this->deviceErrorField = value; - } - - inline System::String^ NodeConnectionInfoExType::PacketSizeError::get() { - return this->packetSizeErrorField; - } - inline System::Void NodeConnectionInfoExType::PacketSizeError::set(System::String^ value) { - this->packetSizeErrorField = value; - } - - inline System::String^ NodeConnectionInfoExType::ConfigurationCountError::get() { - return this->configurationCountErrorField; - } - inline System::Void NodeConnectionInfoExType::ConfigurationCountError::set(System::String^ value) { - this->configurationCountErrorField = value; - } - - - inline System::UInt64 NodeConnectionInfoExStructType::ConnectionIndex::get() { - return this->connectionIndexField; - } - inline System::Void NodeConnectionInfoExStructType::ConnectionIndex::set(System::UInt64 value) { - this->connectionIndexField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ NodeConnectionInfoExStructType::DeviceDescriptor::get() { - return this->deviceDescriptorField; - } - inline System::Void NodeConnectionInfoExStructType::DeviceDescriptor::set(Microsoft::Kits::Samples::Usb::UsbDeviceDescriptorType^ value) { - this->deviceDescriptorField = value; - } - - inline System::Byte NodeConnectionInfoExStructType::CurrentConfigurationValue::get() { - return this->currentConfigurationValueField; - } - inline System::Void NodeConnectionInfoExStructType::CurrentConfigurationValue::set(System::Byte value) { - this->currentConfigurationValueField = value; - } - - inline System::Byte NodeConnectionInfoExStructType::Speed::get() { - return this->speedField; - } - inline System::Void NodeConnectionInfoExStructType::Speed::set(System::Byte value) { - this->speedField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType NodeConnectionInfoExStructType::SpeedStr::get() { - return this->speedStrField; - } - inline System::Void NodeConnectionInfoExStructType::SpeedStr::set(Microsoft::Kits::Samples::Usb::UsbConnectionSpeedType value) { - this->speedStrField = value; - } - - inline System::Boolean NodeConnectionInfoExStructType::DeviceIsHub::get() { - return this->deviceIsHubField; - } - inline System::Void NodeConnectionInfoExStructType::DeviceIsHub::set(System::Boolean value) { - this->deviceIsHubField = value; - } - - inline System::Byte NodeConnectionInfoExStructType::DeviceAddress::get() { - return this->deviceAddressField; - } - inline System::Void NodeConnectionInfoExStructType::DeviceAddress::set(System::Byte value) { - this->deviceAddressField = value; - } - - inline System::UInt64 NodeConnectionInfoExStructType::NumOfOpenPipes::get() { - return this->numOfOpenPipesField; - } - inline System::Void NodeConnectionInfoExStructType::NumOfOpenPipes::set(System::UInt64 value) { - this->numOfOpenPipesField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbConnectionStatusType NodeConnectionInfoExStructType::UsbConnectionStatus::get() { - return this->usbConnectionStatusField; - } - inline System::Void NodeConnectionInfoExStructType::UsbConnectionStatus::set(Microsoft::Kits::Samples::Usb::UsbConnectionStatusType value) { - this->usbConnectionStatusField = value; - } - - inline Microsoft::Kits::Samples::Usb::DevicePowerStateType NodeConnectionInfoExStructType::DevicePowerState::get() { - return this->devicePowerStateField; - } - inline System::Void NodeConnectionInfoExStructType::DevicePowerState::set(Microsoft::Kits::Samples::Usb::DevicePowerStateType value) { - this->devicePowerStateField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ NodeConnectionInfoExStructType::Pipe::get() { - return this->pipeField; - } - inline System::Void NodeConnectionInfoExStructType::Pipe::set(cli::array< Microsoft::Kits::Samples::Usb::UsbPipeInfoType^ >^ value) { - this->pipeField = value; - } - - - inline System::Byte UsbDeviceDescriptorType::Length::get() { - return this->lengthField; - } - inline System::Void UsbDeviceDescriptorType::Length::set(System::Byte value) { - this->lengthField = value; - } - - inline System::Byte UsbDeviceDescriptorType::DescriptorType::get() { - return this->descriptorTypeField; - } - inline System::Void UsbDeviceDescriptorType::DescriptorType::set(System::Byte value) { - this->descriptorTypeField = value; - } - - inline System::UInt16 UsbDeviceDescriptorType::CdUSB::get() { - return this->cdUSBField; - } - inline System::Void UsbDeviceDescriptorType::CdUSB::set(System::UInt16 value) { - this->cdUSBField = value; - } - - inline System::Byte UsbDeviceDescriptorType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void UsbDeviceDescriptorType::DeviceClass::set(System::Byte value) { - this->deviceClassField = value; - } - - inline System::Byte UsbDeviceDescriptorType::DeviceSubclass::get() { - return this->deviceSubclassField; - } - inline System::Void UsbDeviceDescriptorType::DeviceSubclass::set(System::Byte value) { - this->deviceSubclassField = value; - } - - inline System::Byte UsbDeviceDescriptorType::DeviceProtocol::get() { - return this->deviceProtocolField; - } - inline System::Void UsbDeviceDescriptorType::DeviceProtocol::set(System::Byte value) { - this->deviceProtocolField = value; - } - - inline System::Byte UsbDeviceDescriptorType::MaxPacketSize0::get() { - return this->maxPacketSize0Field; - } - inline System::Void UsbDeviceDescriptorType::MaxPacketSize0::set(System::Byte value) { - this->maxPacketSize0Field = value; - } - - inline System::UInt16 UsbDeviceDescriptorType::IdVendor::get() { - return this->idVendorField; - } - inline System::Void UsbDeviceDescriptorType::IdVendor::set(System::UInt16 value) { - this->idVendorField = value; - } - - inline System::UInt16 UsbDeviceDescriptorType::IdProduct::get() { - return this->idProductField; - } - inline System::Void UsbDeviceDescriptorType::IdProduct::set(System::UInt16 value) { - this->idProductField = value; - } - - inline System::UInt16 UsbDeviceDescriptorType::CdDevice::get() { - return this->cdDeviceField; - } - inline System::Void UsbDeviceDescriptorType::CdDevice::set(System::UInt16 value) { - this->cdDeviceField = value; - } - - inline System::Byte UsbDeviceDescriptorType::IManufacturer::get() { - return this->iManufacturerField; - } - inline System::Void UsbDeviceDescriptorType::IManufacturer::set(System::Byte value) { - this->iManufacturerField = value; - } - - inline System::Byte UsbDeviceDescriptorType::IProduct::get() { - return this->iProductField; - } - inline System::Void UsbDeviceDescriptorType::IProduct::set(System::Byte value) { - this->iProductField = value; - } - - inline System::Byte UsbDeviceDescriptorType::ISerialNumber::get() { - return this->iSerialNumberField; - } - inline System::Void UsbDeviceDescriptorType::ISerialNumber::set(System::Byte value) { - this->iSerialNumberField = value; - } - - inline System::Byte UsbDeviceDescriptorType::NumConfigurations::get() { - return this->numConfigurationsField; - } - inline System::Void UsbDeviceDescriptorType::NumConfigurations::set(System::Byte value) { - this->numConfigurationsField = value; - } - - - inline Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ UsbPipeInfoType::EndpointDescriptor::get() { - return this->endpointDescriptorField; - } - inline System::Void UsbPipeInfoType::EndpointDescriptor::set(Microsoft::Kits::Samples::Usb::EndpointDescriptorType^ value) { - this->endpointDescriptorField = value; - } - - inline System::UInt64 UsbPipeInfoType::ScheduleOffset::get() { - return this->scheduleOffsetField; - } - inline System::Void UsbPipeInfoType::ScheduleOffset::set(System::UInt64 value) { - this->scheduleOffsetField = value; - } - - - inline System::String^ UsbDeviceClassDetailsType::DeviceType::get() { - return this->deviceTypeField; - } - inline System::Void UsbDeviceClassDetailsType::DeviceType::set(System::String^ value) { - this->deviceTypeField = value; - } - - inline System::String^ UsbDeviceClassDetailsType::DeviceTypeError::get() { - return this->deviceTypeErrorField; - } - inline System::Void UsbDeviceClassDetailsType::DeviceTypeError::set(System::String^ value) { - this->deviceTypeErrorField = value; - } - - inline System::String^ UsbDeviceClassDetailsType::SubclassType::get() { - return this->subclassTypeField; - } - inline System::Void UsbDeviceClassDetailsType::SubclassType::set(System::String^ value) { - this->subclassTypeField = value; - } - - inline System::String^ UsbDeviceClassDetailsType::SubclassTypeError::get() { - return this->subclassTypeErrorField; - } - inline System::Void UsbDeviceClassDetailsType::SubclassTypeError::set(System::String^ value) { - this->subclassTypeErrorField = value; - } - - inline System::String^ UsbDeviceClassDetailsType::DeviceProtocol::get() { - return this->deviceProtocolField; - } - inline System::Void UsbDeviceClassDetailsType::DeviceProtocol::set(System::String^ value) { - this->deviceProtocolField = value; - } - - inline System::String^ UsbDeviceClassDetailsType::DeviceProtocolError::get() { - return this->deviceProtocolErrorField; - } - inline System::Void UsbDeviceClassDetailsType::DeviceProtocolError::set(System::String^ value) { - this->deviceProtocolErrorField = value; - } - - inline System::UInt32 UsbDeviceClassDetailsType::UvcVersion::get() { - return this->uvcVersionField; - } - inline System::Void UsbDeviceClassDetailsType::UvcVersion::set(System::UInt32 value) { - this->uvcVersionField = value; - } - - - inline Microsoft::Kits::Samples::Usb::HubNodeInformationType^ ExternalHubType::HubNodeInformation::get() { - return this->hubNodeInformationField; - } - inline System::Void ExternalHubType::HubNodeInformation::set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value) { - this->hubNodeInformationField = value; - } - - inline System::String^ ExternalHubType::HubName::get() { - return this->hubNameField; - } - inline System::Void ExternalHubType::HubName::set(System::String^ value) { - this->hubNameField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubInformationExType^ ExternalHubType::HubInformationEx::get() { - return this->hubInformationExField; - } - inline System::Void ExternalHubType::HubInformationEx::set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value) { - this->hubInformationExField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ ExternalHubType::HubCapabilityEx::get() { - return this->hubCapabilityExField; - } - inline System::Void ExternalHubType::HubCapabilityEx::set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value) { - this->hubCapabilityExField = value; - } - - inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ ExternalHubType::ConnectionInfo::get() { - return this->connectionInfoField; - } - inline System::Void ExternalHubType::ConnectionInfo::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExType^ value) { - this->connectionInfoField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ ExternalHubType::UsbDevice::get() { - return this->usbDeviceField; - } - inline System::Void ExternalHubType::UsbDevice::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value) { - this->usbDeviceField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ ExternalHubType::NoDevice::get() { - return this->noDeviceField; - } - inline System::Void ExternalHubType::NoDevice::set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value) { - this->noDeviceField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ ExternalHubType::DeviceConfiguration::get() { - return this->deviceConfigurationField; - } - inline System::Void ExternalHubType::DeviceConfiguration::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceConfigurationType^ >^ value) { - this->deviceConfigurationField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ ExternalHubType::BosDescriptor::get() { - return this->bosDescriptorField; - } - inline System::Void ExternalHubType::BosDescriptor::set(Microsoft::Kits::Samples::Usb::UsbBosDescriptorType^ value) { - this->bosDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ ExternalHubType::ConnectionInfoV2::get() { - return this->connectionInfoV2Field; - } - inline System::Void ExternalHubType::ConnectionInfoV2::set(Microsoft::Kits::Samples::Usb::NodeConnectionInfoExV2Type^ value) { - this->connectionInfoV2Field = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ ExternalHubType::ExternalHub::get() { - return this->externalHubField; - } - inline System::Void ExternalHubType::ExternalHub::set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value) { - this->externalHubField = value; - } - - inline Microsoft::Kits::Samples::Usb::PortConnectorType^ ExternalHubType::PortConnector::get() { - return this->portConnectorField; - } - inline System::Void ExternalHubType::PortConnector::set(Microsoft::Kits::Samples::Usb::PortConnectorType^ value) { - this->portConnectorField = value; - } - - inline System::String^ ExternalHubType::ServiceName::get() { - return this->serviceNameField; - } - inline System::Void ExternalHubType::ServiceName::set(System::String^ value) { - this->serviceNameField = value; - } - - inline System::String^ ExternalHubType::HwId::get() { - return this->hwIdField; - } - inline System::Void ExternalHubType::HwId::set(System::String^ value) { - this->hwIdField = value; - } - - inline System::String^ ExternalHubType::DeviceId::get() { - return this->deviceIdField; - } - inline System::Void ExternalHubType::DeviceId::set(System::String^ value) { - this->deviceIdField = value; - } - - inline System::String^ ExternalHubType::DeviceName::get() { - return this->deviceNameField; - } - inline System::Void ExternalHubType::DeviceName::set(System::String^ value) { - this->deviceNameField = value; - } - - inline System::String^ ExternalHubType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void ExternalHubType::DeviceClass::set(System::String^ value) { - this->deviceClassField = value; - } - - inline System::String^ ExternalHubType::UsbProtocol::get() { - return this->usbProtocolField; - } - inline System::Void ExternalHubType::UsbProtocol::set(System::String^ value) { - this->usbProtocolField = value; - } - - - inline Microsoft::Kits::Samples::Usb::HubNodeType HubNodeInformationType::HubNode::get() { - return this->hubNodeField; - } - inline System::Void HubNodeInformationType::HubNode::set(Microsoft::Kits::Samples::Usb::HubNodeType value) { - this->hubNodeField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubInformationType^ HubNodeInformationType::HubInformation::get() { - return this->hubInformationField; - } - inline System::Void HubNodeInformationType::HubInformation::set(Microsoft::Kits::Samples::Usb::HubInformationType^ value) { - this->hubInformationField = value; - } - - inline System::UInt64 HubNodeInformationType::MiParentNumberOfInterfaces::get() { - return this->miParentNumberOfInterfacesField; - } - inline System::Void HubNodeInformationType::MiParentNumberOfInterfaces::set(System::UInt64 value) { - this->miParentNumberOfInterfacesField = value; - } - - - inline System::Boolean HubInformationType::IsRootHub::get() { - return this->isRootHubField; - } - inline System::Void HubInformationType::IsRootHub::set(System::Boolean value) { - this->isRootHubField = value; - } - - inline System::Boolean HubInformationType::IsBusPowered::get() { - return this->isBusPoweredField; - } - inline System::Void HubInformationType::IsBusPowered::set(System::Boolean value) { - this->isBusPoweredField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubInformationType::HubDescriptor::get() { - return this->hubDescriptorField; - } - inline System::Void HubInformationType::HubDescriptor::set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value) { - this->hubDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ HubInformationType::HubCharacteristics::get() { - return this->hubCharacteristicsField; - } - inline System::Void HubInformationType::HubCharacteristics::set(Microsoft::Kits::Samples::Usb::HubCharacteristicsType^ value) { - this->hubCharacteristicsField = value; - } - - - inline System::Byte HubDescriptorType::DescriptorLength::get() { - return this->descriptorLengthField; - } - inline System::Void HubDescriptorType::DescriptorLength::set(System::Byte value) { - this->descriptorLengthField = value; - } - - inline System::Byte HubDescriptorType::DescriptorType::get() { - return this->descriptorTypeField; - } - inline System::Void HubDescriptorType::DescriptorType::set(System::Byte value) { - this->descriptorTypeField = value; - } - - inline System::Byte HubDescriptorType::NumberOfPorts::get() { - return this->numberOfPortsField; - } - inline System::Void HubDescriptorType::NumberOfPorts::set(System::Byte value) { - this->numberOfPortsField = value; - } - - inline System::Byte HubDescriptorType::PowerOntoPowerGood::get() { - return this->powerOntoPowerGoodField; - } - inline System::Void HubDescriptorType::PowerOntoPowerGood::set(System::Byte value) { - this->powerOntoPowerGoodField = value; - } - - inline System::Byte HubDescriptorType::HubControlCurrent::get() { - return this->hubControlCurrentField; - } - inline System::Void HubDescriptorType::HubControlCurrent::set(System::Byte value) { - this->hubControlCurrentField = value; - } - - - inline System::UInt32 HubCharacteristicsType::HubCharacteristicsValue::get() { - return this->hubCharacteristicsValueField; - } - inline System::Void HubCharacteristicsType::HubCharacteristicsValue::set(System::UInt32 value) { - this->hubCharacteristicsValueField = value; - } - - inline System::String^ HubCharacteristicsType::PowerSwitching::get() { - return this->powerSwitchingField; - } - inline System::Void HubCharacteristicsType::PowerSwitching::set(System::String^ value) { - this->powerSwitchingField = value; - } - - inline System::Boolean HubCharacteristicsType::CompoundDevice::get() { - return this->compoundDeviceField; - } - inline System::Void HubCharacteristicsType::CompoundDevice::set(System::Boolean value) { - this->compoundDeviceField = value; - } - - inline System::String^ HubCharacteristicsType::OverCurrentProtection::get() { - return this->overCurrentProtectionField; - } - inline System::Void HubCharacteristicsType::OverCurrentProtection::set(System::String^ value) { - this->overCurrentProtectionField = value; - } - - - inline Microsoft::Kits::Samples::Usb::HubTypeType HubInformationExType::HubType::get() { - return this->hubTypeField; - } - inline System::Void HubInformationExType::HubType::set(Microsoft::Kits::Samples::Usb::HubTypeType value) { - this->hubTypeField = value; - } - - inline System::UInt16 HubInformationExType::HighestPortNumber::get() { - return this->highestPortNumberField; - } - inline System::Void HubInformationExType::HighestPortNumber::set(System::UInt16 value) { - this->highestPortNumberField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubDescriptorType^ HubInformationExType::HubDescriptor::get() { - return this->hubDescriptorField; - } - inline System::Void HubInformationExType::HubDescriptor::set(Microsoft::Kits::Samples::Usb::HubDescriptorType^ value) { - this->hubDescriptorField = value; - } - - inline Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ HubInformationExType::Hub30Descriptor::get() { - return this->hub30DescriptorField; - } - inline System::Void HubInformationExType::Hub30Descriptor::set(Microsoft::Kits::Samples::Usb::Hub30DescriptorType^ value) { - this->hub30DescriptorField = value; - } - - - inline System::Byte Hub30DescriptorType::Length::get() { - return this->lengthField; - } - inline System::Void Hub30DescriptorType::Length::set(System::Byte value) { - this->lengthField = value; - } - - inline System::Byte Hub30DescriptorType::DescriptorType::get() { - return this->descriptorTypeField; - } - inline System::Void Hub30DescriptorType::DescriptorType::set(System::Byte value) { - this->descriptorTypeField = value; - } - - inline System::Byte Hub30DescriptorType::NumberOfPorts::get() { - return this->numberOfPortsField; - } - inline System::Void Hub30DescriptorType::NumberOfPorts::set(System::Byte value) { - this->numberOfPortsField = value; - } - - inline System::UInt16 Hub30DescriptorType::HubCharacteristics::get() { - return this->hubCharacteristicsField; - } - inline System::Void Hub30DescriptorType::HubCharacteristics::set(System::UInt16 value) { - this->hubCharacteristicsField = value; - } - - inline System::Byte Hub30DescriptorType::PowerOntoPowerGood::get() { - return this->powerOntoPowerGoodField; - } - inline System::Void Hub30DescriptorType::PowerOntoPowerGood::set(System::Byte value) { - this->powerOntoPowerGoodField = value; - } - - inline System::Byte Hub30DescriptorType::HubControlCurrent::get() { - return this->hubControlCurrentField; - } - inline System::Void Hub30DescriptorType::HubControlCurrent::set(System::Byte value) { - this->hubControlCurrentField = value; - } - - inline System::Byte Hub30DescriptorType::HubHdrDecLat::get() { - return this->hubHdrDecLatField; - } - inline System::Void Hub30DescriptorType::HubHdrDecLat::set(System::Byte value) { - this->hubHdrDecLatField = value; - } - - inline System::UInt16 Hub30DescriptorType::HubDelay::get() { - return this->hubDelayField; - } - inline System::Void Hub30DescriptorType::HubDelay::set(System::UInt16 value) { - this->hubDelayField = value; - } - - inline System::UInt16 Hub30DescriptorType::DeviceRemovable::get() { - return this->deviceRemovableField; - } - inline System::Void Hub30DescriptorType::DeviceRemovable::set(System::UInt16 value) { - this->deviceRemovableField = value; - } - - - inline System::Boolean HubCapabilitiesExType::HubIsHighSpeedCapable::get() { - return this->hubIsHighSpeedCapableField; - } - inline System::Void HubCapabilitiesExType::HubIsHighSpeedCapable::set(System::Boolean value) { - this->hubIsHighSpeedCapableField = value; - } - - inline System::Boolean HubCapabilitiesExType::HubIsHighSpeed::get() { - return this->hubIsHighSpeedField; - } - inline System::Void HubCapabilitiesExType::HubIsHighSpeed::set(System::Boolean value) { - this->hubIsHighSpeedField = value; - } - - inline System::Boolean HubCapabilitiesExType::HubIsMultiTtCapable::get() { - return this->hubIsMultiTtCapableField; - } - inline System::Void HubCapabilitiesExType::HubIsMultiTtCapable::set(System::Boolean value) { - this->hubIsMultiTtCapableField = value; - } - - inline System::Boolean HubCapabilitiesExType::HubIsMultiTt::get() { - return this->hubIsMultiTtField; - } - inline System::Void HubCapabilitiesExType::HubIsMultiTt::set(System::Boolean value) { - this->hubIsMultiTtField = value; - } - - inline System::Boolean HubCapabilitiesExType::HubIsRoot::get() { - return this->hubIsRootField; - } - inline System::Void HubCapabilitiesExType::HubIsRoot::set(System::Boolean value) { - this->hubIsRootField = value; - } - - inline System::Boolean HubCapabilitiesExType::HubIsArmedWakeOnConnect::get() { - return this->hubIsArmedWakeOnConnectField; - } - inline System::Void HubCapabilitiesExType::HubIsArmedWakeOnConnect::set(System::Boolean value) { - this->hubIsArmedWakeOnConnectField = value; - } - - inline System::Boolean HubCapabilitiesExType::HubIsBusPowered::get() { - return this->hubIsBusPoweredField; - } - inline System::Void HubCapabilitiesExType::HubIsBusPowered::set(System::Boolean value) { - this->hubIsBusPoweredField = value; - } - - - inline Microsoft::Kits::Samples::Usb::HubNodeInformationType^ RootHubType::HubNodeInformation::get() { - return this->hubNodeInformationField; - } - inline System::Void RootHubType::HubNodeInformation::set(Microsoft::Kits::Samples::Usb::HubNodeInformationType^ value) { - this->hubNodeInformationField = value; - } - - inline System::String^ RootHubType::HubName::get() { - return this->hubNameField; - } - inline System::Void RootHubType::HubName::set(System::String^ value) { - this->hubNameField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubInformationExType^ RootHubType::HubInformationEx::get() { - return this->hubInformationExField; - } - inline System::Void RootHubType::HubInformationEx::set(Microsoft::Kits::Samples::Usb::HubInformationExType^ value) { - this->hubInformationExField = value; - } - - inline Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ RootHubType::HubCapabilityEx::get() { - return this->hubCapabilityExField; - } - inline System::Void RootHubType::HubCapabilityEx::set(Microsoft::Kits::Samples::Usb::HubCapabilitiesExType^ value) { - this->hubCapabilityExField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ RootHubType::ExternalHub::get() { - return this->externalHubField; - } - inline System::Void RootHubType::ExternalHub::set(cli::array< Microsoft::Kits::Samples::Usb::ExternalHubType^ >^ value) { - this->externalHubField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ RootHubType::UsbDevice::get() { - return this->usbDeviceField; - } - inline System::Void RootHubType::UsbDevice::set(cli::array< Microsoft::Kits::Samples::Usb::UsbDeviceType^ >^ value) { - this->usbDeviceField = value; - } - - inline cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ RootHubType::NoDevice::get() { - return this->noDeviceField; - } - inline System::Void RootHubType::NoDevice::set(cli::array< Microsoft::Kits::Samples::Usb::NoDeviceType^ >^ value) { - this->noDeviceField = value; - } - - inline System::String^ RootHubType::ServiceName::get() { - return this->serviceNameField; - } - inline System::Void RootHubType::ServiceName::set(System::String^ value) { - this->serviceNameField = value; - } - - inline System::String^ RootHubType::HwId::get() { - return this->hwIdField; - } - inline System::Void RootHubType::HwId::set(System::String^ value) { - this->hwIdField = value; - } - - inline System::String^ RootHubType::DeviceId::get() { - return this->deviceIdField; - } - inline System::Void RootHubType::DeviceId::set(System::String^ value) { - this->deviceIdField = value; - } - - inline System::String^ RootHubType::DeviceName::get() { - return this->deviceNameField; - } - inline System::Void RootHubType::DeviceName::set(System::String^ value) { - this->deviceNameField = value; - } - - inline System::String^ RootHubType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void RootHubType::DeviceClass::set(System::String^ value) { - this->deviceClassField = value; - } - - inline System::String^ RootHubType::UsbProtocol::get() { - return this->usbProtocolField; - } - inline System::Void RootHubType::UsbProtocol::set(System::String^ value) { - this->usbProtocolField = value; - } - - - inline System::String^ UsbHCPowerStateType::SystemState::get() { - return this->systemStateField; - } - inline System::Void UsbHCPowerStateType::SystemState::set(System::String^ value) { - this->systemStateField = value; - } - - inline System::String^ UsbHCPowerStateType::HostControllerState::get() { - return this->hostControllerStateField; - } - inline System::Void UsbHCPowerStateType::HostControllerState::set(System::String^ value) { - this->hostControllerStateField = value; - } - - inline System::String^ UsbHCPowerStateType::HubState::get() { - return this->hubStateField; - } - inline System::Void UsbHCPowerStateType::HubState::set(System::String^ value) { - this->hubStateField = value; - } - - inline System::Boolean UsbHCPowerStateType::CanWakeUp::get() { - return this->canWakeUpField; - } - inline System::Void UsbHCPowerStateType::CanWakeUp::set(System::Boolean value) { - this->canWakeUpField = value; - } - - inline System::Boolean UsbHCPowerStateType::IsPowered::get() { - return this->isPoweredField; - } - inline System::Void UsbHCPowerStateType::IsPowered::set(System::Boolean value) { - this->isPoweredField = value; - } - - - inline cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ UsbHCPowerStateMappingType::PowerMap::get() { - return this->powerMapField; - } - inline System::Void UsbHCPowerStateMappingType::PowerMap::set(cli::array< Microsoft::Kits::Samples::Usb::UsbHCPowerStateType^ >^ value) { - this->powerMapField = value; - } - - inline System::String^ UsbHCPowerStateMappingType::LastSleepState::get() { - return this->lastSleepStateField; - } - inline System::Void UsbHCPowerStateMappingType::LastSleepState::set(System::String^ value) { - this->lastSleepStateField = value; - } - - - inline System::Int64 UsbHCDeviceInfoType::VendorId::get() { - return this->vendorIdField; - } - inline System::Void UsbHCDeviceInfoType::VendorId::set(System::Int64 value) { - this->vendorIdField = value; - } - - inline System::Int64 UsbHCDeviceInfoType::DeviceId::get() { - return this->deviceIdField; - } - inline System::Void UsbHCDeviceInfoType::DeviceId::set(System::Int64 value) { - this->deviceIdField = value; - } - - inline System::String^ UsbHCDeviceInfoType::DriverKey::get() { - return this->driverKeyField; - } - inline System::Void UsbHCDeviceInfoType::DriverKey::set(System::String^ value) { - this->driverKeyField = value; - } - - inline System::Int64 UsbHCDeviceInfoType::SubSysId::get() { - return this->subSysIdField; - } - inline System::Void UsbHCDeviceInfoType::SubSysId::set(System::Int64 value) { - this->subSysIdField = value; - } - - inline System::Int64 UsbHCDeviceInfoType::Revision::get() { - return this->revisionField; - } - inline System::Void UsbHCDeviceInfoType::Revision::set(System::Int64 value) { - this->revisionField = value; - } - - inline System::UInt64 UsbHCDeviceInfoType::DebugPort::get() { - return this->debugPortField; - } - inline System::Void UsbHCDeviceInfoType::DebugPort::set(System::UInt64 value) { - this->debugPortField = value; - } - - inline System::UInt64 UsbHCDeviceInfoType::NumberOfRootPorts::get() { - return this->numberOfRootPortsField; - } - inline System::Void UsbHCDeviceInfoType::NumberOfRootPorts::set(System::UInt64 value) { - this->numberOfRootPortsField = value; - } - - inline System::UInt64 UsbHCDeviceInfoType::ControllerFlavor::get() { - return this->controllerFlavorField; - } - inline System::Void UsbHCDeviceInfoType::ControllerFlavor::set(System::UInt64 value) { - this->controllerFlavorField = value; - } - - inline System::String^ UsbHCDeviceInfoType::ControllerFlavorString::get() { - return this->controllerFlavorStringField; - } - inline System::Void UsbHCDeviceInfoType::ControllerFlavorString::set(System::String^ value) { - this->controllerFlavorStringField = value; - } - - inline System::Boolean UsbHCDeviceInfoType::PortSwitchingEnabled::get() { - return this->portSwitchingEnabledField; - } - inline System::Void UsbHCDeviceInfoType::PortSwitchingEnabled::set(System::Boolean value) { - this->portSwitchingEnabledField = value; - } - - inline System::Boolean UsbHCDeviceInfoType::SelectiveSuspendEnabled::get() { - return this->selectiveSuspendEnabledField; - } - inline System::Void UsbHCDeviceInfoType::SelectiveSuspendEnabled::set(System::Boolean value) { - this->selectiveSuspendEnabledField = value; - } - - inline System::UInt64 UsbHCDeviceInfoType::LegacyBios::get() { - return this->legacyBiosField; - } - inline System::Void UsbHCDeviceInfoType::LegacyBios::set(System::UInt64 value) { - this->legacyBiosField = value; - } - - - inline Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ HostControllerType::ControllerInfo::get() { - return this->controllerInfoField; - } - inline System::Void HostControllerType::ControllerInfo::set(Microsoft::Kits::Samples::Usb::UsbHCDeviceInfoType^ value) { - this->controllerInfoField = value; - } - - inline Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ HostControllerType::PowerMapping::get() { - return this->powerMappingField; - } - inline System::Void HostControllerType::PowerMapping::set(Microsoft::Kits::Samples::Usb::UsbHCPowerStateMappingType^ value) { - this->powerMappingField = value; - } - - inline Microsoft::Kits::Samples::Usb::RootHubType^ HostControllerType::RootHub::get() { - return this->rootHubField; - } - inline System::Void HostControllerType::RootHub::set(Microsoft::Kits::Samples::Usb::RootHubType^ value) { - this->rootHubField = value; - } - - inline System::String^ HostControllerType::ServiceName::get() { - return this->serviceNameField; - } - inline System::Void HostControllerType::ServiceName::set(System::String^ value) { - this->serviceNameField = value; - } - - inline System::String^ HostControllerType::HwId::get() { - return this->hwIdField; - } - inline System::Void HostControllerType::HwId::set(System::String^ value) { - this->hwIdField = value; - } - - inline System::String^ HostControllerType::DeviceId::get() { - return this->deviceIdField; - } - inline System::Void HostControllerType::DeviceId::set(System::String^ value) { - this->deviceIdField = value; - } - - inline System::String^ HostControllerType::DeviceName::get() { - return this->deviceNameField; - } - inline System::Void HostControllerType::DeviceName::set(System::String^ value) { - this->deviceNameField = value; - } - - inline System::String^ HostControllerType::DeviceClass::get() { - return this->deviceClassField; - } - inline System::Void HostControllerType::DeviceClass::set(System::String^ value) { - this->deviceClassField = value; - } - - inline System::String^ HostControllerType::UsbProtocol::get() { - return this->usbProtocolField; - } - inline System::Void HostControllerType::UsbProtocol::set(System::String^ value) { - this->usbProtocolField = value; - } - } - } - } -} - diff --git a/tests/projects/winsdk/usbview/usbviddesc.h b/tests/projects/winsdk/usbview/usbviddesc.h deleted file mode 100644 index f5a17164f..000000000 --- a/tests/projects/winsdk/usbview/usbviddesc.h +++ /dev/null @@ -1,743 +0,0 @@ -/*++ - -Copyright (c) 2002-2003 Microsoft Corporation - -Module Name: - - USBVIDDESC.H - -Abstract: - - This is a header file for USB Video Class Specific descriptors which are not yet in - a standard system header file. - -Environment: - - user mode - -Revision History: - - 11-20-2002 : created - 03-28-2003 : major updates to support latest UVC specs - ---*/ - -#pragma pack(push, 1) - -/***************************************************************************** - D E F I N E S -*****************************************************************************/ - -//global version for USB Video Class spec version -#define BCDVDC 0x0083 - -// -// USB Device Class Definition for Video Devices v8.c -// Appendix A. Video Device Class Codes -// - -// A.1 Video Interface Class Code -//TBD Normally would be in USB100.h but not official yet -#define USB_DEVICE_CLASS_VIDEO 0x0E -#define USB_DEVICE_CLASS_VIDEO_PRERELEASE 0xFF -//CC_VIDEO in spec. The rest of the codes will be USB_VIDEO plus text from spec codes - -// A.2 Video Interface Subclass Codes -// -#define USB_VIDEO_SC_UNDEFINED 0x00 -#define USB_VIDEO_SC_VIDEOCONTROL 0x01 -#define USB_VIDEO_SC_VIDEOSTREAMING 0x02 -#define USB_VIDEO_SC_VIDEO_INTERFACE_COLLECTION 0x03 - -// A.3 Video Interface Protocol Codes -// -#define USB_VIDEO_PC_PROTOCOL_UNDEFINED 0x00 - -// A.4 Video Class-Specific Descriptor Types -// -#define USB_VIDEO_CS_UNDEFINED 0x20 -#define USB_VIDEO_CS_DEVICE 0x21 -#define USB_VIDEO_CS_CONFIGURATION 0x22 -#define USB_VIDEO_CS_STRING 0x23 -#define USB_VIDEO_CS_INTERFACE 0x24 -#define USB_VIDEO_CS_ENDPOINT 0x25 - -// A.5 Video Class-Specific VC (Video Control) Interface Descriptor Subtypes -// -#define USB_VIDEO_VC_DESCRIPTOR_UNDEFINED 0x00 -#define USB_VIDEO_VC_HEADER 0x01 -#define USB_VIDEO_VC_INPUT_TERMINAL 0x02 -#define USB_VIDEO_VC_OUTPUT_TERMINAL 0x03 -#define USB_VIDEO_VC_SELECTOR_UNIT 0x04 -#define USB_VIDEO_VC_PROCESSING_UNIT 0x05 -#define USB_VIDEO_VC_EXTENSION_UNIT 0x06 - -// A.6 Video Class-Specific VS (Video Streaming) Interface Descriptor Subtypes -// -#define USB_VIDEO_VS_UNDEFINED 0x00 -#define USB_VIDEO_VS_INPUT_HEADER 0x01 -#define USB_VIDEO_VS_OUTPUT_HEADER 0x02 -#define USB_VIDEO_VS_STILL_IMAGE_FRAME 0x03 -#define USB_VIDEO_VS_FORMAT_UNCOMPRESSED 0x04 -#define USB_VIDEO_VS_FRAME_UNCOMPRESSED 0x05 -#define USB_VIDEO_VS_FORMAT_MJPEG 0x06 -#define USB_VIDEO_VS_FRAME_MJPEG 0x07 -#define USB_VIDEO_VS_FORMAT_MPEG1 0x08 -#define USB_VIDEO_VS_FORMAT_MPEG2PS 0x09 -#define USB_VIDEO_VS_FORMAT_MPEG2TS 0x0A -#define USB_VIDEO_VS_FORMAT_MPEG4SL 0x0B -#define USB_VIDEO_VS_FORMAT_DV 0x0C -#define USB_VIDEO_VS_COLORFORMAT 0x0D -#define USB_VIDEO_VS_FORMAT_VENDOR 0x0E -#define USB_VIDEO_VS_FRAME_VENDOR 0x0F - -// A.7 Video Class-Specific Endpoint Descriptor Subtypes -// -#define USB_VIDEO_EP_UNDEFINED 0x00 -#define USB_VIDEO_EP_GENERAL 0x01 -#define USB_VIDEO_EP_ENDPOINT 0x02 -#define USB_VIDEO_EP_INTERRUPT 0x03 - -// -// Below definitions only necessary if testing requests -// -// A.8 Video Class-Specific Request Codes -// -#define USB_VIDEO_RC_UNDEFINED 0x00 -#define USB_VIDEO_SET_CUR 0x01 -#define USB_VIDEO_GET_CUR 0x81 -#define USB_VIDEO_GET_MIN 0x82 -#define USB_VIDEO_GET_MAX 0x83 -#define USB_VIDEO_GET_RES 0x84 -#define USB_VIDEO_GET_LEN 0x85 -#define USB_VIDEO_GET_INFO 0x86 -#define USB_VIDEO_GET_DEF 0x87 - -// A.9 Control Selector Codes -// A.9.1 VideoControl Interface Control Selectors -#define USB_VIDEO_VC_UNDEFINED_CONTROL 0x00 -#define USB_VIDEO_VC_VIDEO_POWER_MODE_CONTROL 0x01 -#define USB_VIDEO_VC_REQUEST_ERROR_CODE_CONTROL 0x02 -#define USB_VIDEO_VC_INDICATE_HOST_CLOCK_CONTROL 0x03 - -//A.9.2 Terminal Control Selectors -// -#define USB_VIDEO_TE_CONTROL_UNDEFINED 0x00 - -//A.9.3 Selector Unit Control Selectors -// -#define USB_VIDEO_SU_CONTROL_UNDEFINED 0x00 -#define USB_VIDEO_SU_INPUT_SELECT_CONTROL 0x01 - -//A.9.4 Camera Terminal Control Selectors -// -#define USB_VIDEO_CT_CONTROL_UNDEFINED 0x00 -#define USB_VIDEO_CT_SCANNING_MODE_CONTROL 0x01 -#define USB_VIDEO_CT_AE_MODE_CONTROL 0x02 -#define USB_VIDEO_CT_AE_PRIORITY_CONTROL 0x03 -#define USB_VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 -#define USB_VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 -#define USB_VIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06 -#define USB_VIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07 -#define USB_VIDEO_CT_FOCUS_AUTO_CONTROL 0x08 -#define USB_VIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09 -#define USB_VIDEO_CT_IRIS_RELATIVE_CONTROL 0x0A -#define USB_VIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0B -#define USB_VIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0C -#define USB_VIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0D -#define USB_VIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0E -#define USB_VIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0F -#define USB_VIDEO_CT_ROLL_RELATIVE_CONTROL 0x10 - -//A.9.5 Processing Unit Control Selectors -// -#define USB_VIDEO_PU_CONTROL_UNDEFINED 0x04 -#define USB_VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 -#define USB_VIDEO_PU_BRIGHTNESS_CONTROL 0x02 -#define USB_VIDEO_PU_CONTRAST_CONTROL 0x03 -#define USB_VIDEO_PU_GAIN_CONTROL 0x04 -#define USB_VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 -#define USB_VIDEO_PU_HUE_CONTROL 0x06 -#define USB_VIDEO_PU_SATURATION_CONTROL 0x07 -#define USB_VIDEO_PU_SHARPNESS_CONTROL 0x08 -#define USB_VIDEO_PU_GAMMA_CONTROL 0x09 -#define USB_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A -#define USB_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B -#define USB_VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C -#define USB_VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D -#define USB_VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0E -#define USB_VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F -#define USB_VIDEO_PU_HUE_AUTO_CONTROL 0x10 - -//A.9.6 Extension Unit Control Selectors -// -#define USB_VIDEO_XU_CONTROL_UNDEFINED 0x00 - -//A.9.7 VideoStreaming Interface Control Selectors -// -#define USB_VIDEO_VS_CONTROL_UNDEFINED 0x00 -#define USB_VIDEO_VS_PROBE_CONTROL 0x01 -#define USB_VIDEO_VS_COMMIT_CONTROL 0x02 -#define USB_VIDEO_VS_STILL_PROBE_CONTROL 0x03 -#define USB_VIDEO_VS_STILL_COMMIT_CONTROL 0x04 -#define USB_VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 -#define USB_VIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06 -#define USB_VIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07 -#define USB_VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 -#define USB_VIDEO_VS_SYNCH_DELAY_CONTROL 0x09 - -#define TapeControls 0 -#define TransportModes 1 -#define CameraControls 2 -#define ProcessorControls 3 -#define InHeaderControls 4 - -/***************************************************************************** - T Y P E D E F S -*****************************************************************************/ - - -/***************************************************************************** - USB Device Class Definition for Video Devices v8.b -*****************************************************************************/ - -typedef struct _USB_VIDEO_COMMON_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; -} USB_VIDEO_COMMON_DESCRIPTOR, -*PUSB_VIDEO_COMMON_DESCRIPTOR; - -// 3.6.2 Class-Specific VC (Video Control) Interface Descriptor -// -typedef struct _USB_VIDEO_VC_INTERFACE_HEADER_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - USHORT bcdVDC; - USHORT wTotalLength; - ULONG32 dwClockFrequency; - UCHAR bInCollection; -// UCHAR baInterfaceNr; // variable length (0 minimum) -} USB_VIDEO_VC_INTERFACE_HEADER_DESCRIPTOR, -*PUSB_VIDEO_VC_INTERFACE_HEADER_DESCRIPTOR; - -// 3.6.2.1 Input Terminal Descriptor -// -typedef struct _USB_VIDEO_INPUT_TERMINAL_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR iTerminal; -} USB_VIDEO_INPUT_TERMINAL_DESCRIPTOR, -*PUSB_VIDEO_INPUT_TERMINAL_DESCRIPTOR; - -// 3.6.2.2 Output Terminal Descriptor -// -typedef struct _USB_VIDEO_OUTPUT_TERMINAL_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR bSourceID; - UCHAR iTerminal; -} USB_VIDEO_OUTPUT_TERMINAL_DESCRIPTOR, -*PUSB_VIDEO_OUTPUT_TERMINAL_DESCRIPTOR; - -// 3.6.2.3 Camera Unit Descriptor -// -typedef struct _USB_VIDEO_CAMERA_TERMINAL_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR iTerminal; - USHORT wObjectiveFocalLengthMin; - USHORT wObjectiveFocalLengthMax; - USHORT wOcularFocalLength; - UCHAR bControlSize; -// UCHAR bmControls; // variable length (0 min, 3 max) -} USB_VIDEO_CAMERA_TERMINAL_DESCRIPTOR, -*PUSB_VIDEO_CAMERA_TERMINAL_DESCRIPTOR; - -// 3.6.2.4 Selector Unit Descriptor -// -typedef struct _USB_VIDEO_SELECTOR_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - UCHAR bNrInPins; - UCHAR baSourceID; // variable length (1 minimum) - UCHAR iSelector; -} USB_VIDEO_SELECTOR_UNIT_DESCRIPTOR, -*PUSB_VIDEO_SELECTOR_UNIT_DESCRIPTOR; - -// 3.6.2.5 Processing Unit Descriptor -// -typedef struct _USB_VIDEO_PROCESSING_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - UCHAR bSourceID; - USHORT wMaxMultiplier; - UCHAR bControlSize; -// UCHAR bmControls; // variable length (0 minimum) - UCHAR iProcessing; -} USB_VIDEO_PROCESSING_UNIT_DESCRIPTOR, -*PUSB_VIDEO_PROCESSING_UNIT_DESCRIPTOR; - -// 3.6.2.6 Extension Unit Descriptor -// -typedef struct _USB_VIDEO_EXTENSION_UNIT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bUnitID; - GUID guidExtensionCode; - UCHAR bNumControls; - UCHAR bNrInPins; - UCHAR baSourceID; // variable length (1 minimum) -// UCHAR bControlSize; -// UCHAR bmControls; // variable length (0 minimum) -// UCHAR iExtension; -} USB_VIDEO_EXTENSION_UNIT_DESCRIPTOR, -*PUSB_VIDEO_EXTENSION_UNIT_DESCRIPTOR; - -// 3.7.2.2 Class-Specific VC Interrupt EndPoint Descriptor -// -typedef struct _USB_VIDEO_VC_INTERRUPT_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubType; - USHORT wMaxTransferSize; -} USB_VIDEO_VC_INTERRUPT_ENDPOINT_DESCRIPTOR, -*PUSB_VIDEO_VC_INTERRUPT_ENDPOINT_DESCRIPTOR; -// 3.8.2.1 Class-Specific Input Header Descriptor -// -typedef struct _USB_VIDEO_INPUT_HEADER_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bNumFormats; - USHORT wTotalLength; - UCHAR bEndpointAddress; - UCHAR bmInfo; - UCHAR bTerminalLink; - UCHAR bStillCaptureMethod; - UCHAR bTriggerSupport; - UCHAR bTriggerUsage; - UCHAR bControlSize; -// UCHAR bmaControls; // variable length (0 minimum) -} USB_VIDEO_INPUT_HEADER_DESCRIPTOR, -*PUSB_VIDEO_INPUT_HEADER_DESCRIPTOR; - -// 3.8.2.2 Class-Specific Output Header Descriptor -// -typedef struct _USB_VIDEO_OUTPUT_HEADER_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bNumFormats; - USHORT wTotalLength; - UCHAR bEndpointAddress; - UCHAR bTerminalLink; -} USB_VIDEO_OUTPUT_HEADER_DESCRIPTOR, -*PUSB_VIDEO_OUTPUT_HEADER_DESCRIPTOR; - -// 3.8.2.3 Payload Format Descriptors -//Payload Format Descriptor Document -//Uncompressed Video DWGVideo Payload Uncompressed 0.xx.doc -//MJPEG Video DWGVideo Payload MJPEG Format Ver0.xx.doc -//MPEG1 System Stream DWGVideo Payload MPEG1 System Stream, MPEG2-PS Format Ver0.xx.doc -//MPEG2 PS DWGVideo Payload MPEG1 System Stream, MPEG2-PS Format Ver0.xx.doc -//MPEG-2 TS DWGVideo Payload MPEG2TS Format Ver0.xx.doc -//MPEG-4 SL DWGVideo Payload MPEG4 SL format Ver0.xx.doc -//DV DWGVideo Payload DV Format Ver0.xx.doc - -// 3.8.2.4 Video Frame Descriptor -// -//Video Frame Descriptor Document -//Uncompressed DWGVideo Payload Uncompressed 0.xx.doc -//MJPEG DWGVideo Payload MJPEG Format Ver0.xx.doc - -// 3.8.2.5 Still Image Frame Descriptor -// -typedef struct _VIDEO_STILL_IMAGE { - USHORT wWidth; - USHORT wHeight; -} VIDEO_STILL_IMAGE, -*PVIDEO_STILL_IMAGE; - -typedef struct _USB_VIDEO_STILL_IMAGE_FRAME_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bEndpointAddress; - UCHAR bNumImageSizePatterns; - VIDEO_STILL_IMAGE dwStillImage; // variable count - UCHAR bNumCompressionPattern; - UCHAR bCompression; // variable count -} USB_VIDEO_STILL_IMAGE_FRAME_DESCRIPTOR, -*PUSB_VIDEO_STILL_IMAGE_FRAME_DESCRIPTOR; - -// 3.8.2.6 Color Matching Descriptor -// -typedef struct _USB_VIDEO_COLOR_MATCHING_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bColorPrimaries; - UCHAR bTransferCharacteristics; - UCHAR bMatrixCoefficients; -} USB_VIDEO_COLOR_MATCHING_DESCRIPTOR, -*PUSB_VIDEO_COLOR_MATCHING_DESCRIPTOR; -/* -// 3.9.1 Class-specific VC Interrupt Endpoint Descriptor -typedef struct _USB_VIDEO_VS_ENDPOINT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubType; - USHORT wMaxTransferSize; -} USB_VIDEO_VS_ENDPOINT_DESCRIPTOR, -*PUSB_VIDEO_VS_ENDPOINT_DESCRIPTOR; -*/ -// -// USB Device Class Definition for Video Devices: Uncompressed Payload 0.8a Draft Revision -// - -// 3.1.1 Uncompressed Video Format Descriptor -// -typedef struct _USB_VIDEO_UNCOMPRESSED_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - GUID guidFormat; - UCHAR bBitsPerPixel; - UCHAR bDefaultFrameIndex; - UCHAR bAspectRatioX; - UCHAR bAspectRatioY; - UCHAR bmInterlaceFlags; - UCHAR bCopyProtect; -} USB_VIDEO_UNCOMPRESSED_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_UNCOMPRESSED_FORMAT_DESCRIPTOR; - -// 3.1.2 Uncompressed Video Frame Descriptor Common -// -typedef struct _USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_COMMON { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; -} USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_COMMON, -*PUSB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_COMMON; - -// 3.1.2 Uncompressed Video Frame Descriptor - Continuous -// -typedef struct _USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_CONTINUOUS { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG32 dwMinFrameInterval; - ULONG32 dwMaxFrameInterval; - ULONG32 dwFrameIntervalStep; -} USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_CONTINUOUS, -*PUSB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_CONTINUOUS; - -// 3.1.2 Uncompressed Video Frame Descriptor - Discrete -// -typedef struct _USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_DISCRETE { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG32 dwFrameInterval; // variable count -} USB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_DISCRETE, -*PUSB_VIDEO_UNCOMPRESSED_FRAME_DESCRIPTOR_DISCRETE; - -// -// USB Device Class Definition for Video Devices: Motion-JPEG Payload 0.8a Draft Revision -// 3.1.1 MJPEG Video Format Descriptor -// -typedef struct _USB_VIDEO_MJPEG_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - UCHAR bmFlags; - UCHAR bDefaultFrameIndex; - UCHAR bAspectRatioX; - UCHAR bAspectRatioY; - UCHAR bmInterlaceFlags; - UCHAR bCopyProtect; -} USB_VIDEO_MJPEG_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_MJPEG_FORMAT_DESCRIPTOR; - -// 3.1.2 MJPEG Video Frame Descriptors Common -// -typedef struct _USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_COMMON { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; -} USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_COMMON, -*PUSB_VIDEO_MJPEG_FRAME_DESCRIPTOR_COMMON; - -// 3.1.2 MJPEG Video Frame Descriptors - Continuous -// -typedef struct _USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_CONTINUOUS { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG32 dwMinFrameInterval; - ULONG32 dwMaxFrameInterval; - ULONG32 dwFrameIntervalStep; -} USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_CONTINUOUS, -*PUSB_VIDEO_MJPEG_FRAME_DESCRIPTOR_CONTINUOUS; - -// 3.1.2 MJPEG Video Frame Descriptors -Discrete -// -typedef struct _USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_DISCRETE { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG32 dwFrameInterval; // variable count -} USB_VIDEO_MJPEG_FRAME_DESCRIPTOR_DISCRETE, -*PUSB_VIDEO_MJPEG_FRAME_DESCRIPTOR_DISCRETE; - -// -// USB Device Class Definition for Video Devices: MPEG1-SS, MPEG2-PS Payload 0.8a Draft Revision -// 3.1.1 MPEG1 System Stream Format Descriptor -// -typedef struct _USB_VIDEO_MPEG1_SS_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - USHORT wPacketLength; - USHORT wPackLength; - UCHAR bPackdataType; -} USB_VIDEO_MPEG1_SS_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_MPEG1_SS_FORMAT_DESCRIPTOR; - -// 3.1.2 MPEG2 PS Format Descriptor -// -typedef struct _USB_VIDEO_MPEG2_PS_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - USHORT wPacketLength; - USHORT wPackLength; - UCHAR bPackdataType; -} USB_VIDEO_MPEG2_PS_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_MPEG2_PS_FORMAT_DESCRIPTOR; - -// -// USB Device Class Definition for Video Devices: MPEG-2 TS Payload 0.8a Draft Revision -// 3.1.1 MPEG-2 TS Format Descriptor -// -typedef struct _USB_VIDEO_MPEG2_TS_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bDataOffset; - UCHAR bPacketLength; - UCHAR bStrideLength; -} USB_VIDEO_MPEG2_TS_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_MPEG2_TS_FORMAT_DESCRIPTOR; - -// -// USB Device Class Definition for Video Devices: MPEG4 SL Payload 0.8a Draft Revision -// 3.1.1 MPEG4 SL Format Descriptor -// -typedef struct _USB_VIDEO_MPEG4_SL_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - USHORT wPacketLength; -} USB_VIDEO_MPEG4_SL_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_MPEG4_SL_FORMAT_DESCRIPTOR; - -// USB Device Class Definition for Video Devices: DV Payload 0.8a Draft Revision -// 3.1.1 DV Format Descriptor -typedef struct _USB_VIDEO_DV_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - ULONG32 dwMaxVideoFrameBufferSize; - UCHAR bFormatType; -} USB_VIDEO_DV_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_DV_FORMAT_DESCRIPTOR; - -// USB Device Class Definition for Video Devices: Vendor Payload 0.8c Draft Revision -// 3.1.1 Vendor Video Format Descriptor -typedef struct _USB_VIDEO_VENDOR_VIDEO_FORMAT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - GUID guidMajorFormat; - GUID guidSubFormat; - GUID guidSpecifier; - UCHAR bPayloadClass; - UCHAR bDefaultFrameIndex; - UCHAR bCopyProtect; -} USB_VIDEO_VENDOR_VIDEO_FORMAT_DESCRIPTOR, -*PUSB_VIDEO_VENDOR_VIDEO_FORMAT_DESCRIPTOR; - -// USB Device Class Definition for Video Devices: Vendor Payload 0.8c Draft Revision -// 3.1.2 Vendor Video Frame Descriptor -typedef struct _USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_COMMON { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; -} USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_COMMON, -*PUSB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_COMMON; - -typedef struct _USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_CONTINUOUS { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG32 dwMinFrameInterval; - ULONG32 dwMaxFrameInterval; - ULONG32 dwFrameIntervalStep; -} USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_CONTINUOUS, -*PUSB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_CONTINUOUS; - -typedef struct _USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_DISCRETE { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG32 dwMinBitRate; - ULONG32 dwMaxBitRate; - ULONG32 dwMaxVideoFrameBufferSize; - ULONG32 dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG32 dwFrameInterval; // variable count -} USB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_DISCRETE, -*PUSB_VIDEO_VENDOR_VIDEO_FRAME_DESCRIPTOR_DISCRETE; - -// USB Device Class Definition for Video Devices: Media Transport Terminal 0.8a Draft Revision -// 3.1 Media Transport Input Descriptor -typedef struct _USB_VIDEO_MEDIA_TRANSPORT_INPUT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR iTerminal; - UCHAR bControlSize; - UCHAR bmControls; // variable size (min 1) -// UCHAR bTransportModeSize; // variable count (min 0) -// UCHAR bmTransportModes; // variable count (min 0) -} USB_VIDEO_MEDIA_TRANSPORT_INPUT_DESCRIPTOR, -*PUSB_VIDEO_MEDIA_TRANSPORT_INPUT_DESCRIPTOR; - -// 3.2 Media Transport Output Descriptor -typedef struct _USB_VIDEO_MEDIA_TRANSPORT_OUTPUT_DESCRIPTOR { - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bTerminalID; - USHORT wTerminalType; - UCHAR bAssocTerminal; - UCHAR bSourceID; - UCHAR iTerminal; - UCHAR bControlSize; - UCHAR bmControls; // variable size (min 1) -// UCHAR bTransportModeSize; // variable count (min 0) -// UCHAR bmTransportModes; // variable count (min 0) -} USB_VIDEO_MEDIA_TRANSPORT_OUTPUT_DESCRIPTOR, -*PUSB_VIDEO_MEDIA_TRANSPORT_OUTPUT_DESCRIPTOR; - -#pragma pack(pop) diff --git a/tests/projects/winsdk/usbview/uvcdesc.h b/tests/projects/winsdk/usbview/uvcdesc.h deleted file mode 100644 index f343fa731..000000000 --- a/tests/projects/winsdk/usbview/uvcdesc.h +++ /dev/null @@ -1,1106 +0,0 @@ -//+------------------------------------------------------------------------- -// -// Microsoft Windows -// -// Copyright (C) Microsoft Corporation, 1999 - 2008 -// -// File: uvcdesc.h -// -// This header is from the UVC 1.1 USBVideo driver -// -//-------------------------------------------------------------------------- - -#ifndef ___UVCDESC_H___ -#define ___UVCDESC_H___ - - -// USB Video Device Class Code -#define USB_DEVICE_CLASS_VIDEO 0x0E - -// Video sub-classes -#define SUBCLASS_UNDEFINED 0x00 -#define VIDEO_SUBCLASS_CONTROL 0x01 -#define VIDEO_SUBCLASS_STREAMING 0x02 - -// Video Class-Specific Descriptor Types -#define CS_UNDEFINED 0x20 -#define CS_DEVICE 0x21 -#define CS_CONFIGURATION 0x22 -#define CS_STRING 0x23 -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -// Video Class-Specific VC Interface Descriptor Subtypes -#define VC_HEADER 0x01 -#define INPUT_TERMINAL 0x02 -#define OUTPUT_TERMINAL 0x03 -#define SELECTOR_UNIT 0x04 -#define PROCESSING_UNIT 0x05 -#define EXTENSION_UNIT 0x06 -#define MAX_TYPE_UNIT 0x07 - -// Video Class-Specific VS Interface Descriptor Subtypes -#define VS_DESCRIPTOR_UNDEFINED 0x00 -#define VS_INPUT_HEADER 0x01 -#define VS_OUTPUT_HEADER 0x02 -#define VS_STILL_IMAGE_FRAME 0x03 -#define VS_FORMAT_UNCOMPRESSED 0x04 -#define VS_FRAME_UNCOMPRESSED 0x05 -#define VS_FORMAT_MJPEG 0x06 -#define VS_FRAME_MJPEG 0x07 -#define VS_FORMAT_MPEG1 0x08 -#define VS_FORMAT_MPEG2PS 0x09 -#define VS_FORMAT_MPEG2TS 0x0A -#define VS_FORMAT_MPEG4SL 0x0B -#define VS_FORMAT_DV 0x0C -#define VS_COLORFORMAT 0x0D -#define VS_FORMAT_VENDOR 0x0E -#define VS_FRAME_VENDOR 0x0F - -// Video Class-Specific Endpoint Descriptor Subtypes -#define EP_UNDEFINED 0x00 -#define EP_GENERAL 0x01 -#define EP_ENDPOINT 0x02 -#define EP_INTERRUPT 0x03 - -// Video Class-Specific Terminal Types -#define TERMINAL_TYPE_VENDOR_SPECIFIC 0x0100 -#define TERMINAL_TYPE_USB_STREAMING 0x0101 -#define TERMINAL_TYPE_INPUT_MASK 0x0200 -#define TERMINAL_TYPE_INPUT_VENDOR_SPECIFIC 0x0200 -#define TERMINAL_TYPE_INPUT_CAMERA 0x0201 -#define TERMINAL_TYPE_INPUT_MEDIA_TRANSPORT 0x0202 -#define TERMINAL_TYPE_OUTPUT_MASK 0x0300 -#define TERMINAL_TYPE_OUTPUT_VENDOR_SPECIFIC 0x0300 -#define TERMINAL_TYPE_OUTPUT_DISPLAY 0x0301 -#define TERMINAL_TYPE_OUTPUT_MEDIA_TRANSPORT 0x0302 -#define TERMINAL_TYPE_EXTERNAL_VENDOR_SPECIFIC 0x0400 -#define TERMINAL_TYPE_EXTERNAL_UNDEFINED 0x0400 -#define TERMINAL_TYPE_EXTERNAL_COMPOSITE 0x0401 -#define TERMINAL_TYPE_EXTERNAL_SVIDEO 0x0402 -#define TERMINAL_TYPE_EXTERNAL_COMPONENT 0x0403 - - -// Controls for error checking only -#define DEV_SPECIFIC_CONTROL 0x1001 - -// Map KSNODE_TYPE GUIDs to Indexes -#define NODE_TYPE_NONE 0 -#define NODE_TYPE_STREAMING 1 -#define NODE_TYPE_INPUT_TERMINAL 2 -#define NODE_TYPE_OUTPUT_TERMINAL 3 -#define NODE_TYPE_SELECTOR 4 -#define NODE_TYPE_PROCESSING 5 -#define NODE_TYPE_CAMERA_TERMINAL 6 -#define NODE_TYPE_INPUT_MTT 7 -#define NODE_TYPE_OUTPUT_MTT 8 -#define NODE_TYPE_DEV_SPEC 9 -#define NODE_TYPE_MAX 9 - -// USB bmRequestType values -#define USBVIDEO_INTERFACE_SET 0x21 -#define USBVIDEO_ENDPOINT_SET 0x22 -#define USBVIDEO_INTERFACE_GET 0xA1 -#define USBVIDEO_ENDPOINT_GET 0xA2 - -// Video Class-specific specific requests -#define CLASS_SPECIFIC_GET_MASK 0x80 - -#define RC_UNDEFINED 0x00 -#define SET_CUR 0x01 -#define GET_CUR 0x81 -#define GET_MIN 0x82 -#define GET_MAX 0x83 -#define GET_RES 0x84 -#define GET_LEN 0x85 -#define GET_INFO 0x86 -#define GET_DEF 0x87 - -// Power Mode Control constants -#define POWER_MODE_CONTROL_FULL 0x0 -#define POWER_MODE_CONTROL_DEV_DEPENDENT 0x1 - -// Video Class-specific Processing Unit Controls -#define PU_CONTROL_UNDEFINED 0x00 -#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 -#define PU_BRIGHTNESS_CONTROL 0x02 -#define PU_CONTRAST_CONTROL 0x03 -#define PU_GAIN_CONTROL 0x04 -#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 -#define PU_HUE_CONTROL 0x06 -#define PU_SATURATION_CONTROL 0x07 -#define PU_SHARPNESS_CONTROL 0x08 -#define PU_GAMMA_CONTROL 0x09 -#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A -#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B -#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C -#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D -#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0E -#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F -#define PU_HUE_AUTO_CONTROL 0x10 -#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 -#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 - -// Video Class-specific Camera Terminal Controls -#define CT_CONTROL_UNDEFINED 0x00 -#define CT_SCANNING_MODE_CONTROL 0x01 -#define CT_AE_MODE_CONTROL 0x02 -#define CT_AE_PRIORITY_CONTROL 0x03 -#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 -#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 -#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 -#define CT_FOCUS_RELATIVE_CONTROL 0x07 -#define CT_FOCUS_AUTO_CONTROL 0x08 -#define CT_IRIS_ABSOLUTE_CONTROL 0x09 -#define CT_IRIS_RELATIVE_CONTROL 0x0A -#define CT_ZOOM_ABSOLUTE_CONTROL 0x0B -#define CT_ZOOM_RELATIVE_CONTROL 0x0C -#define CT_PANTILT_ABSOLUTE_CONTROL 0x0D -#define CT_PANTILT_RELATIVE_CONTROL 0x0E -#define CT_ROLL_ABSOLUTE_CONTROL 0x0F -#define CT_ROLL_RELATIVE_CONTROL 0x10 -#define CT_PRIVACY_CONTROL 0x11 - -#define CT_RELATIVE_INCREASE 0x01 -#define CT_RELATIVE_DECREASE 0xff -#define CT_RELATIVE_STOP 0x00 - -// Selector Unit Control Selector -#define SU_INPUT_SELECT_CONTROL 0x01 - -// Media Tape Transport Control Selector -#define MTT_CONTROL_UNDEFINED 0x00 -#define MTT_TRANSPORT_CONTROL 0x01 -#define MTT_ATN_INFORMATION_CONTROL 0x02 -#define MTT_MEDIA_INFORMATION_CONTROL 0x03 -#define MTT_TIME_CODE_INFORMATION_CONTROL 0x04 - -// Media Transport Terminal States -#define MTT_STATE_PLAY_NEXT_FRAME 0x00 -#define MTT_STATE_PLAY_FWD_SLOWEST 0x01 -#define MTT_STATE_PLAY_SLOW_FWD_4 0x02 -#define MTT_STATE_PLAY_SLOW_FWD_3 0x03 -#define MTT_STATE_PLAY_SLOW_FWD_2 0x04 -#define MTT_STATE_PLAY_SLOW_FWD_1 0x05 -#define MTT_STATE_PLAY_X1 0x06 -#define MTT_STATE_PLAY_FAST_FWD_1 0x07 -#define MTT_STATE_PLAY_FAST_FWD_2 0x08 -#define MTT_STATE_PLAY_FAST_FWD_3 0x09 -#define MTT_STATE_PLAY_FAST_FWD_4 0x0A -#define MTT_STATE_PLAY_FASTEST_FWD 0x0B -#define MTT_STATE_PLAY_PREV_FRAME 0x0C -#define MTT_STATE_PLAY_SLOWEST_REV 0x0D -#define MTT_STATE_PLAY_SLOW_REV_4 0x0E -#define MTT_STATE_PLAY_SLOW_REV_3 0x0F -#define MTT_STATE_PLAY_SLOW_REV_2 0x10 -#define MTT_STATE_PLAY_SLOW_REV_1 0x11 -#define MTT_STATE_PLAY_REV 0x12 -#define MTT_STATE_PLAY_FAST_REV_1 0x13 -#define MTT_STATE_PLAY_FAST_REV_2 0x14 -#define MTT_STATE_PLAY_FAST_REV_3 0x15 -#define MTT_STATE_PLAY_FAST_REV_4 0x16 -#define MTT_STATE_PLAY_FASTEST_REV 0x17 -#define MTT_STATE_PLAY 0x18 -#define MTT_STATE_PAUSE 0x19 -#define MTT_STATE_PLAY_REVERSE_PAUSE 0x1A - - -#define MTT_STATE_STOP 0x40 -#define MTT_STATE_FAST_FORWARD 0x41 -#define MTT_STATE_REWIND 0x42 -#define MTT_STATE_HIGH_SPEED_REWIND 0x43 - -#define MTT_STATE_RECORD_START 0x50 -#define MTT_STATE_RECORD_PAUSE 0x51 - -#define MTT_STATE_EJECT 0x60 - -#define MTT_STATE_PLAY_SLOW_FWD_X 0x70 -#define MTT_STATE_PLAY_FAST_FWD_X 0x71 -#define MTT_STATE_PLAY_SLOW_REV_X 0x72 -#define MTT_STATE_PLAY_FAST_REV_X 0x73 -#define MTT_STATE_STOP_START 0x74 -#define MTT_STATE_STOP_END 0x75 -#define MTT_STATE_STOP_EMERGENCY 0x76 -#define MTT_STATE_STOP_CONDENSATION 0x77 -#define MTT_STATE_UNSPECIFIED 0x7F - -// Video Control Interface Control Selectors -#define VC_UNDEFINED_CONTROL 0x00 -#define VC_VIDEO_POWER_MODE_CONTROL 0x01 -#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 - -// VideoStreaming Interface Control Selectors -#define VS_CONTROL_UNDEFINED 0x00 -#define VS_PROBE_CONTROL 0x01 -#define VS_COMMIT_CONTROL 0x02 -#define VS_STILL_PROBE_CONTROL 0x03 -#define VS_STILL_COMMIT_CONTROL 0x04 -#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 -#define VS_STREAM_ERROR_CODE_CONTROL 0x06 -#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 -#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 -#define VS_SYNC_DELAY_CONTROL 0x09 - -// Probe commit bitmap framing info -#define VS_PROBE_COMMIT_BIT_FID 0x01 -#define VS_PROBE_COMMIT_BIT_EOF 0x02 - -// Stream payload header Bit Field Header bits -#define BFH_FID 0x01 // Frame ID bit -#define BFH_EOF 0x02 // End of Frame bit -#define BFH_PTS 0x04 // Presentation Time Stamp bit -#define BFH_SCR 0x08 // Source Clock Reference bit -#define BFH_RES 0x10 // Reserved bit -#define BFH_STI 0x20 // Still image bit -#define BFH_ERR 0x40 // Error bit -#define BFH_EOH 0x80 // End of header bit - -#define HDR_LENGTH 1 // Length of header length field in bytes -#define BFH_LENGTH 1 // Length of BFH field in bytes -#define PTS_LENGTH 4 // Length of PTS field in bytes -#define SCR_LENGTH 6 // Length of SCR field in bytes - -// USB Video Status Codes (Request Error Code Control) -#define USBVIDEO_RE_STATUS_NOERROR 0x00 -#define USBVIDEO_RE_STATUS_NOT_READY 0x01 -#define USBVIDEO_RE_STATUS_WRONG_STATE 0x02 -#define USBVIDEO_RE_STATUS_POWER 0x03 -#define USBVIDEO_RE_STATUS_OUT_OF_RANGE 0x04 -#define USBVIDEO_RE_STATUS_INVALID_UNIT 0x05 -#define USBVIDEO_RE_STATUS_INVALID_CONTROL 0x06 -#define USBVIDEO_RE_STATUS_UNKNOWN 0x07 - -// USB Video Device Status Codes (Stream Error Code Control) -#define USBVIDEO_SE_STATUS_NOERROR 0x00 -#define USBVIDEO_SE_STATUS_PROTECTED_CONTENT 0x01 -#define USBVIDEO_SE_STATUS_INPUT_BUFFER_UNDERRUN 0x02 -#define USBVIDEO_SE_STATUS_DATA_DICONTINUITY 0x03 -#define USBVIDEO_SE_STATUS_OUTPUT_BUFFER_UNDERRUN 0x04 -#define USBVIDEO_SE_STATUS_OUTPUT_BUFFER_OVERRUN 0x05 -#define USBVIDEO_SE_STATUS_FORMAT_CHANGE 0x06 -#define USBVIDEO_SE_STATUS_STILL_IMAGE_ERROR 0x07 -#define USBVIDEO_SE_STATUS_UNKNOWN 0x08 - -// Status Interrupt Types -#define STATUS_INTERRUPT_VC 1 -#define STATUS_INTERRUPT_VS 2 - -// Status Interrupt Attributes -#define STATUS_INTERRUPT_ATTRIBUTE_VALUE 0x00 -#define STATUS_INTERRUPT_ATTRIBUTE_INFO 0x01 -#define STATUS_INTERRUPT_ATTRIBUTE_FAILURE 0x02 - -// VideoStreaming interface interrupt types -#define VS_INTERRUPT_EVENT_BUTTON_PRESS 0x00 -#define VS_INTERRUPT_VALUE_BUTTON_RELEASE 0x00 -#define VS_INTERRUPT_VALUE_BUTTON_PRESS 0x01 - -// Get Info Values -#define USBVIDEO_ASYNC_CONTROL 0x10 -#define USBVIDEO_SETTABLE_CONTROL 0x2 - -#define MAX_INTERRUPT_PACKET_VALUE_SIZE 8 - -// Frame descriptor frame interval array offsets -#define MIN_FRAME_INTERVAL_OFFSET 0 -#define MAX_FRAME_INTERVAL_OFFSET 1 -#define FRAME_INTERVAL_STEP_OFFSET 2 - -// Still image capture methods -#define STILL_CAPTURE_METHOD_NONE 0 -#define STILL_CAPTURE_METHOD_1 1 -#define STILL_CAPTURE_METHOD_2 2 -#define STILL_CAPTURE_METHOD_3 3 - -// Still image trigger control states -#define STILL_IMAGE_TRIGGER_NORMAL 0 -#define STILL_IMAGE_TRIGGER_TRANSMIT 1 -#define STILL_IMAGE_TRIGGER_TRANSMIT_BULK 2 -#define STILL_IMAGE_TRIGGER_TRANSMIT_ABORT 3 - -// Endpoint descriptor masks -#define EP_DESCRIPTOR_TRANSACTION_SIZE_MASK 0x07ff -#define EP_DESCRIPTOR_NUM_TRANSACTION_MASK 0x1800 -#define EP_DESCRIPTOR_NUM_TRANSACTION_OFFSET 11 - - -// Copy protection flag defined in the Uncompressed Payload Spec -#define USB_VIDEO_UNCOMPRESSED_RESTRICT_DUPLICATION 1 - -// Interlace flags -#define INTERLACE_FLAGS_SUPPORTED_MASK 0x01 -#define INTERLACE_FLAGS_FIELDS_PER_FRAME_MASK 0x02 -#define INTERLACE_FLAGS_FIELDS_PER_FRAME_2 0x00 -#define INTERLACE_FLAGS_FIELDS_PER_FRAME_1 0x02 -#define INTERLACE_FLAGS_FIELD_1_FIRST_MASK 0x04 -#define INTERLACE_FLAGS_FIELD_PATTERN_MASK 0x30 -#define INTERLACE_FLAGS_FIELD_PATTERN_FIELD1 0x00 -#define INTERLACE_FLAGS_FIELD_PATTERN_FIELD2 0x10 -#define INTERLACE_FLAGS_FIELD_PATTERN_REGULAR 0x20 -#define INTERLACE_FLAGS_FIELD_PATTERN_RANDOM 0x30 -#define INTERLACE_FLAGS_DISPLAY_MODE_MASK 0xC0 -#define INTERLACE_FLAGS_DISPLAY_MODE_BOB 0x00 -#define INTERLACE_FLAGS_DISPLAY_MODE_WEAVE 0x40 -#define INTERLACE_FLAGS_DISPLAY_MODE_BOB_WEAVE 0x80 - -// Color Matching Flags -#define UVC_PRIMARIES_UNKNOWN 0x0 -#define UVC_PRIMARIES_BT709 0x1 -#define UVC_PRIMARIES_BT470_2M 0x2 -#define UVC_PRIMARIES_BT470_2BG 0x3 -#define UVC_PRIMARIES_SMPTE_170M 0x4 -#define UVC_PRIMARIES_SMPTE_240M 0x5 - -#define UVC_GAMMA_UNKNOWN 0x0 -#define UVC_GAMMA_BT709 0x1 -#define UVC_GAMMA_BT470_2M 0x2 -#define UVC_GAMMA_BT470_2BG 0x3 -#define UVC_GAMMA_SMPTE_170M 0x4 -#define UVC_GAMMA_SMPTE_240M 0x5 -#define UVC_GAMMA_LINEAR 0x6 -#define UVC_GAMMA_sRGB 0x7 - -#define UVC_TRANSFER_MATRIX_UNKNOWN 0x0 -#define UVC_TRANSFER_MATRIX_BT709 0x1 -#define UVC_TRANSFER_MATRIX_FCC 0x2 -#define UVC_TRANSFER_MATRIX_BT470_2BG 0x3 -#define UVC_TRANSFER_MATRIX_BT601 0x4 -#define UVC_TRANSFER_MATRIX_SMPTE_240M 0x5 - -// -// BEGIN - VDC Descriptor and Control Structures -// -#pragma warning( disable : 4200 ) // Allow zero-sized arrays at end of structs -#pragma pack( push, vdc_descriptor_structs, 1) - -// Video Specific Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // descriptor subtype -} VIDEO_SPECIFIC, *PVIDEO_SPECIFIC; - -#define SIZEOF_VIDEO_SPECIFIC(pDesc) sizeof(VIDEO_SPECIFIC) - - -// Video Unit Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // descriptor subtype - UCHAR bUnitID; // Constant uniquely identifying the Unit -} VIDEO_UNIT, *PVIDEO_UNIT; - -#define SIZEOF_VIDEO_UNIT(pDesc) sizeof(VIDEO_UNIT) - -// VideoControl Header Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // VC_HEADER descriptor subtype - USHORT bcdVideoSpec; // USB video class spec revision number - USHORT wTotalLength; // Total length, including all units and terminals - ULONG dwClockFreq; // Device clock frequency in Hz - UCHAR bInCollection; // number of video streaming interfaces - UCHAR baInterfaceNr[]; // interface number array -} VIDEO_CONTROL_HEADER_UNIT, *PVIDEO_CONTROL_HEADER_UNIT; - -#define SIZEOF_VIDEO_CONTROL_HEADER_UNIT(pDesc) \ - ((sizeof(VIDEO_CONTROL_HEADER_UNIT) + (pDesc)->bInCollection)) - - -// VideoControl Input Terminal Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // INPUT_TERMINAL descriptor subtype - UCHAR bTerminalID; // Constant uniquely identifying the Terminal - USHORT wTerminalType; // Constant characterizing the terminal type - UCHAR bAssocTerminal; // ID of associated output terminal - UCHAR iTerminal; // Index of string descriptor -} VIDEO_INPUT_TERMINAL, *PVIDEO_INPUT_TERMINAL; - -#define SIZEOF_VIDEO_INPUT_TERMINAL(pDesc) sizeof(VIDEO_INPUT_TERMINAL) - - -// VideoControl Output Terminal Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // OUTPUT_TERMINAL descriptor subtype - UCHAR bTerminalID; // Constant uniquely identifying the Terminal - USHORT wTerminalType; // Constant characterizing the terminal type - UCHAR bAssocTerminal; // ID of associated input terminal - UCHAR bSourceID; // ID of source unit/terminal - UCHAR iTerminal; // Index of string descriptor -} VIDEO_OUTPUT_TERMINAL, *PVIDEO_OUTPUT_TERMINAL; - -#define SIZEOF_VIDEO_OUTPUT_TERMINAL(pDesc) sizeof(VIDEO_OUTPUT_TERMINAL) - - -// VideoControl Camera Terminal Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // INPUT_TERMINAL descriptor subtype - UCHAR bTerminalID; // Constant uniquely identifying the Terminal - USHORT wTerminalType; // Sensor type - UCHAR bAssocTerminal; // ID of associated output terminal - UCHAR iTerminal; // Index of string descriptor - USHORT wObjectiveFocalLengthMin; // Min focal length for zoom - USHORT wObjectiveFocalLengthMax; // Max focal length for zoom - USHORT wOcularFocalLength; // Ocular focal length for zoom - UCHAR bControlSize; // Size of bmControls field - UCHAR bmControls[]; // Bitmap of controls supported -} VIDEO_CAMERA_TERMINAL, *PVIDEO_CAMERA_TERMINAL; - -#define SIZEOF_VIDEO_CAMERA_TERMINAL(pDesc) \ - (sizeof(VIDEO_CAMERA_TERMINAL) + (pDesc)->bControlSize) - - -// Media Transport Input Terminal Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // INPUT_TERMINAL descriptor subtype - UCHAR bTerminalID; // Constant uniquely identifying the Terminal - USHORT wTerminalType; // Media Transport type - UCHAR bAssocTerminal; // ID of associated output terminal - UCHAR iTerminal; // Index of string descriptor - UCHAR bControlSize; // Size of bmControls field - UCHAR bmControls[]; // Bitmap of controls supported -} VIDEO_INPUT_MTT, *PVIDEO_INPUT_MTT; - - -__inline size_t SizeOfVideoInputMTT(_In_ PVIDEO_INPUT_MTT pDesc) -{ - UCHAR bTransportModeSize; - PUCHAR pbCurr; - - pbCurr = pDesc->bmControls + pDesc->bControlSize; - bTransportModeSize = *pbCurr; - - return sizeof(VIDEO_INPUT_MTT) + pDesc->bControlSize + 1 + bTransportModeSize; -} - -#define SIZEOF_VIDEO_INPUT_MTT(pDesc) SizeOfVideoInputMTT(pDesc) - - -// Media Transport Output Terminal Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // OUTPUT_TERMINAL descriptor subtype - UCHAR bTerminalID; // Constant uniquely identifying the Terminal - USHORT wTerminalType; // Media Transport type - UCHAR bAssocTerminal; // ID of associated output terminal - UCHAR bSourceID; // ID of source unit/terminal - UCHAR iTerminal; // Index of string descriptor - UCHAR bControlSize; // Size of bmControls field - UCHAR bmControls[]; // Bitmap of controls supported -} VIDEO_OUTPUT_MTT, *PVIDEO_OUTPUT_MTT; - - -__inline size_t SizeOfVideoOutputMTT(_In_ PVIDEO_OUTPUT_MTT pDesc) -{ - UCHAR bTransportModeSize; - PUCHAR pbCurr; - - pbCurr = pDesc->bmControls + pDesc->bControlSize; - bTransportModeSize = *pbCurr; - - return sizeof(VIDEO_OUTPUT_MTT) + pDesc->bControlSize + 1+ bTransportModeSize; -} - -#define SIZEOF_VIDEO_OUTPUT_MTT(pDesc) SizeOfVideoOutputMTT(pDesc) - - -// VideoControl Selector Unit Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // SELECTOR_UNIT descriptor subtype - UCHAR bUnitID; // Constant uniquely identifying the Unit - UCHAR bNrInPins; // Number of input pins - UCHAR baSourceID[]; // IDs of connected units/terminals -} VIDEO_SELECTOR_UNIT, *PVIDEO_SELECTOR_UNIT; - -#define SIZEOF_VIDEO_SELECTOR_UNIT(pDesc) \ - (sizeof(VIDEO_SELECTOR_UNIT) + (pDesc)->bNrInPins + 1) - - -// VideoControl Processing Unit Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // PROCESSING_UNIT descriptor subtype - UCHAR bUnitID; // Constant uniquely identifying the Unit - UCHAR bSourceID; // ID of connected unit/terminal - USHORT wMaxMultiplier; // Maximum digital magnification - UCHAR bControlSize; // Size of bmControls field - UCHAR bmControls[]; // Bitmap of controls supported -} VIDEO_PROCESSING_UNIT, *PVIDEO_PROCESSING_UNIT; - -#define SIZEOF_VIDEO_PROCESSING_UNIT(pDesc) \ - (sizeof(VIDEO_PROCESSING_UNIT) + 1 + (pDesc)->bControlSize) - - -// VideoControl Extension Unit Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // EXTENSION_UNIT descriptor subtype - UCHAR bUnitID; // Constant uniquely identifying the Unit - GUID guidExtensionCode; // Vendor-specific code identifying extension unit - UCHAR bNumControls; // Number of controls in Extension Unit - UCHAR bNrInPins; // Number of input pins - UCHAR baSourceID[]; // IDs of connected units/terminals -} VIDEO_EXTENSION_UNIT, *PVIDEO_EXTENSION_UNIT; -// this is followed by bControlSize, bmControls and iExtension (1 byte) - -__inline size_t SizeOfVideoExtensionUnit(PVIDEO_EXTENSION_UNIT pDesc) -{ - UCHAR bControlSize; - PUCHAR pbCurr; - - // baSourceID is an array, and hence understood to be an address - pbCurr = pDesc->baSourceID + pDesc->bNrInPins; - if (((ULONG_PTR) pbCurr < (ULONG_PTR) pDesc->baSourceID) || - (ULONG_PTR) pbCurr >= (ULONG_PTR)((UCHAR *) pDesc + pDesc->bLength)) - return 0; - - bControlSize = *pbCurr; - return 24 + pDesc->bNrInPins + bControlSize; -} - -#define SIZEOF_VIDEO_EXTENSION_UNIT(pDesc) SizeOfVideoExtensionUnit(pDesc) - - -// Class-specific Interrupt Endpoint Descriptor -typedef struct { - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_ENDPOINT descriptor type - UCHAR bDescriptorSubtype; // EP_INTERRUPT descriptor subtype - USHORT wMaxTransferSize; // Max interrupt payload size -} VIDEO_CS_INTERRUPT, *PVIDEO_CS_INTERRUPT; - -#define SIZEOF_VIDEO_CS_INTERRUPT(pDesc) sizeof(VIDEO_CS_INTERRUPT) - - -// VideoStreaming Input Header Descriptor -typedef struct _VIDEO_STREAMING_INPUT_HEADER -{ - UCHAR bLength; // Size of this descriptor in bytes - UCHAR bDescriptorType; // CS_INTERFACE descriptor type - UCHAR bDescriptorSubtype; // VS_INPUT_HEADER descriptor subtype - UCHAR bNumFormats; - USHORT wTotalLength; - UCHAR bEndpointAddress; - UCHAR bmInfo; - UCHAR bTerminalLink; - UCHAR bStillCaptureMethod; - UCHAR bTriggerSupport; - UCHAR bTriggerUsage; - UCHAR bControlSize; - UCHAR bmaControls[]; -} VIDEO_STREAMING_INPUT_HEADER, *PVIDEO_STREAMING_INPUT_HEADER; - -#define SIZEOF_VIDEO_STREAMING_INPUT_HEADER(pDesc) \ - (sizeof(VIDEO_STREAMING_INPUT_HEADER) + (pDesc->bNumFormats * pDesc->bControlSize)) - - -// VideoStreaming Output Header Descriptor -typedef struct _VIDEO_STREAMING_OUTPUT_HEADER -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bNumFormats; - USHORT wTotalLength; - UCHAR bEndpointAddress; - UCHAR bTerminalLink; -} VIDEO_STREAMING_OUTPUT_HEADER, *PVIDEO_STREAMING_OUTPUT_HEADER; - -#define SIZEOF_VIDEO_STREAMING_OUTPUT_HEADER(pDesc) sizeof(VIDEO_STREAMING_OUTPUT_HEADER) - - -typedef struct _VIDEO_STILL_IMAGE_RECT -{ - USHORT wWidth; - USHORT wHeight; -} VIDEO_STILL_IMAGE_RECT; - -// VideoStreaming Still Image Frame Descriptor -typedef struct _VIDEO_STILL_IMAGE_FRAME -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bEndpointAddress; - UCHAR bNumImageSizePatterns; - VIDEO_STILL_IMAGE_RECT aStillRect[]; -} VIDEO_STILL_IMAGE_FRAME, *PVIDEO_STILL_IMAGE_FRAME; - -__inline size_t SizeOfVideoStillImageFrame(PVIDEO_STILL_IMAGE_FRAME pDesc) -{ - UCHAR bNumCompressionPatterns; - PUCHAR pbCurr; - - pbCurr = (PUCHAR) pDesc->aStillRect + (sizeof(VIDEO_STILL_IMAGE_RECT) * pDesc->bNumImageSizePatterns); - bNumCompressionPatterns = *pbCurr; - - return (sizeof(VIDEO_STILL_IMAGE_FRAME) + - (sizeof(VIDEO_STILL_IMAGE_RECT) * pDesc->bNumImageSizePatterns) + - 1 + bNumCompressionPatterns); -} - -#define SIZEOF_VIDEO_STILL_IMAGE_FRAME(pDesc) SizeOfVideoStillImageFrame(pDesc) - - -// VideoStreaming Color Matching Descriptor -typedef struct _VIDEO_COLORFORMAT -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bColorPrimaries; - UCHAR bTransferCharacteristics; - UCHAR bMatrixCoefficients; -} VIDEO_COLORFORMAT, *PVIDEO_COLORFORMAT; - -#define SIZEOF_VIDEO_COLORFORMAT(pDesc) sizeof(VIDEO_COLORFORMAT) - - -// VideoStreaming Uncompressed Format Descriptor -typedef struct _VIDEO_FORMAT_UNCOMPRESSED -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - GUID guidFormat; - UCHAR bBitsPerPixel; - UCHAR bDefaultFrameIndex; - UCHAR bAspectRatioX; - UCHAR bAspectRatioY; - UCHAR bmInterlaceFlags; - UCHAR bCopyProtect; -} VIDEO_FORMAT_UNCOMPRESSED, *PVIDEO_FORMAT_UNCOMPRESSED; - -#define SIZEOF_VIDEO_FORMAT_UNCOMPRESSED(pDesc) sizeof(VIDEO_FORMAT_UNCOMPRESSED) - - -// VideoStreaming Uncompressed Frame Descriptor -typedef struct _VIDEO_FRAME_UNCOMPRESSED -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG dwMinBitRate; - ULONG dwMaxBitRate; - ULONG dwMaxVideoFrameBufferSize; - ULONG dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG adwFrameInterval[]; -} VIDEO_FRAME_UNCOMPRESSED, *PVIDEO_FRAME_UNCOMPRESSED; - - -__inline size_t SizeOfVideoFrameUncompressed(_In_ PVIDEO_FRAME_UNCOMPRESSED pDesc) -{ - if (pDesc->bFrameIntervalType == 0) { // Continuous - return sizeof(VIDEO_FRAME_UNCOMPRESSED) + (3 * sizeof(ULONG)); - } - else { // Discrete - return sizeof(VIDEO_FRAME_UNCOMPRESSED) + (pDesc->bFrameIntervalType * sizeof(ULONG)); - } -} - -#define SIZEOF_VIDEO_FRAME_UNCOMPRESSED(pDesc) SizeOfVideoFrameUncompressed(pDesc) - - -// VideoStreaming MJPEG Format Descriptor -typedef struct _VIDEO_FORMAT_MJPEG -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - UCHAR bmFlags; - UCHAR bDefaultFrameIndex; - UCHAR bAspectRatioX; - UCHAR bAspectRatioY; - UCHAR bmInterlaceFlags; - UCHAR bCopyProtect; -} VIDEO_FORMAT_MJPEG, *PVIDEO_FORMAT_MJPEG; - -#define SIZEOF_VIDEO_FORMAT_MJPEG(pDesc) sizeof(VIDEO_FORMAT_MJPEG) - - -// VideoStreaming MJPEG Frame Descriptor -typedef struct _VIDEO_FRAME_MJPEG -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG dwMinBitRate; - ULONG dwMaxBitRate; - ULONG dwMaxVideoFrameBufferSize; - ULONG dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG adwFrameInterval[]; -} VIDEO_FRAME_MJPEG, *PVIDEO_FRAME_MJPEG; - - -__inline size_t SizeOfVideoFrameMjpeg(_In_ PVIDEO_FRAME_MJPEG pDesc) -{ - if (pDesc->bFrameIntervalType == 0) { // Continuous - return sizeof(VIDEO_FRAME_MJPEG) + (3 * sizeof(ULONG)); - } - else { // Discrete - return sizeof(VIDEO_FRAME_MJPEG) + (pDesc->bFrameIntervalType * sizeof(ULONG)); - } -} - -#define SIZEOF_VIDEO_FRAME_MJPEG(pDesc) SizeOfVideoFrameMjpeg(pDesc) - - -// VideoStreaming Vendor Format Descriptor -typedef struct _VIDEO_FORMAT_VENDOR -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - GUID guidMajorFormat; - GUID guidSubFormat; - GUID guidSpecifier; - UCHAR bPayloadClass; - UCHAR bDefaultFrameIndex; - UCHAR bCopyProtect; -} VIDEO_FORMAT_VENDOR, *PVIDEO_FORMAT_VENDOR; - -#define SIZEOF_VIDEO_FORMAT_VENDOR(pDesc) sizeof(VIDEO_FORMAT_VENDOR) - - -// VideoStreaming Vendor Frame Descriptor -typedef struct _VIDEO_FRAME_VENDOR -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG dwMinBitRate; - ULONG dwMaxBitRate; - ULONG dwMaxVideoFrameBufferSize; - ULONG dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - DWORD adwFrameInterval[]; -} VIDEO_FRAME_VENDOR, *PVIDEO_FRAME_VENDOR; - -__inline size_t SizeOfVideoFrameVendor(_In_ PVIDEO_FRAME_VENDOR pDesc) -{ - if (pDesc->bFrameIntervalType == 0) { // Continuous - return sizeof(VIDEO_FRAME_VENDOR) + (3 * sizeof(ULONG)); - } - else { // Discrete - return sizeof(VIDEO_FRAME_VENDOR) + (pDesc->bFrameIntervalType * sizeof(ULONG)); - } -} - -#define SIZEOF_VIDEO_FRAME_VENDOR(pDesc) SizeOfVideoFrameVendor(pDesc) - - -// VideoStreaming DV Format Descriptor -typedef struct _VIDEO_FORMAT_DV -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - ULONG dwMaxVideoFrameBufferSize; - UCHAR bFormatType; -} VIDEO_FORMAT_DV, *PVIDEO_FORMAT_DV; - -#define SIZEOF_VIDEO_FORMAT_DV(pDesc) sizeof(VIDEO_FORMAT_DV) - - -// VideoStreaming MPEG2-TS Format Descriptor -typedef struct _VIDEO_FORMAT_MPEG2TS -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bDataOffset; - UCHAR bPacketLength; - UCHAR bStrideLength; -} VIDEO_FORMAT_MPEG2TS, *PVIDEO_FORMAT_MPEG2TS; - -#define SIZEOF_VIDEO_FORMAT_MPEG2TS(pDesc) sizeof(VIDEO_FORMAT_MPEG2TS) - - -// VideoStreaming MPEG1 System Stream Format Descriptor -typedef struct _VIDEO_FORMAT_MPEG1SS -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bPacketLength; - UCHAR bPackLength; - UCHAR bPackDataType; -} VIDEO_FORMAT_MPEG1SS, *PVIDEO_FORMAT_MPEG1SS; - -#define SIZEOF_VIDEO_FORMAT_MPEG1SS(pDesc) sizeof(VIDEO_FORMAT_MPEG1SS) - - -// VideoStreaming MPEG2-PS Format Descriptor -typedef struct _VIDEO_FORMAT_MPEG2PS -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bPacketLength; - UCHAR bPackLength; - UCHAR bPackDataType; -} VIDEO_FORMAT_MPEG2PS, *PVIDEO_FORMAT_MPEG2PS; - -#define SIZEOF_VIDEO_FORMAT_MPEG2PS(pDesc) sizeof(VIDEO_FORMAT_MPEG2PS) - - -// VideoStreaming MPEG4-SL Format Descriptor -typedef struct _VIDEO_FORMAT_MPEG4SL -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bPacketLength; -} VIDEO_FORMAT_MPEG4SL, *PVIDEO_FORMAT_MPEG4SL; - -#define SIZEOF_VIDEO_FORMAT_MPEG4SL(pDesc) sizeof(VIDEO_FORMAT_MPEG4SL) - -// VideoStreaming Probe/Commit Control -typedef struct _VS_PROBE_COMMIT_CONTROL -{ - USHORT bmHint; - UCHAR bFormatIndex; - UCHAR bFrameIndex; - ULONG dwFrameInterval; - USHORT wKeyFrameRate; - USHORT wPFrameRate; - USHORT wCompQuality; - USHORT wCompWindowSize; - USHORT wDelay; - ULONG dwMaxVideoFrameSize; - ULONG dwMaxPayloadTransferSize; -} VS_PROBE_COMMIT_CONTROL, *PVS_PROBE_COMMIT_CONTROL; - -// VideoStreaming Still Probe/Commit Control -typedef struct _VS_STILL_PROBE_COMMIT_CONTROL -{ - UCHAR bFormatIndex; - UCHAR bFrameIndex; - UCHAR bCompressionIndex; - ULONG dwMaxVideoFrameSize; - ULONG dwMaxPayloadTransferSize; -} VS_STILL_PROBE_COMMIT_CONTROL, *PVS_STILL_PROBE_COMMIT_CONTROL; - - -// Status Interrupt Packet (Video Control) -typedef struct _VC_INTERRUPT_PACKET -{ - UCHAR bStatusType; - UCHAR bOriginator; - UCHAR bEvent; - UCHAR bSelector; - UCHAR bAttribute; - UCHAR bValue[1]; -} VC_INTERRUPT_PACKET, *PVC_INTERRUPT_PACKET; - -// Status Interrupt Packet (Video Control) -typedef struct _VC_INTERRUPT_PACKET_EX -{ - UCHAR bStatusType; - UCHAR bOriginator; - UCHAR bEvent; - UCHAR bSelector; - UCHAR bAttribute; - UCHAR bValue[MAX_INTERRUPT_PACKET_VALUE_SIZE]; -} VC_INTERRUPT_PACKET_EX, *PVC_INTERRUPT_PACKET_EX; - -// Status Interrupt Packet (Video Streaming) -typedef struct _VS_INTERRUPT_PACKET -{ - UCHAR bStatusType; - UCHAR bOriginator; - UCHAR bEvent; - UCHAR bValue[1]; -} VS_INTERRUPT_PACKET, *PVS_INTERRUPT_PACKET; - -// Status Interrupt Packet (Generic) -typedef struct _VIDEO_INTERRUPT_PACKET -{ - UCHAR bStatusType; - UCHAR bOriginator; -} VIDEO_INTERRUPT_PACKET, *PVIDEO_INTERRUPT_PACKET; - - -// Relative property struct -typedef struct _VIDEO_RELATIVE_PROPERTY -{ - UCHAR bValue; - UCHAR bSpeed; -} VIDEO_RELATIVE_PROPERTY, *PVIDEO_RELATIVE_PROPERTY; - -// Relative Zoom control struct -typedef struct _ZOOM_RELATIVE_PROPERTY -{ - UCHAR bZoom; - UCHAR bDigitalZoom; - UCHAR bSpeed; -} ZOOM_RELATIVE_PROPERTY, *PZOOM_RELATIVE_PROPERTY; - -// Relative pan-tilt struct -typedef struct _PANTILT_RELATIVE_PROPERTY -{ - UCHAR bPanRelative; - UCHAR bPanSpeed; - UCHAR bTiltRelative; - UCHAR bTiltSpeed; -} PANTILT_RELATIVE_PROPERTY, *PPANTILT_RELATIVE_PROPERTY; - -typedef struct _MEDIA_INFORMATION_CONTROL -{ - UCHAR bmMediaType; - UCHAR bmWriteProtect; -} MEDIA_INFORMATION_CONTROL, *PMEDIA_INFORMATION_CONTROL; - -typedef struct _TIME_CODE_INFORMATION_CONTROL -{ - UCHAR bcdFrame; - UCHAR bcdSecond; - UCHAR bcdMinute; - UCHAR bcdHour; -} TIME_CODE_INFORMATION_CONTROL, *PTIME_CODE_INFORMATION_CONTROL; - -typedef struct _ATN_INFORMATION_CONTROL -{ - UCHAR bmMediaType; - DWORD dwATN_Data; -} ATN_INFORMATION_CONTROL, *PATN_INFORMATION_CONTROL; - -#define VS_FORMAT_FRAME_BASED 0x10 -#define VS_FRAME_FRAME_BASED 0x11 -#define VS_FORMAT_STREAM_BASED 0x12 - -// Format Descriptor for UVC 1.1 frame based format -typedef struct _VIDEO_FORMAT_FRAME -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - UCHAR bNumFrameDescriptors; - GUID guidFormat; - UCHAR bBitsPerPixel; - UCHAR bDefaultFrameIndex; - UCHAR bAspectRatioX; - UCHAR bAspectRatioY; - UCHAR bmInterlaceFlags; - UCHAR bCopyProtect; - UCHAR bVariableSize; -} VIDEO_FORMAT_FRAME, *PVIDEO_FORMAT_FRAME; - -#define SIZEOF_VIDEO_FORMAT_FRAME(pDesc) sizeof(VIDEO_FORMAT_FRAME) - - -// Frame Descriptor for UVC 1.1 frame based format -typedef struct _VIDEO_FRAME_FRAME -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFrameIndex; - UCHAR bmCapabilities; - USHORT wWidth; - USHORT wHeight; - ULONG dwMinBitRate; - ULONG dwMaxBitRate; - ULONG dwDefaultFrameInterval; - UCHAR bFrameIntervalType; - ULONG dwBytesPerLine; - ULONG adwFrameInterval[]; -} VIDEO_FRAME_FRAME, *PVIDEO_FRAME_FRAME; - -__inline size_t SizeOfVideoFrameFrame(_In_ PVIDEO_FRAME_FRAME pDesc) -{ - if (pDesc->bFrameIntervalType == 0) { // Continuous - return sizeof(VIDEO_FRAME_FRAME) + (3 * sizeof(ULONG)); - } - else { // Discrete - return sizeof(VIDEO_FRAME_FRAME) + (pDesc->bFrameIntervalType * sizeof(ULONG)); - } -} - -#define SIZEOF_VIDEO_FRAME_FRAME(pDesc) SizeOfVideoFrameFrame(pDesc) - -// VideoStreaming Stream Based Format Descriptor -typedef struct _VIDEO_FORMAT_STREAM -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bDescriptorSubtype; - UCHAR bFormatIndex; - GUID guidFormat; - ULONG dwPacketLength; -} VIDEO_FORMAT_STREAM, *PVIDEO_FORMAT_STREAM; - -#define SIZEOF_VIDEO_FORMAT_STREAM(pDesc) sizeof(VIDEO_FORMAT_STREAM) - -// VideoStreaming Probe/Commit Control -typedef struct _VS_PROBE_COMMIT_CONTROL2 -{ - USHORT bmHint; - UCHAR bFormatIndex; - UCHAR bFrameIndex; - ULONG dwFrameInterval; - USHORT wKeyFrameRate; - USHORT wPFrameRate; - USHORT wCompQuality; - USHORT wCompWindowSize; - USHORT wDelay; - ULONG dwMaxVideoFrameSize; - ULONG dwMaxPayloadTransferSize; - ULONG dwClockFrequency; - UCHAR bmFramingInfo; - UCHAR bPreferredVersion; - UCHAR bMinVersion; - UCHAR bMaxVersion; -} VS_PROBE_COMMIT_CONTROL2, *PVS_PROBE_COMMIT_CONTROL2; - -#pragma pack( pop, vdc_descriptor_structs ) -#pragma warning( default : 4200 ) - - -// -// END - VDC Descriptor and Control Structures -// - -#endif // ___UVCDESC_H___ diff --git a/tests/projects/winsdk/usbview/uvcview.c b/tests/projects/winsdk/usbview/uvcview.c deleted file mode 100644 index 04b295292..000000000 --- a/tests/projects/winsdk/usbview/uvcview.c +++ /dev/null @@ -1,2153 +0,0 @@ -/*++ - -Copyright (c) 1997-2011 Microsoft Corporation - -Module Name: - -USBVIEW.C - -Abstract: - -This is the GUI goop for the USBVIEW application. - -Environment: - -user mode - -Revision History: - -04-25-97 : created -11-20-02 : minor changes to support more reporting options -04/13/2005 : major bug fixing -07/01/2008 : add UVC 1.1 support and move to Dev branch - ---*/ - -/***************************************************************************** -I N C L U D E S -*****************************************************************************/ - -#include "resource.h" -#include "uvcview.h" -#include "h264.h" -#include "xmlhelper.h" - -#include - - -/***************************************************************************** -D E F I N E S -*****************************************************************************/ - -// window control defines -// -#define SIZEBAR 0 -#define WINDOWSCALEFACTOR 15 - -/***************************************************************************** - L O C A L T Y P E D E F S -*****************************************************************************/ -typedef struct _TREEITEMINFO -{ - struct _TREEITEMINFO *Next; - USHORT Depth; - PCHAR Name; - -} TREEITEMINFO, *PTREEITEMINFO; - - -/***************************************************************************** -L O C A L E N U M S -*****************************************************************************/ - -typedef enum _USBVIEW_SAVE_FILE_TYPE -{ - UsbViewNone = 0, - UsbViewXmlFile, - UsbViewTxtFile -} USBVIEW_SAVE_FILE_TYPE; - -/***************************************************************************** -L O C A L F U N C T I O N P R O T O T Y P E S -*****************************************************************************/ - -int WINAPI -WinMain ( - _In_ HINSTANCE hInstance, - _In_opt_ HINSTANCE hPrevInstance, - _In_ LPSTR lpszCmdLine, - _In_ int nCmdShow - ); - -BOOL -CreateMainWindow ( - int nCmdShow - ); - -VOID -ResizeWindows ( - BOOL bSizeBar, - int BarLocation - ); - -LRESULT CALLBACK -MainDlgProc ( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ); - -BOOL -USBView_OnInitDialog ( - HWND hWnd, - HWND hWndFocus, - LPARAM lParam - ); - -VOID -USBView_OnClose ( - HWND hWnd - ); - -VOID -USBView_OnCommand ( - HWND hWnd, - int id, - HWND hwndCtl, - UINT codeNotify - ); - -VOID -USBView_OnLButtonDown ( - HWND hWnd, - BOOL fDoubleClick, - int x, - int y, - UINT keyFlags - ); - -VOID -USBView_OnLButtonUp ( - HWND hWnd, - int x, - int y, - UINT keyFlags - ); - -VOID -USBView_OnMouseMove ( - HWND hWnd, - int x, - int y, - UINT keyFlags - ); - -VOID -USBView_OnSize ( - HWND hWnd, - UINT state, - int cx, - int cy - ); - -LRESULT -USBView_OnNotify ( - HWND hWnd, - int DlgItem, - LPNMHDR lpNMHdr - ); - -BOOL -USBView_OnDeviceChange ( - HWND hwnd, - UINT uEvent, - DWORD dwEventData - ); - -VOID DestroyTree (VOID); - -VOID RefreshTree (VOID); - -LRESULT CALLBACK -AboutDlgProc ( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ); - -VOID -WalkTree ( - _In_ HTREEITEM hTreeItem, - _In_ LPFNTREECALLBACK lpfnTreeCallback, - _In_opt_ PVOID pContext - ); - -VOID -ExpandItem ( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ); - -VOID -AddItemInformationToFile( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ); - -DWORD -DisplayLastError( - _Inout_updates_bytes_(count) char *szString, - int count); - -VOID AddItemInformationToXmlView( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ); -HRESULT InitializeConsole(); -VOID UnInitializeConsole(); -BOOL IsStdOutFile(); -VOID DisplayMessage(DWORD dwMsgId, ...); -VOID PrintString(LPTSTR lpszString); -LPTSTR WStringToAnsiString(LPWSTR lpwszString); -VOID WaitForKeyPress(); -BOOL ProcessCommandLine(); -HRESULT ProcessCommandSaveFile(LPTSTR szFileName, DWORD dwCreationDisposition, USBVIEW_SAVE_FILE_TYPE fileType); -HRESULT SaveAllInformationAsText(LPTSTR lpstrTextFileName, DWORD dwCreationDisposition); -HRESULT SaveAllInformationAsXml(LPTSTR lpstrTextFileName , DWORD dwCreationDisposition); - -/***************************************************************************** -G L O B A L S -*****************************************************************************/ -BOOL gDoConfigDesc = TRUE; -BOOL gDoAnnotation = TRUE; -BOOL gLogDebug = FALSE; -int TotalHubs = 0; - -extern DEVICE_GUID_LIST gHubList; -extern DEVICE_GUID_LIST gDeviceList; - -/***************************************************************************** -G L O B A L S P R I V A T E T O T H I S F I L E -*****************************************************************************/ - -HINSTANCE ghInstance = NULL; -HWND ghMainWnd = NULL; -HWND ghTreeWnd = NULL; -HWND ghEditWnd = NULL; -HWND ghStatusWnd = NULL; -HMENU ghMainMenu = NULL; -HTREEITEM ghTreeRoot = NULL; -HCURSOR ghSplitCursor = NULL; -HDEVNOTIFY gNotifyDevHandle = NULL; -HDEVNOTIFY gNotifyHubHandle = NULL; -HANDLE ghStdOut = NULL; - -BOOL gbConsoleFile = FALSE; -BOOL gbConsoleInitialized = FALSE; -BOOL gbButtonDown = FALSE; -BOOL gDoAutoRefresh = TRUE; - -int gBarLocation = 0; -int giGoodDevice = 0; -int giBadDevice = 0; -int giComputer = 0; -int giHub = 0; -int giNoDevice = 0; -int giGoodSsDevice = 0; -int giNoSsDevice = 0; - - -/***************************************************************************** - -WinMain() - -*****************************************************************************/ - -int WINAPI -WinMain ( - _In_ HINSTANCE hInstance, - _In_opt_ HINSTANCE hPrevInstance, - _In_ LPSTR lpszCmdLine, - _In_ int nCmdShow - ) -{ - MSG msg; - HACCEL hAccel; - int retStatus = 0; - - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpszCmdLine); - - InitXmlHelper(); - - ghInstance = hInstance; - - ghSplitCursor = LoadCursor(ghInstance, - MAKEINTRESOURCE(IDC_SPLIT)); - - if (!ghSplitCursor) - { - OOPS(); - return retStatus; - } - - hAccel = LoadAccelerators(ghInstance, - MAKEINTRESOURCE(IDACCEL)); - - if (!hAccel) - { - OOPS(); - return retStatus; - } - - if (!CreateTextBuffer()) - { - return retStatus; - } - - if (!ProcessCommandLine()) - { - // There were no command line flags, open GUI - if (CreateMainWindow(nCmdShow)) - { - while (GetMessage(&msg, NULL, 0, 0)) - { - if (!TranslateAccelerator(ghMainWnd, - hAccel, - &msg) && - !IsDialogMessage(ghMainWnd, - &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - retStatus = 1; - } - } - - DestroyTextBuffer(); - - ReleaseXmlWriter(); - - CHECKFORLEAKS(); - - return retStatus; -} - - -/***************************************************************************** - -ProcessCommandLine() - -Parses the command line and takes appropriate actions. Returns FALSE If there is no action to -perform -*****************************************************************************/ -BOOL ProcessCommandLine() -{ - LPWSTR *szArgList = NULL; - LPTSTR szArg = NULL; - LPTSTR szAnsiArg= NULL; - BOOL quietMode = FALSE; - - HRESULT hr = S_OK; - DWORD dwCreationDisposition = CREATE_NEW; - USBVIEW_SAVE_FILE_TYPE fileType = UsbViewNone; - - int nArgs = 0; - int i = 0; - BOOL bStatus = FALSE; - BOOL bStopArgProcessing = FALSE; - - szArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs); - - // If there are no arguments we return false - bStatus = (nArgs > 1)? TRUE:FALSE; - - if (NULL != szArgList) - { - if (nArgs > 1) - { - // If there are arguments, initialize console for ouput - InitializeConsole(); - } - - for (i = 1; (i < nArgs) && (bStopArgProcessing == FALSE); i++) - { - // Convert argument to ANSI string for futher processing - - szAnsiArg = WStringToAnsiString(szArgList[i]); - - if(NULL == szAnsiArg) - { - DisplayMessage(IDS_USBVIEW_INVALIDARG, szAnsiArg); - DisplayMessage(IDS_USBVIEW_USAGE); - break; - } - - if (0 == _stricmp(szAnsiArg, "/?")) - { - DisplayMessage(IDS_USBVIEW_USAGE); - break; - } - else if (NULL != StrStrI(szAnsiArg, "/saveall:")) - { - fileType = UsbViewTxtFile; - } - else if (NULL != StrStrI(szAnsiArg, "/savexml:")) - { - fileType = UsbViewXmlFile; - } - else if (0 == _stricmp(szAnsiArg, "/f")) - { - dwCreationDisposition = CREATE_ALWAYS; - } - else if (0 == _stricmp(szAnsiArg, "/q")) - { - quietMode = TRUE; - } - else - { - DisplayMessage(IDS_USBVIEW_INVALIDARG, szAnsiArg); - DisplayMessage(IDS_USBVIEW_USAGE); - bStopArgProcessing = TRUE; - } - - if (fileType != UsbViewNone) - { - // Save view information as to file - szArg = strchr(szAnsiArg, ':'); - - if (NULL == szArg || strlen(szArg) == 1) - { - // No ':' or just a ':' - DisplayMessage(IDS_USBVIEW_INVALID_FILENAME, szAnsiArg); - DisplayMessage(IDS_USBVIEW_USAGE); - bStopArgProcessing = TRUE; - } - else - { - hr = ProcessCommandSaveFile(szArg + 1, dwCreationDisposition, fileType); - - if (FAILED(hr)) - { - // No more processing - bStopArgProcessing = TRUE; - } - - fileType = UsbViewNone; - } - } - - if (NULL != szAnsiArg) - { - LocalFree(szAnsiArg); - } - } - - if(!quietMode) - { - WaitForKeyPress(); - } - - if (gbConsoleInitialized) - { - UnInitializeConsole(); - } - - LocalFree(szArgList); - } - return bStatus; -} - - -/***************************************************************************** - -ProcessCommandSaveFile() - -Process the save file command line - -*****************************************************************************/ -HRESULT ProcessCommandSaveFile(LPTSTR szFileName, DWORD dwCreationDisposition, USBVIEW_SAVE_FILE_TYPE fileType) -{ - HRESULT hr = S_OK; - LPTSTR szErrorBuffer = NULL; - - if (UsbViewNone == fileType || NULL == szFileName) - { - hr = E_INVALIDARG; - // Invalid arguments, return - return (hr); - } - - // The UI is not created yet, open the UI, but HIDE it - CreateMainWindow(SW_HIDE); - - if (UsbViewXmlFile == fileType) - { - hr = SaveAllInformationAsXml(szFileName, dwCreationDisposition); - } - - if (UsbViewTxtFile == fileType) - { - hr = SaveAllInformationAsText(szFileName, dwCreationDisposition); - } - - if (FAILED(hr)) - { - if (GetLastError() == ERROR_FILE_EXISTS || hr == HRESULT_FROM_WIN32(ERROR_FILE_EXISTS)) - { - // The operation failed because the file we tried to write to already existed and '/f' option - // was not present. Display error message to user describing '/f' option - switch(fileType) - { - case UsbViewXmlFile: - DisplayMessage(IDS_USBVIEW_FILE_EXISTS_XML, szFileName); - break; - case UsbViewTxtFile: - DisplayMessage(IDS_USBVIEW_FILE_EXISTS_TXT, szFileName); - break; - default: - DisplayMessage(IDS_USBVIEW_INTERNAL_ERROR); - break; - } - } - else - { - // Try to obtain system error message - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - hr, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &szErrorBuffer, // FormatMessage expects this buffer to be cast as LPTSTR - 0, - NULL); - PrintString("Unable to save file.\n"); - PrintString(szErrorBuffer); - LocalFree(szErrorBuffer); - } - } - else - { - // Display file saved to message in console - DisplayMessage(IDS_USBVIEW_SAVED_TO, szFileName); - } - - return (hr); -} - -/***************************************************************************** - -InitializeConsole() - -Initializes the std output in console - -*****************************************************************************/ -HRESULT InitializeConsole() -{ - HRESULT hr = S_OK; - - SetLastError(0); - - // Find if STD_OUTPUT is a console or has been redirected to a File - gbConsoleFile = IsStdOutFile(); - - if (!gbConsoleFile) - { - // Output is not redirected and GUI application do not have console by default, create a console - if(AllocConsole()) - { -#pragma warning(disable:4996) // We don' need the FILE * returned by freopen - // Reopen STDOUT , STDIN and STDERR - if((freopen("conout$", "w", stdout) != NULL) && - (freopen("conin$", "r", stdin) != NULL) && - (freopen("conout$","w", stderr) != NULL)) - { - gbConsoleInitialized = TRUE; - ghStdOut = GetStdHandle(STD_OUTPUT_HANDLE); - } -#pragma warning(default:4996) - } - } - - if (INVALID_HANDLE_VALUE == ghStdOut || FALSE == gbConsoleInitialized) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OOPS(); - } - return hr; -} - -/***************************************************************************** - -UnInitializeConsole() - -UnInitializes the console - -*****************************************************************************/ -VOID UnInitializeConsole() -{ - gbConsoleInitialized = FALSE; - FreeConsole(); -} - -/***************************************************************************** - -IsStdOutFile() - -Finds if the STD_OUTPUT has been redirected to a file -*****************************************************************************/ -BOOL IsStdOutFile() -{ - unsigned htype; - HANDLE hFile; - - // 1 = STDOUT - hFile = (HANDLE) _get_osfhandle(1); - htype = GetFileType(hFile); - htype &= ~FILE_TYPE_REMOTE; - - - // Check if file type is character file - if (FILE_TYPE_DISK == htype) - { - return TRUE; - } - - return FALSE; -} - - -/***************************************************************************** - -DisplayMessage() - -Displays a message to standard output -*****************************************************************************/ -VOID DisplayMessage(DWORD dwResId, ...) -{ - CHAR szFormat[4096]; - HRESULT hr = S_OK; - LPTSTR lpszMessage = NULL; - DWORD dwLen = 0; - va_list ap; - - va_start(ap, dwResId); - - // Initialize console if needed - if (!gbConsoleInitialized) - { - hr = InitializeConsole(); - if (FAILED(hr)) - { - OOPS(); - return; - } - } - - // Load the string resource - dwLen = LoadString(GetModuleHandle(NULL), - dwResId, - szFormat, - ARRAYSIZE(szFormat) - ); - - if(0 == dwLen) - { - PrintString("Unable to find message for given resource ID"); - - // Return if resource ID could not be found - return; - } - - dwLen = FormatMessage( - FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, - szFormat, - dwResId, - 0, - (LPTSTR) &lpszMessage, - ARRAYSIZE(szFormat), - &ap); - - if (dwLen > 0) - { - PrintString(lpszMessage); - LocalFree(lpszMessage); - } - else - { - PrintString("Unable to find message for given ID"); - } - - va_end(ap); - return; -} - -/***************************************************************************** - -WStringToAnsiString() - -Converts the Wide char string to ANSI string and returns the allocated ANSI string. -*****************************************************************************/ -LPTSTR WStringToAnsiString(LPWSTR lpwszString) -{ - int strLen = 0; - LPTSTR szAnsiBuffer = NULL; - - szAnsiBuffer = LocalAlloc(LPTR, (MAX_PATH + 1) * sizeof(CHAR)); - - // Convert string from from WCHAR to ANSI - if (NULL != szAnsiBuffer) - { - strLen = WideCharToMultiByte( - CP_ACP, - 0, - lpwszString, - -1, - szAnsiBuffer, - MAX_PATH + 1, - NULL, - NULL); - - if (strLen > 0) - { - return szAnsiBuffer; - } - } - return NULL; -} - -/***************************************************************************** - -PrintString() - -Displays a string to standard output -*****************************************************************************/ -VOID PrintString(LPTSTR lpszString) -{ - DWORD dwBytesWritten = 0; - size_t Len = 0; - LPSTR lpOemString = NULL; - - if (INVALID_HANDLE_VALUE == ghStdOut || NULL == lpszString) - { - OOPS(); - // Return if invalid inputs - return; - } - - if (FAILED(StringCchLength(lpszString, OUTPUT_MESSAGE_MAX_LENGTH, &Len))) - { - OOPS(); - // Return if string is too long - return; - } - - if (gbConsoleFile) - { - // Console has been redirected to a file, ex: `usbview /savexml:xx > test.txt`. We need to use WriteFile instead of - // WriteConsole for text output. - lpOemString = (LPSTR) LocalAlloc(LPTR, (Len + 1) * sizeof(CHAR)); - if (lpOemString != NULL) - { - if (CharToOemBuff(lpszString, lpOemString, (DWORD) Len)) - { - WriteFile(ghStdOut, (LPVOID) lpOemString, (DWORD) Len, &dwBytesWritten, NULL); - } - else - { - OOPS(); - } - } - } - else - { - // Write to std out in console - WriteConsole(ghStdOut, (LPVOID) lpszString, (DWORD) Len, &dwBytesWritten, NULL); - } - - return; -} - -/***************************************************************************** - -WaitForKeyPress() - -Waits for key press in case of console -*****************************************************************************/ -VOID WaitForKeyPress() -{ - // Wait for key press if console - if (!gbConsoleFile && gbConsoleInitialized) - { - DisplayMessage(IDS_USBVIEW_PRESSKEY); - (VOID) _getch(); - } - return; -} - -/***************************************************************************** - -CreateMainWindow() - -*****************************************************************************/ - -BOOL -CreateMainWindow ( - int nCmdShow - ) -{ - RECT rc; - - InitCommonControls(); - - ghMainWnd = CreateDialog(ghInstance, - MAKEINTRESOURCE(IDD_MAINDIALOG), - NULL, - (DLGPROC) MainDlgProc); - - if (ghMainWnd == NULL) - { - OOPS(); - return FALSE; - } - - GetWindowRect(ghMainWnd, &rc); - - gBarLocation = (rc.right - rc.left) / 3; - - ResizeWindows(FALSE, 0); - - ShowWindow(ghMainWnd, nCmdShow); - - UpdateWindow(ghMainWnd); - - return TRUE; -} - - -/***************************************************************************** - -ResizeWindows() - -Handles resizing the two child windows of the main window. If -bSizeBar is true, then the sizing is happening because the user is -moving the bar. If bSizeBar is false, the sizing is happening -because of the WM_SIZE or something like that. - -*****************************************************************************/ - -VOID -ResizeWindows ( - BOOL bSizeBar, - int BarLocation - ) -{ - RECT MainClientRect; - RECT MainWindowRect; - RECT TreeWindowRect; - RECT StatusWindowRect; - int right; - - // Is the user moving the bar? - // - if (!bSizeBar) - { - BarLocation = gBarLocation; - } - - GetClientRect(ghMainWnd, &MainClientRect); - - GetWindowRect(ghStatusWnd, &StatusWindowRect); - - // Make sure the bar is in a OK location - // - if (bSizeBar) - { - if (BarLocation < - GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR) - { - return; - } - - if ((MainClientRect.right - BarLocation) < - GetSystemMetrics(SM_CXSCREEN)/WINDOWSCALEFACTOR) - { - return; - } - } - - // Save the bar location - // - gBarLocation = BarLocation; - - // Move the tree window - // - MoveWindow(ghTreeWnd, - 0, - 0, - BarLocation, - MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top, - TRUE); - - // Get the size of the window (in case move window failed - // - GetWindowRect(ghTreeWnd, &TreeWindowRect); - GetWindowRect(ghMainWnd, &MainWindowRect); - - right = TreeWindowRect.right - MainWindowRect.left; - - // Move the edit window with respect to the tree window - // - MoveWindow(ghEditWnd, - right+SIZEBAR, - 0, - MainClientRect.right-(right+SIZEBAR), - MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top, - TRUE); - - // Move the Status window with respect to the tree window - // - MoveWindow(ghStatusWnd, - 0, - MainClientRect.bottom - StatusWindowRect.bottom + StatusWindowRect.top, - MainClientRect.right, - StatusWindowRect.bottom - StatusWindowRect.top, - TRUE); -} - - -/***************************************************************************** - -MainWndProc() - -*****************************************************************************/ - -LRESULT CALLBACK -MainDlgProc ( - HWND hWnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ) -{ - - switch (uMsg) - { - - HANDLE_MSG(hWnd, WM_INITDIALOG, USBView_OnInitDialog); - HANDLE_MSG(hWnd, WM_CLOSE, USBView_OnClose); - HANDLE_MSG(hWnd, WM_COMMAND, USBView_OnCommand); - HANDLE_MSG(hWnd, WM_LBUTTONDOWN, USBView_OnLButtonDown); - HANDLE_MSG(hWnd, WM_LBUTTONUP, USBView_OnLButtonUp); - HANDLE_MSG(hWnd, WM_MOUSEMOVE, USBView_OnMouseMove); - HANDLE_MSG(hWnd, WM_SIZE, USBView_OnSize); - HANDLE_MSG(hWnd, WM_NOTIFY, USBView_OnNotify); - HANDLE_MSG(hWnd, WM_DEVICECHANGE, USBView_OnDeviceChange); - } - - return 0; -} - -/***************************************************************************** - -USBView_OnInitDialog() - -*****************************************************************************/ - -BOOL -USBView_OnInitDialog ( - HWND hWnd, - HWND hWndFocus, - LPARAM lParam - ) -{ - HFONT hFont; - HIMAGELIST himl; - HICON hicon; - DEV_BROADCAST_DEVICEINTERFACE broadcastInterface; - - UNREFERENCED_PARAMETER(lParam); - UNREFERENCED_PARAMETER(hWndFocus); - - // Register to receive notification when a USB device is plugged in. - broadcastInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - broadcastInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - - memcpy( &(broadcastInterface.dbcc_classguid), - &(GUID_DEVINTERFACE_USB_DEVICE), - sizeof(struct _GUID)); - - gNotifyDevHandle = RegisterDeviceNotification(hWnd, - &broadcastInterface, - DEVICE_NOTIFY_WINDOW_HANDLE); - - // Now register for Hub notifications. - memcpy( &(broadcastInterface.dbcc_classguid), - &(GUID_CLASS_USBHUB), - sizeof(struct _GUID)); - - gNotifyHubHandle = RegisterDeviceNotification(hWnd, - &broadcastInterface, - DEVICE_NOTIFY_WINDOW_HANDLE); - - gHubList.DeviceInfo = INVALID_HANDLE_VALUE; - InitializeListHead(&gHubList.ListHead); - gDeviceList.DeviceInfo = INVALID_HANDLE_VALUE; - InitializeListHead(&gDeviceList.ListHead); - - //end add - - ghTreeWnd = GetDlgItem(hWnd, IDC_TREE); - - //added - if ((himl = ImageList_Create(15, 15, - FALSE, 2, 0)) == NULL) - { - OOPS(); - } - - if(himl != NULL) - { - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_ICON)); - giGoodDevice = ImageList_AddIcon(himl, hicon); - - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_BADICON)); - giBadDevice = ImageList_AddIcon(himl, hicon); - - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_COMPUTER)); - giComputer = ImageList_AddIcon(himl, hicon); - - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_HUB)); - giHub = ImageList_AddIcon(himl, hicon); - - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NODEVICE)); - giNoDevice = ImageList_AddIcon(himl, hicon); - - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_SSICON)); - giGoodSsDevice = ImageList_AddIcon(himl, hicon); - - hicon = LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NOSSDEVICE)); - giNoSsDevice = ImageList_AddIcon(himl, hicon); - - TreeView_SetImageList(ghTreeWnd, himl, TVSIL_NORMAL); - // end add - } - - ghEditWnd = GetDlgItem(hWnd, IDC_EDIT); - -#ifdef H264_SUPPORT - // set the edit control to have a max text limit size - SendMessage(ghEditWnd, EM_LIMITTEXT, 0 /* USE DEFAULT MAX*/, 0); -#endif - - ghStatusWnd = GetDlgItem(hWnd, IDC_STATUS); - ghMainMenu = GetMenu(hWnd); - if (ghMainMenu == NULL) - { - OOPS(); - } - { - CHAR pszFont[256]; - CHAR pszHeight[8]; - - memset(pszFont, 0, sizeof(pszFont)); - LoadString(ghInstance, IDS_STANDARD_FONT, pszFont, sizeof(pszFont) - 1); - memset(pszHeight, 0, sizeof(pszHeight)); - LoadString(ghInstance, IDS_STANDARD_FONT_HEIGHT, pszHeight, sizeof(pszHeight) - 1); - - hFont = CreateFont((int) pszHeight[0], 0, 0, 0, - 400, 0, 0, 0, - 0, 1, 2, 1, - 49, pszFont); - } - SendMessage(ghEditWnd, - WM_SETFONT, - (WPARAM) hFont, - 0); - - RefreshTree(); - - return FALSE; -} - -/***************************************************************************** - -USBView_OnClose() - -*****************************************************************************/ - -VOID -USBView_OnClose ( - HWND hWnd - ) -{ - - UNREFERENCED_PARAMETER(hWnd); - - DestroyTree(); - - PostQuitMessage(0); -} - - -/***************************************************************************** - -AddItemInformationToFile() - -Saves the information about the current item to the list -*****************************************************************************/ -VOID -AddItemInformationToFile( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ) -{ - HRESULT hr = S_OK; - HANDLE hf = NULL; - DWORD dwBytesWritten = 0; - - hf = *((PHANDLE) pContext); - - ResetTextBuffer(); - - hr = UpdateTreeItemDeviceInfo(hTreeWnd, hTreeItem); - - if (FAILED(hr)) - { - OOPS(); - } - else - { - WriteFile(hf, GetTextBuffer(), GetTextBufferPos()*sizeof(CHAR), &dwBytesWritten, NULL); - } - - ResetTextBuffer(); -} - - - -/***************************************************************************** - -SaveAllInformationAsText() - -Saves the entire USB tree as a text file -*****************************************************************************/ -HRESULT -SaveAllInformationAsText( - LPTSTR lpstrTextFileName, - DWORD dwCreationDisposition - ) -{ - HRESULT hr = S_OK; - HANDLE hf = NULL; - - hf = CreateFile(lpstrTextFileName, - GENERIC_WRITE, - 0, - NULL, - dwCreationDisposition, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hf == INVALID_HANDLE_VALUE) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OOPS(); - } - else - { - if (GetLastError() == ERROR_ALREADY_EXISTS) - { - // CreateFile() sets this error if we are overwriting an existing file - // Reset this error to avoid false alarms - SetLastError(0); - } - - if (ghTreeRoot == NULL) - { - // If tree has not been populated yet, try a refresh - RefreshTree(); - } - - if (ghTreeRoot) - { - - LockFile(hf, 0, 0, 0, 0); - WalkTreeTopDown(ghTreeRoot, AddItemInformationToFile, &hf, NULL); - UnlockFile(hf, 0, 0, 0, 0); - CloseHandle(hf); - - hr = S_OK; - } - else - { - hr = HRESULT_FROM_WIN32(GetLastError()); - OOPS(); - } - } - - ResetTextBuffer(); - return hr; -} - - -/***************************************************************************** - -USBView_OnCommand() - -*****************************************************************************/ - -VOID -USBView_OnCommand ( - HWND hWnd, - int id, - HWND hwndCtl, - UINT codeNotify - ) -{ - MENUITEMINFO menuInfo; - char szFile[MAX_PATH + 1]; - OPENFILENAME ofn; - HANDLE hf = NULL; - DWORD dwBytesWritten = 0; - int nTextLength = 0; - size_t lengthToNull = 0; - HRESULT hr = S_OK; - - UNREFERENCED_PARAMETER(hwndCtl); - UNREFERENCED_PARAMETER(codeNotify); - - //initialize save dialog variables - memset(szFile, 0, sizeof(szFile)); - memset(&ofn, 0, sizeof(OPENFILENAME)); - - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = hWnd; - ofn.nFilterIndex = 1; - ofn.lpstrFile = szFile; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrFileTitle = NULL; - ofn.nMaxFileTitle = 0; - ofn.lpstrInitialDir = 0; - ofn.lpstrTitle = NULL; - ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; - - - switch (id) - { - case ID_AUTO_REFRESH: - gDoAutoRefresh = !gDoAutoRefresh; - menuInfo.cbSize = sizeof(menuInfo); - menuInfo.fMask = MIIM_STATE; - menuInfo.fState = gDoAutoRefresh ? MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(ghMainMenu, - id, - FALSE, - &menuInfo); - break; - - case ID_SAVE: - { - // initialize the save file name - StringCchCopy(szFile, MAX_PATH, "USBView.txt"); - ofn.lpstrFilter = "Text\0*.TXT\0\0"; - ofn.lpstrDefExt = "txt"; - - //call dialog box - if (! GetSaveFileName(&ofn)) - { - OOPS(); - break; - } - - //create new file - hf = CreateFile((LPTSTR)ofn.lpstrFile, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (hf == INVALID_HANDLE_VALUE) - { - OOPS(); - } - else - { - char *szText = NULL; - - //get data from display window to transfer to file - nTextLength = GetWindowTextLength(ghEditWnd); - nTextLength++; - - szText = ALLOC((DWORD)nTextLength); - if (NULL != szText) - { - GetWindowText(ghEditWnd, (LPSTR) szText, nTextLength); - - // - // Constrain length to the first null, which should be at - // the end of the window text. This prevents writing extra - // null characters. - // - if (StringCchLength(szText, nTextLength, &lengthToNull) == S_OK) - { - nTextLength = (int) lengthToNull; - - //lock the file, write to the file, unlock file - LockFile(hf, 0, 0, 0, 0); - - WriteFile(hf, szText, nTextLength, &dwBytesWritten, NULL); - - UnlockFile(hf, 0, 0, 0, 0); - } - else - { - OOPS(); - } - CloseHandle(hf); - FREE(szText); - } - else - { - OOPS(); - } - } - - break; - } - - case ID_SAVEALL: - { - // initialize the save file name - StringCchCopy(szFile, MAX_PATH, "USBViewAll.txt"); - ofn.lpstrFilter = "Text\0*.txt\0\0"; - ofn.lpstrDefExt = "txt"; - - //call dialog box - if (! GetSaveFileName(&ofn)) - { - OOPS(); - break; - } - - // Save the file, overwrite in case of UI since UI gives popup for confirmation - hr = SaveAllInformationAsText(ofn.lpstrFile, CREATE_ALWAYS); - if (FAILED(hr)) - { - OOPS(); - } - - break; - } - - case ID_SAVEXML: - { - // initialize the save file name - StringCchCopy(szFile, MAX_PATH, "USBViewAll.xml"); - ofn.lpstrFilter = "Xml\0*.xml\0\0"; - ofn.lpstrDefExt = "xml"; - - //call dialog box - if (! GetSaveFileName(&ofn)) - { - OOPS(); - break; - } - - // Save the file, overwrite in case of UI since UI gives popup for confirmation - hr = SaveAllInformationAsXml(ofn.lpstrFile, CREATE_ALWAYS); - if (FAILED(hr)) - { - OOPS(); - } - - break; - } - - case ID_CONFIG_DESCRIPTORS: - gDoConfigDesc = !gDoConfigDesc; - menuInfo.cbSize = sizeof(menuInfo); - menuInfo.fMask = MIIM_STATE; - menuInfo.fState = gDoConfigDesc ? MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(ghMainMenu, - id, - FALSE, - &menuInfo); - break; - - case ID_ANNOTATION: - gDoAnnotation = !gDoAnnotation; - menuInfo.cbSize = sizeof(menuInfo); - menuInfo.fMask = MIIM_STATE; - menuInfo.fState = gDoAnnotation ? MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(ghMainMenu, - id, - FALSE, - &menuInfo); - break; - - case ID_LOG_DEBUG: - gLogDebug = !gLogDebug; - menuInfo.cbSize = sizeof(menuInfo); - menuInfo.fMask = MIIM_STATE; - menuInfo.fState = gLogDebug ? MFS_CHECKED : MFS_UNCHECKED; - SetMenuItemInfo(ghMainMenu, - id, - FALSE, - &menuInfo); - break; - - case ID_ABOUT: - DialogBox(ghInstance, - MAKEINTRESOURCE(IDD_ABOUT), - ghMainWnd, - (DLGPROC) AboutDlgProc); - break; - - case ID_EXIT: - UnregisterDeviceNotification(gNotifyDevHandle); - UnregisterDeviceNotification(gNotifyHubHandle); - DestroyTree(); - PostQuitMessage(0); - break; - - case ID_REFRESH: - RefreshTree(); - break; - } -} - -/***************************************************************************** - -USBView_OnLButtonDown() - -*****************************************************************************/ - -VOID -USBView_OnLButtonDown ( - HWND hWnd, - BOOL fDoubleClick, - int x, - int y, - UINT keyFlags - ) -{ - - UNREFERENCED_PARAMETER(fDoubleClick); - UNREFERENCED_PARAMETER(x); - UNREFERENCED_PARAMETER(y); - UNREFERENCED_PARAMETER(keyFlags); - - gbButtonDown = TRUE; - SetCapture(hWnd); -} - -/***************************************************************************** - -USBView_OnLButtonUp() - -*****************************************************************************/ - -VOID -USBView_OnLButtonUp ( - HWND hWnd, - int x, - int y, - UINT keyFlags - ) -{ - - UNREFERENCED_PARAMETER(hWnd); - UNREFERENCED_PARAMETER(x); - UNREFERENCED_PARAMETER(y); - UNREFERENCED_PARAMETER(keyFlags); - - gbButtonDown = FALSE; - ReleaseCapture(); -} - -/***************************************************************************** - -USBView_OnMouseMove() - -*****************************************************************************/ - -VOID -USBView_OnMouseMove ( - HWND hWnd, - int x, - int y, - UINT keyFlags - ) -{ - UNREFERENCED_PARAMETER(hWnd); - UNREFERENCED_PARAMETER(y); - UNREFERENCED_PARAMETER(keyFlags); - - SetCursor(ghSplitCursor); - - if (gbButtonDown) - { - ResizeWindows(TRUE, x); - } -} - -/***************************************************************************** - -USBView_OnSize(); - -*****************************************************************************/ - -VOID -USBView_OnSize ( - HWND hWnd, - UINT state, - int cx, - int cy - ) -{ - UNREFERENCED_PARAMETER(hWnd); - UNREFERENCED_PARAMETER(state); - UNREFERENCED_PARAMETER(cx); - UNREFERENCED_PARAMETER(cy); - - ResizeWindows(FALSE, 0); -} - -/***************************************************************************** - -USBView_OnNotify() - -*****************************************************************************/ - -LRESULT -USBView_OnNotify ( - HWND hWnd, - int DlgItem, - LPNMHDR lpNMHdr - ) -{ - UNREFERENCED_PARAMETER(hWnd); - UNREFERENCED_PARAMETER(DlgItem); - - if (lpNMHdr->code == TVN_SELCHANGED) - { - HTREEITEM hTreeItem; - - hTreeItem = ((NM_TREEVIEW *)lpNMHdr)->itemNew.hItem; - - if (hTreeItem) - { - UpdateEditControl(ghEditWnd, - ghTreeWnd, - hTreeItem); - } - } - - return 0; -} - - -/***************************************************************************** - -USBView_OnDeviceChange() - -*****************************************************************************/ - -BOOL -USBView_OnDeviceChange ( - HWND hwnd, - UINT uEvent, - DWORD dwEventData - ) -{ - UNREFERENCED_PARAMETER(hwnd); - UNREFERENCED_PARAMETER(dwEventData); - - if (gDoAutoRefresh) - { - switch (uEvent) - { - case DBT_DEVICEARRIVAL: - case DBT_DEVICEREMOVECOMPLETE: - RefreshTree(); - break; - } - } - - return TRUE; -} - - - -/***************************************************************************** - -DestroyTree() - -*****************************************************************************/ - -VOID DestroyTree (VOID) -{ - // Clear the selection of the TreeView, so that when the tree is - // destroyed, the control won't try to constantly "shift" the - // selection to another item. - // - TreeView_SelectItem(ghTreeWnd, NULL); - - // Destroy the current contents of the TreeView - // - if (ghTreeRoot) - { - WalkTree(ghTreeRoot, CleanupItem, NULL); - - TreeView_DeleteAllItems(ghTreeWnd); - - ghTreeRoot = NULL; - } - - ClearDeviceList(&gDeviceList); - ClearDeviceList(&gHubList); -} - -/***************************************************************************** - -RefreshTree() - -*****************************************************************************/ - -VOID RefreshTree (VOID) -{ - CHAR statusText[128]; - ULONG devicesConnected; - - // Clear the edit control - // - SetWindowText(ghEditWnd, ""); - - // Destroy the current contents of the TreeView - // - DestroyTree(); - - // Create the root tree node - // - ghTreeRoot = AddLeaf(TVI_ROOT, 0, "My Computer", ComputerIcon); - - if (ghTreeRoot != NULL) - { - // Enumerate all USB buses and populate the tree - // - EnumerateHostControllers(ghTreeRoot, &devicesConnected); - - // - // Expand all tree nodes - // - WalkTree(ghTreeRoot, ExpandItem, NULL); - - // Update Status Line with number of devices connected - // - memset(statusText, 0, sizeof(statusText)); - StringCchPrintf(statusText, sizeof(statusText), -#ifdef H264_SUPPORT - "UVC Spec Version: %d.%d Version: %d.%d Devices Connected: %d Hubs Connected: %d", - UVC_SPEC_MAJOR_VERSION, UVC_SPEC_MINOR_VERSION, USBVIEW_MAJOR_VERSION, USBVIEW_MINOR_VERSION, - devicesConnected, TotalHubs); -#else - "Devices Connected: %d Hubs Connected: %d", - devicesConnected, TotalHubs); -#endif - - SetWindowText(ghStatusWnd, statusText); - } - else - { - OOPS(); - } - -} - -/***************************************************************************** - -AboutDlgProc() - -*****************************************************************************/ - -LRESULT CALLBACK -AboutDlgProc ( - HWND hwnd, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ) -{ - UNREFERENCED_PARAMETER(lParam); - - switch (uMsg) - { - case WM_INITDIALOG: - { - HRESULT hr; - char TextBuffer[TEXT_ITEM_LENGTH]; - HWND hItem; - - hItem = GetDlgItem(hwnd, IDC_VERSION); - - if (hItem != NULL) - { - hr = StringCbPrintfA(TextBuffer, - sizeof(TextBuffer), - "USBView version: %d.%d", - USBVIEW_MAJOR_VERSION, - USBVIEW_MINOR_VERSION); - if (SUCCEEDED(hr)) - { - SetWindowText(hItem,TextBuffer); - } - } - - hItem = GetDlgItem(hwnd, IDC_UVCVERSION); - - if (hItem != NULL) - { - hr = StringCbPrintfA(TextBuffer, - sizeof(TextBuffer), - "USB Video Class Spec version: %d.%d", - UVC_SPEC_MAJOR_VERSION, - UVC_SPEC_MINOR_VERSION); - if (SUCCEEDED(hr)) - { - SetWindowText(hItem,TextBuffer); - } - } - } - break; - case WM_COMMAND: - - switch (LOWORD(wParam)) - { - case IDOK: - case IDCANCEL: - - EndDialog (hwnd, 0); - break; - } - break; - - } - - return FALSE; -} - - -/***************************************************************************** - -AddLeaf() - -*****************************************************************************/ - -HTREEITEM -AddLeaf ( - HTREEITEM hTreeParent, - LPARAM lParam, - _In_ LPTSTR lpszText, - TREEICON TreeIcon - ) -{ - TV_INSERTSTRUCT tvins; - HTREEITEM hti; - - memset(&tvins, 0, sizeof(tvins)); - - // Set the parent item - // - tvins.hParent = hTreeParent; - - tvins.hInsertAfter = TVI_LAST; - - // pszText and lParam members are valid - // - tvins.item.mask = TVIF_TEXT | TVIF_PARAM; - - // Set the text of the item. - // - tvins.item.pszText = lpszText; - - // Set the user context item - // - tvins.item.lParam = lParam; - - // Add the item to the tree-view control. - // - hti = TreeView_InsertItem(ghTreeWnd, &tvins); - - // added - tvins.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE; - tvins.item.hItem = hti; - - // Determine which icon to display for the device - // - switch (TreeIcon) - { - case ComputerIcon: - tvins.item.iImage = giComputer; - tvins.item.iSelectedImage = giComputer; - break; - - case HubIcon: - tvins.item.iImage = giHub; - tvins.item.iSelectedImage = giHub; - break; - - case NoDeviceIcon: - tvins.item.iImage = giNoDevice; - tvins.item.iSelectedImage = giNoDevice; - break; - - case GoodDeviceIcon: - tvins.item.iImage = giGoodDevice; - tvins.item.iSelectedImage = giGoodDevice; - break; - - case GoodSsDeviceIcon: - tvins.item.iImage = giGoodSsDevice; - tvins.item.iSelectedImage = giGoodSsDevice; - break; - - case NoSsDeviceIcon: - tvins.item.iImage = giNoSsDevice; - tvins.item.iSelectedImage = giNoSsDevice; - break; - - case BadDeviceIcon: - default: - tvins.item.iImage = giBadDevice; - tvins.item.iSelectedImage = giBadDevice; - break; - } - TreeView_SetItem(ghTreeWnd, &tvins.item); - - return hti; -} - - -/***************************************************************************** - -WalkTreeTopDown() - -*****************************************************************************/ - -VOID -WalkTreeTopDown( - _In_ HTREEITEM hTreeItem, - _In_ LPFNTREECALLBACK lpfnTreeCallback, - _In_opt_ PVOID pContext, - _In_opt_ LPFNTREENOTIFYCALLBACK lpfnTreeNotifyCallback - ) -{ - if (hTreeItem) - { - HTREEITEM hTreeChild = TreeView_GetChild(ghTreeWnd, hTreeItem); - HTREEITEM hTreeSibling = TreeView_GetNextSibling(ghTreeWnd, hTreeItem); - - // - // Call the lpfnCallBack on the node itself. - // - (*lpfnTreeCallback)(ghTreeWnd, hTreeItem, pContext); - - // - // Recursively call WalkTree on the node's first child. - // - - if (hTreeChild) - { - WalkTreeTopDown(hTreeChild, - lpfnTreeCallback, - pContext, - lpfnTreeNotifyCallback); - } - - // - // Recursively call WalkTree on the node's first sibling. - // - if (hTreeSibling) - { - WalkTreeTopDown(hTreeSibling, - lpfnTreeCallback, - pContext, - lpfnTreeNotifyCallback); - } - else - { - // If there are no more siblings, we have reached the end of - // list of child nodes. Call notify function - if (lpfnTreeNotifyCallback != NULL) - { - (*lpfnTreeNotifyCallback)(pContext); - } - } - } -} - -/***************************************************************************** - -WalkTree() - -*****************************************************************************/ - -VOID -WalkTree ( - _In_ HTREEITEM hTreeItem, - _In_ LPFNTREECALLBACK lpfnTreeCallback, - _In_opt_ PVOID pContext - ) -{ - if (hTreeItem) - { - // Recursively call WalkTree on the node's first child. - // - WalkTree(TreeView_GetChild(ghTreeWnd, hTreeItem), - lpfnTreeCallback, - pContext); - - // - // Call the lpfnCallBack on the node itself. - // - (*lpfnTreeCallback)(ghTreeWnd, hTreeItem, pContext); - - // - // - // Recursively call WalkTree on the node's first sibling. - // - WalkTree(TreeView_GetNextSibling(ghTreeWnd, hTreeItem), - lpfnTreeCallback, - pContext); - } -} - -/***************************************************************************** - -ExpandItem() - -*****************************************************************************/ - -VOID -ExpandItem ( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ) -{ - // - // Make this node visible. - // - UNREFERENCED_PARAMETER(pContext); - - TreeView_Expand(hTreeWnd, hTreeItem, TVE_EXPAND); -} - -/***************************************************************************** - -SaveAllInformationAsXML() - -Saves the entire USB tree as an XML file -*****************************************************************************/ -HRESULT -SaveAllInformationAsXml( - LPTSTR lpstrTextFileName, - DWORD dwCreationDisposition - ) -{ - HRESULT hr = S_OK; - - if (ghTreeRoot == NULL) - { - // If tree has not been populated yet, try a refresh - RefreshTree(); - } - if (ghTreeRoot) - { - WalkTreeTopDown(ghTreeRoot, AddItemInformationToXmlView, NULL, XmlNotifyEndOfNodeList); - - hr = SaveXml(lpstrTextFileName, dwCreationDisposition); - } - else - { - hr = E_FAIL; - OOPS(); - } - ResetTextBuffer(); - return hr; -} - -//***************************************************************************** -// -// AddItemInformationToXmlView -// -// hTreeItem - Handle of selected TreeView item for which information should -// be added to the XML View -// -//***************************************************************************** -VOID -AddItemInformationToXmlView( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ) -{ - TV_ITEM tvi; - PVOID info; - PCHAR tviName = NULL; - - UNREFERENCED_PARAMETER(pContext); - -#ifdef H264_SUPPORT - ResetErrorCounts(); -#endif - - tviName = (PCHAR) ALLOC(256); - - if (NULL == tviName) - { - return; - } - - // - // Get the name of the TreeView item, along with the a pointer to the - // info we stored about the item in the item's lParam. - // - - tvi.mask = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM; - tvi.hItem = hTreeItem; - tvi.pszText = (LPSTR) tviName; - tvi.cchTextMax = 256; - - TreeView_GetItem(hTreeWnd, - &tvi); - - info = (PVOID)tvi.lParam; - - if (NULL != info) - { - // - // Add Item to XML object - // - switch (*(PUSBDEVICEINFOTYPE)info) - { - case HostControllerInfo: - XmlAddHostController(tviName, (PUSBHOSTCONTROLLERINFO) info); - break; - - case RootHubInfo: - XmlAddRootHub(tviName, (PUSBROOTHUBINFO) info); - break; - - case ExternalHubInfo: - XmlAddExternalHub(tviName, (PUSBEXTERNALHUBINFO) info); - break; - - case DeviceInfo: - XmlAddUsbDevice(tviName, (PUSBDEVICEINFO) info); - break; - } - - } - return; -} - -/***************************************************************************** - -DisplayLastError() - -*****************************************************************************/ - -DWORD -DisplayLastError( - _Inout_updates_bytes_(count) char *szString, - int count) -{ - LPVOID lpMsgBuf; - - // get the last error code - DWORD dwError = GetLastError(); - - // get the system message for this error code - if (FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - dwError, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL )) - { - StringCchPrintf(szString, count, "Error: %s", (LPTSTR)lpMsgBuf ); - } - - // Free the local buffer - LocalFree( lpMsgBuf ); - - // return the error - return dwError; -} - -#if DBG - -/***************************************************************************** - -Oops() - -*****************************************************************************/ - -VOID -Oops -( - _In_ PCHAR File, - ULONG Line - ) -{ - char szBuf[1024]; - LPTSTR lpMsgBuf; - DWORD dwGLE = GetLastError(); - - memset(szBuf, 0, sizeof(szBuf)); - - // get the system message for this error code - if (FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dwGLE, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR) &lpMsgBuf, - 0, - NULL)) - { - StringCchPrintf(szBuf, sizeof(szBuf), - "File: %s, Line %d\r\nGetLastError 0x%x %u %s\n", - File, Line, dwGLE, dwGLE, lpMsgBuf); - } - else - { - StringCchPrintf(szBuf, sizeof(szBuf), - "File: %s, Line %d\r\nGetLastError 0x%x %u\r\n", - File, Line, dwGLE, dwGLE); - } - OutputDebugString(szBuf); - - // Free the system allocated local buffer - LocalFree(lpMsgBuf); - - return; -} - -#endif diff --git a/tests/projects/winsdk/usbview/uvcview.h b/tests/projects/winsdk/usbview/uvcview.h deleted file mode 100644 index d5c3f5786..000000000 --- a/tests/projects/winsdk/usbview/uvcview.h +++ /dev/null @@ -1,675 +0,0 @@ -/*++ - -Copyright (c) 1997-2008 Microsoft Corporation - -Module Name: - - UVCVIEW.H - -Abstract: - - This is the header file for UVCVIEW - -Environment: - - user mode - -Revision History: - - 04-25-97 : created - 04/13/2005 : major bug fixing - ---*/ - -/***************************************************************************** - I N C L U D E S -*****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// This is mostly a private USB Audio descriptor header -#include "usbdesc.h" - -// This is the inbox USBVideo driver descriptor header (copied locally) -#include "uvcdesc.h" - -/***************************************************************************** - P R A G M A S -*****************************************************************************/ - -#pragma once - -/***************************************************************************** - D E F I N E S -*****************************************************************************/ - -// define H264_SUPPORT to add H.264 support to uvcview.exe -#define H264_SUPPORT - -#define TEXT_ITEM_LENGTH 64 - -#ifdef DEBUG -#undef DBG -#define DBG 1 -#endif - -#if DBG -#define OOPS() Oops(__FILE__, __LINE__) -#else -#define OOPS() -#endif - -#if DBG - -#define ALLOC(dwBytes) MyAlloc(__FILE__, __LINE__, (dwBytes)) - -#define REALLOC(hMem, dwBytes) MyReAlloc((hMem), (dwBytes)) - -#define FREE(hMem) MyFree((hMem)) - -#define CHECKFORLEAKS() MyCheckForLeaks() - -#else - -#define ALLOC(dwBytes) GlobalAlloc(GPTR,(dwBytes)) - -#define REALLOC(hMem, dwBytes) GlobalReAlloc((hMem), (dwBytes), (GMEM_MOVEABLE|GMEM_ZEROINIT)) - -#define FREE(hMem) GlobalFree((hMem)) - -#define CHECKFORLEAKS() - -#endif - -#define DEVICE_CONFIGURATION_TEXT_LENGTH 10240 - -#define STR_INVALID_POWER_STATE "(invalid state) " -#define STR_UNKNOWN_CONTROLLER_FLAVOR "Unknown" - -FORCEINLINE -VOID -InitializeListHead( - _Out_ PLIST_ENTRY ListHead - ) -{ - ListHead->Flink = ListHead->Blink = ListHead; -} - -// -// BOOLEAN -// IsListEmpty( -// PLIST_ENTRY ListHead -// ); -// - -#define IsListEmpty(ListHead) \ - ((ListHead)->Flink == (ListHead)) - -// -// PLIST_ENTRY -// RemoveHeadList( -// PLIST_ENTRY ListHead -// ); -// - -#define RemoveHeadList(ListHead) \ - (ListHead)->Flink;\ - {RemoveEntryList((ListHead)->Flink)} - -// -// VOID -// RemoveEntryList( -// PLIST_ENTRY Entry -// ); -// - -#define RemoveEntryList(Entry) {\ - PLIST_ENTRY _EX_Blink;\ - PLIST_ENTRY _EX_Flink;\ - _EX_Flink = (Entry)->Flink;\ - _EX_Blink = (Entry)->Blink;\ - _EX_Blink->Flink = _EX_Flink;\ - _EX_Flink->Blink = _EX_Blink;\ - } - -// -// VOID -// InsertTailList( -// PLIST_ENTRY ListHead, -// PLIST_ENTRY Entry -// ); -// - -#define InsertTailList(ListHead,Entry) {\ - PLIST_ENTRY _EX_Blink;\ - PLIST_ENTRY _EX_ListHead;\ - _EX_ListHead = (ListHead);\ - _EX_Blink = _EX_ListHead->Blink;\ - (Entry)->Flink = _EX_ListHead;\ - (Entry)->Blink = _EX_Blink;\ - _EX_Blink->Flink = (Entry);\ - _EX_ListHead->Blink = (Entry);\ - } - -// global version for USB Video Class spec version (pre-release) -#define BCDVDC 0x0083 - -// A.2 Video Interface Subclass Codes -#define SC_VIDEO_INTERFACE_COLLECTION 0x03 - -// A.3 Video Interface Protocol Codes -#define PC_PROTOCOL_UNDEFINED 0x00 - -// USB Video Class spec version -#define NOT_UVC 0x0 -#define UVC10 0x100 -#define UVC11 0x110 - -#ifdef H264_SUPPORT -#define UVC15 0x150 -#endif - -#define OUTPUT_MESSAGE_MAX_LENGTH 1024 -#define MAX_DEVICE_PROP 200 -#define MAX_DRIVER_KEY_NAME 256 - -/***************************************************************************** - T Y P E D E F S -*****************************************************************************/ - -typedef enum _TREEICON -{ - ComputerIcon, - HubIcon, - NoDeviceIcon, - GoodDeviceIcon, - BadDeviceIcon, - GoodSsDeviceIcon, - NoSsDeviceIcon -} TREEICON; - -// Callback function for walking TreeView items -// -typedef VOID -(*LPFNTREECALLBACK)( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext -); - - -// Callback notification function called at end of every tree depth -typedef VOID -(*LPFNTREENOTIFYCALLBACK)(PVOID pContext); - -// -// Structure used to build a linked list of String Descriptors -// retrieved from a device. -// - -typedef struct _STRING_DESCRIPTOR_NODE -{ - struct _STRING_DESCRIPTOR_NODE *Next; - UCHAR DescriptorIndex; - USHORT LanguageID; - USB_STRING_DESCRIPTOR StringDescriptor[1]; -} STRING_DESCRIPTOR_NODE, *PSTRING_DESCRIPTOR_NODE; - -// -// A collection of device properties. The device can be hub, host controller or usb device -// -typedef struct _USB_DEVICE_PNP_STRINGS -{ - PCHAR DeviceId; - PCHAR DeviceDesc; - PCHAR HwId; - PCHAR Service; - PCHAR DeviceClass; - PCHAR PowerState; -} USB_DEVICE_PNP_STRINGS, *PUSB_DEVICE_PNP_STRINGS; - -typedef struct _DEVICE_INFO_NODE { - HDEVINFO DeviceInfo; - LIST_ENTRY ListEntry; - SP_DEVINFO_DATA DeviceInfoData; - SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; - PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceDetailData; - PSTR DeviceDescName; - ULONG DeviceDescNameLength; - PSTR DeviceDriverName; - ULONG DeviceDriverNameLength; - DEVICE_POWER_STATE LatestDevicePowerState; -} DEVICE_INFO_NODE, *PDEVICE_INFO_NODE; - -// -// Structures assocated with TreeView items through the lParam. When an item -// is selected, the lParam is retrieved and the structure it which it points -// is used to display information in the edit control. -// - -typedef enum _USBDEVICEINFOTYPE -{ - HostControllerInfo, - RootHubInfo, - ExternalHubInfo, - DeviceInfo -} USBDEVICEINFOTYPE, *PUSBDEVICEINFOTYPE; - -typedef struct _USBHOSTCONTROLLERINFO -{ - USBDEVICEINFOTYPE DeviceInfoType; - LIST_ENTRY ListEntry; - PCHAR DriverKey; - ULONG VendorID; - ULONG DeviceID; - ULONG SubSysID; - ULONG Revision; - USB_POWER_INFO USBPowerInfo[6]; - BOOL BusDeviceFunctionValid; - ULONG BusNumber; - USHORT BusDevice; - USHORT BusFunction; - PUSB_CONTROLLER_INFO_0 ControllerInfo; - PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; -} USBHOSTCONTROLLERINFO, *PUSBHOSTCONTROLLERINFO; - -typedef struct _USBROOTHUBINFO -{ - USBDEVICEINFOTYPE DeviceInfoType; - PUSB_NODE_INFORMATION HubInfo; - PUSB_HUB_INFORMATION_EX HubInfoEx; - PCHAR HubName; - PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps; - PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; - PDEVICE_INFO_NODE DeviceInfoNode; - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx; - -} USBROOTHUBINFO, *PUSBROOTHUBINFO; - -typedef struct _USBEXTERNALHUBINFO -{ - USBDEVICEINFOTYPE DeviceInfoType; - PUSB_NODE_INFORMATION HubInfo; - PUSB_HUB_INFORMATION_EX HubInfoEx; - PCHAR HubName; - PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo; - PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps; - PUSB_DESCRIPTOR_REQUEST ConfigDesc; - PUSB_DESCRIPTOR_REQUEST BosDesc; - PSTRING_DESCRIPTOR_NODE StringDescs; - PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2; // NULL if root HUB - PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; - PDEVICE_INFO_NODE DeviceInfoNode; - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx; -} USBEXTERNALHUBINFO, *PUSBEXTERNALHUBINFO; - - -// HubInfo, HubName may be in USBDEVICEINFOTYPE, so they can be removed -typedef struct -{ - USBDEVICEINFOTYPE DeviceInfoType; - PUSB_NODE_INFORMATION HubInfo; // NULL if not a HUB - PUSB_HUB_INFORMATION_EX HubInfoEx; // NULL if not a HUB - PCHAR HubName; // NULL if not a HUB - PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo; // NULL if root HUB - PUSB_PORT_CONNECTOR_PROPERTIES PortConnectorProps; - PUSB_DESCRIPTOR_REQUEST ConfigDesc; // NULL if root HUB - PUSB_DESCRIPTOR_REQUEST BosDesc; // NULL if root HUB - PSTRING_DESCRIPTOR_NODE StringDescs; - PUSB_NODE_CONNECTION_INFORMATION_EX_V2 ConnectionInfoV2; // NULL if root HUB - PUSB_DEVICE_PNP_STRINGS UsbDeviceProperties; - PDEVICE_INFO_NODE DeviceInfoNode; - PUSB_HUB_CAPABILITIES_EX HubCapabilityEx; // NULL if not a HUB -} USBDEVICEINFO, *PUSBDEVICEINFO; - -typedef struct _STRINGLIST -{ -#ifdef H264_SUPPORT - ULONGLONG ulFlag; -#else - ULONG ulFlag; -#endif - PCHAR pszString; - PCHAR pszModifier; - -} STRINGLIST, * PSTRINGLIST; - -typedef struct _DEVICE_GUID_LIST { - HDEVINFO DeviceInfo; - LIST_ENTRY ListHead; -} DEVICE_GUID_LIST, *PDEVICE_GUID_LIST; - - -/***************************************************************************** - G L O B A L S -*****************************************************************************/ - -// -// USBVIEW.C -// - -BOOL gDoConfigDesc; -BOOL gDoAnnotation; -BOOL gLogDebug; -int TotalHubs; - -// -// ENUM.C -// - -PCHAR ConnectionStatuses[]; - -// -// DISPVID.C -// -DEFINE_GUID(YUY2_Format,0x32595559L,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); -DEFINE_GUID(NV12_Format,0x3231564EL,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); - -#ifdef H264_SUPPORT -DEFINE_GUID(H264_Format,0x34363248, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71); -#endif - -// The following flags/variables are all initialized in Display.c InitializePerDeviceSettings() -// -// Save the default frame from the MJPEG, Uncompressed, Vendor and Frame Based Format descriptor -// Check for this when processing the individual Frame descriptors -UCHAR g_chMJPEGFrameDefault; -UCHAR g_chUNCFrameDefault; -UCHAR g_chVendorFrameDefault; -UCHAR g_chFrameBasedFrameDefault; - -// Spec version of UVC device -UINT g_chUVCversion; - -// Base address of the USBDEVICEINFO for device we're parsing -PUSBDEVICEINFO CurrentUSBDeviceInfo; - -// Base address of the Configuration descriptor we're parsing -PUSB_CONFIGURATION_DESCRIPTOR CurrentConfigDesc; - -// Length of the current configuration descriptor -DWORD dwConfigLength; -// Our current position from the beginning of the config descriptor -DWORD dwConfigIndex; - -// -// DISPLAY.C -// -int gDeviceSpeed; - -// Save the current Configuration starting and ending addresses -// Used in ValidateDescAddress() -// -PUSB_CONFIGURATION_DESCRIPTOR g_pConfigDesc; -PSTRING_DESCRIPTOR_NODE g_pStringDescs; -PUCHAR g_descEnd; - -/***************************************************************************** - F U N C T I O N P R O T O T Y P E S -*****************************************************************************/ - -// -// USBVIEW.C -// - -HTREEITEM -AddLeaf ( - HTREEITEM hTreeParent, - LPARAM lParam, - _In_ LPTSTR lpszText, - TREEICON TreeIcon -); - -VOID -Oops -( - _In_ PCHAR File, - ULONG Line -); - -// -// DISPLAY.C -// - -EXTERN_C UINT IsIADDevice (PUSBDEVICEINFO info); -EXTERN_C UINT IsUVCDevice (PUSBDEVICEINFO info); -EXTERN_C PCHAR GetVendorString(USHORT idVendor); -EXTERN_C PCHAR GetLangIDString(USHORT idLang); -EXTERN_C UINT GetConfigurationSize (PUSBDEVICEINFO info); -EXTERN_C PUSB_COMMON_DESCRIPTOR -GetNextDescriptor( - _In_reads_bytes_(TotalLength) - PUSB_COMMON_DESCRIPTOR FirstDescriptor, - _In_ - ULONG TotalLength, - _In_ - PUSB_COMMON_DESCRIPTOR StartDescriptor, - _In_ long - DescriptorType - ); - -HRESULT -UpdateTreeItemDeviceInfo( - HWND hTreeWnd, - HTREEITEM hTreeItem - ); - -PCHAR -GetTextBuffer( -); - -BOOL -ResetTextBuffer( -); - -BOOL -CreateTextBuffer ( -); - -VOID -DestroyTextBuffer ( -); - -UINT -GetTextBufferPos ( -); - -VOID -UpdateEditControl ( - HWND hEditWnd, - HWND hTreeWnd, - HTREEITEM hTreeItem -); - - -VOID __cdecl -AppendBuffer ( - LPCTSTR lpFormat, - ... -); - -VOID __cdecl -AppendTextBuffer ( - LPCTSTR lpFormat, - ... -); - -VOID -DisplayStringDescriptor ( - UCHAR Index, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState -); - -PCHAR -GetStringFromList( - PSTRINGLIST slPowerState, - ULONG ulNumElements, - -#ifdef H264_SUPPORT - ULONGLONG ulFlag, -#else - ULONG ulFlag, -#endif - _In_ PCHAR szDefault - ); - -EXTERN_C PCHAR GetPowerStateString( - WDMUSB_POWER_STATE powerState - ); - -EXTERN_C PCHAR GetControllerFlavorString( - USB_CONTROLLER_FLAVOR flavor - ); - -EXTERN_C ULONG GetEhciDebugPort( - ULONG vendorId, - ULONG deviceId - ); - -VOID -WalkTreeTopDown( - _In_ HTREEITEM hTreeItem, - _In_ LPFNTREECALLBACK lpfnTreeCallback, - _In_opt_ PVOID pContext, - _In_opt_ LPFNTREENOTIFYCALLBACK lpfnTreeNotifyCallback - ); - -VOID RefreshTree (VOID); - -// -// ENUM.C -// - -VOID -EnumerateHostControllers ( - HTREEITEM hTreeParent, - ULONG *DevicesConnected - ); - - -VOID -CleanupItem ( - HWND hTreeWnd, - HTREEITEM hTreeItem, - PVOID pContext - ); - -DEVICE_POWER_STATE -AcquireDevicePowerState( - _Inout_ PDEVICE_INFO_NODE pNode - ); - -_Success_(return == TRUE) -BOOL -GetDeviceProperty( - _In_ HDEVINFO DeviceInfoSet, - _In_ PSP_DEVINFO_DATA DeviceInfoData, - _In_ DWORD Property, - _Outptr_ LPTSTR *ppBuffer - ); - -void -ClearDeviceList( - PDEVICE_GUID_LIST DeviceList - ); - -// -// DEBUG.C -// - -_Success_(return != NULL) -_Post_writable_byte_size_(dwBytes) -HGLOBAL -MyAlloc ( - _In_ PCHAR File, - ULONG Line, - DWORD dwBytes - ); - -_Success_(return != NULL) -_Post_writable_byte_size_(dwBytes) -HGLOBAL -MyReAlloc ( - HGLOBAL hMem, - DWORD dwBytes - ); - -HGLOBAL -MyFree ( - HGLOBAL hMem - ); - -VOID -MyCheckForLeaks ( - VOID - ); - -// -// DEVNODE.C -// - - -PUSB_DEVICE_PNP_STRINGS -DriverNameToDeviceProperties( - _In_reads_bytes_(cbDriverName) PCHAR DriverName, - _In_ size_t cbDriverName - ); - -VOID FreeDeviceProperties( - _In_ PUSB_DEVICE_PNP_STRINGS *ppDevProps - ); -// -// DISPAUD.C -// - -BOOL -DisplayAudioDescriptor ( - PUSB_AUDIO_COMMON_DESCRIPTOR CommonDesc, - UCHAR bInterfaceSubClass - ); - -// -// DISPVID.C -// - -BOOL -DisplayVideoDescriptor ( - PVIDEO_SPECIFIC VidCommonDesc, - UCHAR bInterfaceSubClass, - PSTRING_DESCRIPTOR_NODE StringDescs, - DEVICE_POWER_STATE LatestDevicePowerState - ); - -// -// DISPLAY.C -// - -BOOL -ValidateDescAddress ( - PUSB_COMMON_DESCRIPTOR commonDesc - ); diff --git a/tests/projects/winsdk/usbview/uvcview.rc b/tests/projects/winsdk/usbview/uvcview.rc deleted file mode 100644 index 6c7642ce3..000000000 --- a/tests/projects/winsdk/usbview/uvcview.rc +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include "resource.h" -#include - -////////////////////////////////////////////////////////////////////////////// -// -// VERSION -// -#define VER_FILEDESCRIPTION_STR "Microsoft\256 Windows(TM) USB device viewer" -#define VER_INTERNALNAME_STR "USBView" -#define VER_ORIGINALFILENAME_STR VER_INTERNALNAME_STR -#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corporation 1996-2011 All Rights Reserved." - -#define VER_FILETYPE VFT_APP -#define VER_FILESUBTYPE VFT2_UNKNOWN - -#include - - -////////////////////////////////////////////////////////////////////////////// -// -// ICON -// -IDI_ICON ICON DISCARDABLE "USB.ICO" -IDI_BADICON ICON DISCARDABLE "BANG.ICO" -IDI_COMPUTER ICON DISCARDABLE "MONITOR.ICO" -IDI_HUB ICON DISCARDABLE "HUB.ICO" -IDI_NODEVICE ICON DISCARDABLE "PORT.ICO" -IDI_NOSSDEVICE ICON DISCARDABLE "SSPORT.ICO" -IDI_SSICON ICON DISCARDABLE "SSUSB.ICO" - -////////////////////////////////////////////////////////////////////////////// -// -// Cursor -// -IDC_SPLIT CURSOR DISCARDABLE "SPLIT.CUR" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_MAINDIALOG DIALOGEX 0, 0, 415, 243 -STYLE WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | - WS_THICKFRAME -CAPTION "USB Device Viewer" -MENU IDR_MENU -FONT 8, "MS Shell Dlg" -BEGIN - CONTROL "Tree1",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | - TVS_HASLINES | TVS_LINESATROOT | WS_BORDER | WS_TABSTOP, - 0,0,120,234,WS_EX_CLIENTEDGE - EDITTEXT IDC_EDIT,120,0,295,234,ES_MULTILINE | ES_READONLY | - WS_VSCROLL | WS_HSCROLL - CONTROL "Devices Connected: 0",IDC_STATUS,"msctls_statusbar32", - SBARS_SIZEGRIP, - 0,235,415,8 -END - - -IDD_ABOUT DIALOG DISCARDABLE 0, 0, 230, 117 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About USBView" -FONT 8, "MS Shell Dlg" -BEGIN - DEFPUSHBUTTON "OK",IDOK,90,100,50,14 - LTEXT "USB Device Viewer",IDC_STATIC,54,15,104,8 - LTEXT VER_LEGALCOPYRIGHT_STR,IDC_STATIC,54,45,145,8 - EDITTEXT IDC_VERSION,54,60,110,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER - EDITTEXT IDC_UVCVERSION,54,75,110,8,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER - ICON IDI_ICON,IDC_STATIC,15,15,21,20 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_MENU MENU DISCARDABLE -BEGIN - POPUP "&File" - BEGIN - MENUITEM "&Refresh\tF5", ID_REFRESH - MENUITEM SEPARATOR - MENUITEM "Save Current &View ..." ID_SAVE - MENUITEM "Save As (&txt) ...", ID_SAVEALL - MENUITEM "Save As (&xml) ...\tF2", ID_SAVEXML - MENUITEM SEPARATOR - - MENUITEM "E&xit", ID_EXIT - END - POPUP "&Options" - BEGIN - MENUITEM "&Auto Refresh", ID_AUTO_REFRESH, CHECKED - MENUITEM "Show &Config Descriptors", ID_CONFIG_DESCRIPTORS, CHECKED - MENUITEM SEPARATOR -// MENUITEM "&Show Description Annotations", ID_ANNOTATION, CHECKED - MENUITEM "&Log to debugger", ID_LOG_DEBUG - END - POPUP "&Help" - BEGIN - MENUITEM "&About", ID_ABOUT - END -END - -////////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDACCEL ACCELERATORS DISCARDABLE -BEGIN - VK_F5, ID_REFRESH, VIRTKEY,NOINVERT - VK_F2, ID_SAVEXML, VIRTKEY,NOINVERT -END - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDS_STRINGBASE "Base string" -END - -STRINGTABLE -BEGIN - IDS_STANDARD_FONT "Courier" - IDS_STANDARD_FONT_HEIGHT "\13" - IDS_STANDARD_FONT_WIDTH "\8" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_USBVIEW_USAGE "usbview usage:\nusbview [/?]\n\t/? - this usage message.\ - \n\t/q quiet mode, does not display 'Press any key to continue ...\n\t\ - \nusbview [/q] [/f] /saveall:\ - \n\tsaveall - saves the USB tree view as a text file\ - \n\t/f - overwrite file if it already exists\n\nusbview [/q] [/f] /savexml:\ - \n\tsavexml - saves the USB tree view as a xml file\n\t/f - overwrite file if it already exists\n\n" - IDS_USBVIEW_PRESSKEY "Press any key to continue ...\n" - IDS_USBVIEW_INVALIDARG "Invalid argument: [%1]\n" - IDS_USBVIEW_FILE_EXISTS_TXT "File: [%1] already exists, try `usbview /f /saveall:[%1]` to force overwrite\n" - IDS_USBVIEW_FILE_EXISTS_XML "File: [%1] already exists, try `usbview /f /savexml:[%1]` to force overwrite\n" - IDS_USBVIEW_INTERNAL_ERROR "An internal error occured, please report this as a bug\n" - IDS_USBVIEW_SAVED_TO "Usbview information saved to file : [%1]\n" - IDS_USBVIEW_INVALID_FILENAME "The argument : [%1] is invalid or incomplete.\n" -END - diff --git a/tests/projects/winsdk/usbview/vndrlist.h b/tests/projects/winsdk/usbview/vndrlist.h deleted file mode 100644 index ccf21267b..000000000 --- a/tests/projects/winsdk/usbview/vndrlist.h +++ /dev/null @@ -1,11036 +0,0 @@ -/*++ - -Copyright (c) 1997-2008 Microsoft Corporation - -Module Name: - - VNDRLIST.H - -Abstract: - - This header file contains a list of all currently known USB Vendor IDs - and the vendor name associated with each Vendor ID. - -Source: - - http://www.usb.org - -Environment: - - Kernel & user mode - -Revision History: - - 04-25-97 : created - 03-28-03 : refreshed with latest list from usb.org - 05-04-05 : refreshed with latest list from usb.org - 05-02-07 : refreshed with latest list from usb.org - 03-19-08 : refreshed with latest list from usb.org - ---*/ - -#ifndef __VNDRLIST_H__ -#define __VNDRLIST_H__ - -// -// Vendor ID structure -// -typedef struct _VENDOR_ID { - USHORT usVendorID; - PCHAR szVendor; -} VENDOR_ID, *PVENDOR_ID; - -// -// This list built from information obtained from -// http://www.usb.org/developers/tools/ -// -// This information has not been independently verified and no claims -// are made here as to its accuracy. -// -// 10978 total -// -VENDOR_ID USBVendorIDs[] = -{ - { 0x0079, "Shenzhen Longshengwei Technology, Co., Ltd." }, - { 0x013A, "Aimgene Technology Co., Ltd" }, - { 0x03CC, "GN OTOMETRICS" }, - { 0x03E8, "EndPoints Inc." }, - { 0x03E9, "Thesys Microelectronics" }, - { 0x03EA, "Data Broadcasting Corp." }, - { 0x03EB, "Atmel Corporation" }, - { 0x03EC, "Iwatsu America Inc." }, - { 0x03ED, "Mitel Corporation" }, - { 0x03EE, "Mitsumi" }, - { 0x03F0, "HP Inc." }, - { 0x03F1, "Genoa Technology" }, - { 0x03F2, "Oak Technology, Inc" }, - { 0x03F3, "Adaptec, Inc." }, - { 0x03F4, "Diebold, Inc." }, - { 0x03F5, "Siemens Electromechanical" }, - { 0x03F7, "Tulip Computers International" }, - { 0x03F8, "Epson Imaging Technology Center" }, - { 0x03F9, "KeyTronic Corp." }, - { 0x03FB, "OPTi Inc." }, - { 0x03FC, "Elitegroup Computer Systems" }, - { 0x03FD, "Xilinx Inc." }, - { 0x03FE, "Farallon Comunications" }, - { 0x03FF, "Weitek Corporation" }, - { 0x0400, "National Semiconductor" }, - { 0x0401, "National Registry Inc." }, - { 0x0402, "ALi Corporation" }, - { 0x0403, "Future Technology Devices International Limited" }, - { 0x0404, "NCR Corporation" }, - { 0x0405, "inSilicon" }, - { 0x0406, "Fujitsu-ICL Computers" }, - { 0x0407, "Fujitsu Personal Systems, Inc." }, - { 0x0408, "Quanta Computer Inc." }, - { 0x0409, "NEC Corporation" }, - { 0x040A, "Eastman Kodak Company" }, - { 0x040B, "Weltrend Semiconductor" }, - { 0x040C, "VTech Computers Ltd" }, - { 0x040D, "VIA Technologies, Inc." }, - { 0x040E, "MCCI Corporation" }, - { 0x040F, "Echo Speech Corporation" }, - { 0x0410, "Isis Distributed Systems, Inc." }, - { 0x0411, "BUFFALO INC." }, - { 0x0412, "Award Software International" }, - { 0x0413, "Leadtek Research Inc." }, - { 0x0414, "Giga-Byte Technology Co., Ltd." }, - { 0x0416, "Nuvoton Technology Corp." }, - { 0x0417, "Symbios, Inc." }, - { 0x0418, "AST Research" }, - { 0x0419, "Samsung Info. Systems America Inc." }, - { 0x041A, "Phoenix Technologies Ltd." }, - { 0x041B, "d'TV" }, - { 0x041D, "S3 Incorporated" }, - { 0x041E, "Creative Labs" }, - { 0x041F, "LCS Telegraphics" }, - { 0x0420, "Chips and Technologies" }, - { 0x0421, "Nokia Corporation" }, - { 0x0422, "ADI Systems Inc." }, - { 0x0423, "CATC" }, - { 0x0424, "Microchip-SMSC" }, - { 0x0425, "Freescale Semiconductor Hong Kong Limited" }, - { 0x0426, "Integrated Device Technology" }, - { 0x0427, "Motorola Electronics Taiwan Ltd." }, - { 0x0428, "Advanced Gravis Computer Ltd." }, - { 0x0429, "Cirrus Logic Inc." }, - { 0x042A, "Ericsson Austrian, AG" }, - { 0x042C, "Innovative Semiconductors, Inc." }, - { 0x042D, "Micronics" }, - { 0x042E, "Acer, Inc.(2)" }, - { 0x042F, "Molex Inc." }, - { 0x0430, "Fujitsu Component Limited" }, - { 0x0431, "ITAC Systems, Inc." }, - { 0x0432, "Unisys Corp." }, - { 0x0433, "Alps Electric Inc." }, - { 0x0434, "Samsung Info. Systems America Inc.(2)" }, - { 0x0435, "Hyundai Electronics America" }, - { 0x0436, "Taugagreining HF" }, - { 0x0437, "Framatome Connectors USA" }, - { 0x0438, "Advanced Micro Devices" }, - { 0x0439, "Voice Technologies Group" }, - { 0x043C, "Lucid Designs" }, - { 0x043D, "Lexmark International Inc." }, - { 0x043E, "LG Electronics USA Inc." }, - { 0x043F, "RadiSys Corporation" }, - { 0x0440, "EIZO NANAO CORPORATION" }, - { 0x0441, "Winbond Systems Lab." }, - { 0x0442, "Cygnion Corp." }, - { 0x0443, "Gateway 2000" }, - { 0x0445, "Agere Systems" }, - { 0x0446, "NMB Technologies Corporation" }, - { 0x0447, "Momentum Microsystems" }, - { 0x0449, "Eldim" }, - { 0x044A, "Shamrock Technology Co., Ltd." }, - { 0x044B, "WSI" }, - { 0x044C, "CCL/ITRI" }, - { 0x044D, "Siemens Nixdorf AG" }, - { 0x044E, "Alps Electric Co., Ltd." }, - { 0x044F, "ThrustMaster, Inc." }, - { 0x0450, "DFI Inc." }, - { 0x0451, "Texas Instruments" }, - { 0x0452, "Mitsubishi Electric & Electronics US, Inc." }, - { 0x0453, "CMD Technology" }, - { 0x0454, "Vobis Microcomputer AGO" }, - { 0x0455, "Telematics International, Inc." }, - { 0x0456, "Analog Devices, Inc." }, - { 0x0457, "Silicon Integrated Systems Corp." }, - { 0x0458, "KYE Systems Corp." }, - { 0x0459, "Adobe Systems, Inc." }, - { 0x045A, "SONICblue Incorporated" }, - { 0x045B, "Renesas Electronics Corp." }, - { 0x045D, "Nortel Networks" }, - { 0x045E, "Microsoft Corporation" }, - { 0x0460, "Ace Cad Enterprise Co., Ltd." }, - { 0x0461, "Primax Electronics" }, - { 0x0463, "EATON" }, - { 0x0464, "AMP/Tycoelectronics" }, - { 0x0465, "Pacific Micro Computing" }, - { 0x0467, "AT&T Paradyne" }, - { 0x0468, "Wieson Technologies Co., Ltd." }, - { 0x046A, "CHERRY" }, - { 0x046B, "American Megatrends" }, - { 0x046C, "Toshiba Corporation, Digital Media Network Company" }, - { 0x046D, "Logitech Inc." }, - { 0x046E, "Behavior Tech Computer Corporation" }, - { 0x046F, "Crystal Semiconductor" }, - { 0x0471, "Philips Consumer Lifestyle BV" }, - { 0x0472, "Oracle" }, - { 0x0473, "Sanyo Information Business Co., Ltd." }, - { 0x0474, "Sanyo Electric Co. Ltd." }, - { 0x0475, "TECO Electric & Machinery Co., Ltd." }, - { 0x0476, "AESP" }, - { 0x0477, "Seagate Technology" }, - { 0x0478, "Connectix Corp." }, - { 0x0479, "Advanced Peripheral Laboratories" }, - { 0x047A, "Semtech Corporation" }, - { 0x047B, "Silitek Corp." }, - { 0x047D, "Kensington" }, - { 0x047E, "Avago Technologies Inc." }, - { 0x047F, "Plantronics, Inc." }, - { 0x0480, "Toshiba America Info. Systems, Inc." }, - { 0x0481, "Zenith Data Systems" }, - { 0x0482, "Kyocera Corporation" }, - { 0x0483, "STMicroelectronics" }, - { 0x0484, "Specialix" }, - { 0x0485, "Nokia Monitors" }, - { 0x0486, "ASUS Computers Inc." }, - { 0x0487, "Stewart Connector" }, - { 0x0488, "Cirque Corporation" }, - { 0x0489, "Foxconn - Hon Hai" }, - { 0x048A, "S-MOS Systems, Inc." }, - { 0x048C, "Alps Electric Ireland Ltd." }, - { 0x048D, "ITE Tech Inc." }, - { 0x048F, "Eicon Tech." }, - { 0x0490, "United Microelectronic Corporation (UMC)" }, - { 0x0491, "Capetronic Kaohsiung Corp." }, - { 0x0492, "Samsung Semiconductor, Inc." }, - { 0x0493, "MAG Technology Co., Ltd." }, - { 0x0495, "ESS Technology, Inc." }, - { 0x0496, "Micron Electronics" }, - { 0x0497, "Smile International, Inc." }, - { 0x0498, "Capetronic (Kaohsiung) Corp." }, - { 0x0499, "Yamaha Corporation" }, - { 0x049A, "Gandalf Technologies Ltd." }, - { 0x049B, "Curtis Computer Products" }, - { 0x049C, "Acer Advanced Labs, Inc." }, - { 0x049D, "VLSI Technology, Inc." }, - { 0x049F, "Compaq Computer Corporation" }, - { 0x04A0, "Digital Equipment Corp." }, - { 0x04A1, "SystemSoft Corporation" }, - { 0x04A2, "FirePower Systems" }, - { 0x04A3, "Trident Microsystems Inc." }, - { 0x04A4, "Hitachi, Ltd." }, - { 0x04A5, "BenQ Corporation" }, - { 0x04A6, "Nokia Display Products" }, - { 0x04A7, "Visioneer" }, - { 0x04A8, "Multivideo Labs, Inc." }, - { 0x04A9, "Canon Inc." }, - { 0x04AA, "Daewoo Teletech Co., Ltd." }, - { 0x04AB, "Chromatic Research" }, - { 0x04AC, "Micro Audiometrics Corp." }, - { 0x04AD, "Dooin Electronics" }, - { 0x04AE, "Brooktree Corporation" }, - { 0x04AF, "Winnov L.P." }, - { 0x04B0, "Nikon Corporation" }, - { 0x04B1, "Pan International" }, - { 0x04B3, "IBM Corporation" }, - { 0x04B4, "Cypress Semiconductor" }, - { 0x04B5, "ROHM Co., Ltd." }, - { 0x04B6, "Hint Corporation" }, - { 0x04B7, "Compal Electronics, Inc." }, - { 0x04B8, "Seiko Epson Corp." }, - { 0x04B9, "SafeNet, Inc." }, - { 0x04BA, "Toucan Systems Limited" }, - { 0x04BB, "I-O Data Device, Inc." }, - { 0x04BC, "Digital Systems Associates" }, - { 0x04BD, "Toshiba Electronics Taiwan Corp." }, - { 0x04BE, "Telia Research AB" }, - { 0x04BF, "TDK Corporation" }, - { 0x04C2, "Methode Electronics Far East Pte Ltd." }, - { 0x04C3, "Maxi Switch, Inc." }, - { 0x04C4, "Lockheed Martin Energy Research" }, - { 0x04C5, "Fujitsu Ltd." }, - { 0x04C6, "Toshiba America Electronic Components" }, - { 0x04C7, "Micro Macro Technologies" }, - { 0x04C8, "Konica Corporation" }, - { 0x04CA, "Lite-On Technology Corp." }, - { 0x04CB, "FUJIFILM Corporation" }, - { 0x04CC, "ST-Ericsson" }, - { 0x04CD, "Tatung Company of America, Inc." }, - { 0x04CE, "ScanLogic Corporation" }, - { 0x04CF, "Myson Century, Inc." }, - { 0x04D0, "Digi International" }, - { 0x04D1, "ITT Cannon" }, - { 0x04D2, "Altec Lansing Technologies, Inc." }, - { 0x04D3, "VidUS, Inc." }, - { 0x04D4, "LSI Logic Inc." }, - { 0x04D5, "Forte Technologies, Inc." }, - { 0x04D6, "Mentor Graphics" }, - { 0x04D7, "Oki Semiconductor" }, - { 0x04D8, "Microchip Technology Inc." }, - { 0x04D9, "Holtek Semiconductor, Inc." }, - { 0x04DA, "Panasonic Corporation" }, - { 0x04DB, "Hypertec Ltd." }, - { 0x04DC, "Huan Hsin Holdings Ltd." }, - { 0x04DD, "Sharp Corporation" }, - { 0x04DE, "MindShare, Inc." }, - { 0x04DF, "ePadLink" }, - { 0x04E1, "Iiyama Corporation" }, - { 0x04E2, "Exar Corporation" }, - { 0x04E3, "Zilog" }, - { 0x04E4, "ACC Microelectronics" }, - { 0x04E5, "Promise Technology" }, - { 0x04E6, "Identiv, Inc." }, - { 0x04E7, "Elo TouchSystems" }, - { 0x04E8, "Samsung Electronics Co., Ltd." }, - { 0x04E9, "PC-Tel, Inc." }, - { 0x04EA, "Sipex Corporation" }, - { 0x04EB, "Northstar Systems Corp." }, - { 0x04EC, "Tokyo Electron Device Limited" }, - { 0x04ED, "Annabooks" }, - { 0x04EF, "Pacific Electronic International, Inc." }, - { 0x04F0, "Daewoo Electronics Co., Ltd." }, - { 0x04F1, "Victor Company of Japan, Limited" }, - { 0x04F2, "Chicony Electronics Co., Ltd." }, - { 0x04F3, "ELAN Microelectronics Corportation" }, - { 0x04F4, "Harting Elektronik Inc." }, - { 0x04F5, "Fujitsu-ICL Systems, Inc." }, - { 0x04F6, "Norand Corporation" }, - { 0x04F7, "Newnex Technology Corp." }, - { 0x04F8, "FuturePlus Systems" }, - { 0x04F9, "Brother Industries, Ltd." }, - { 0x04FA, "Dallas Semiconductor" }, - { 0x04FB, "Biostar Microtech Int'l Corp." }, - { 0x04FC, "SUNPLUS TECHNOLOGY CO., LTD." }, - { 0x04FD, "Soliton Systems K.K." }, - { 0x04FE, "PFU Limited" }, - { 0x04FF, "E-CMOS Corp." }, - { 0x0500, "Siam United Hi-Tech" }, - { 0x0501, "Fujikura/DDK" }, - { 0x0502, "Acer, Inc." }, - { 0x0503, "Hitachi America Ltd." }, - { 0x0504, "Hayes Microcomputer Products" }, - { 0x0505, "Digital Home Corporation" }, - { 0x0506, "3Com Corporation" }, - { 0x0507, "Hosiden Corporation" }, - { 0x0508, "Clarion Co., Ltd." }, - { 0x0509, "Aztech Systems Ltd" }, - { 0x050A, "Cinch Connectors" }, - { 0x050B, "Cable System International" }, - { 0x050C, "InnoMedia, Inc." }, - { 0x050D, "Belkin International, Inc." }, - { 0x050E, "Neon Technology, Inc." }, - { 0x050F, "KC Technology Inc." }, - { 0x0510, "Sejin Electron Inc." }, - { 0x0511, "N*ABLE Technologies, Inc (Data Book)" }, - { 0x0512, "Hualon Microelectronics Corp." }, - { 0x0513, "digital-X, Inc." }, - { 0x0514, "FCI Electronics" }, - { 0x0515, "ACTC" }, - { 0x0516, "Longwell Electronics/Longwell Company" }, - { 0x0517, "Butterfly Communications" }, - { 0x0518, "EzKEY Corp." }, - { 0x0519, "Star Micronics Co., LTD" }, - { 0x051A, "WYSE Technology" }, - { 0x051C, "Shuttle Inc." }, - { 0x051D, "American Power Conversion" }, - { 0x051E, "Scientific Atlanta, Inc." }, - { 0x051F, "IO Systems Inc." }, - { 0x0520, "Taiwan Semiconductor Manufacturing Co." }, - { 0x0521, "Airborn Connectors" }, - { 0x0522, "ACON, Advanced-Connectek, Inc." }, - { 0x0523, "ATEN GMBH" }, - { 0x0524, "Sola Electronics" }, - { 0x0525, "PLX Technology, Inc." }, - { 0x0526, "Temic MHS S.A." }, - { 0x0527, "ALTRA" }, - { 0x0528, "ATI Technologies, Inc." }, - { 0x0529, "SafeNet Data Security (Israel) Ltd." }, - { 0x052A, "Crescent Heart Software" }, - { 0x052B, "Tekom Technologies, Inc" }, - { 0x052C, "Canon Development Americas" }, - { 0x052D, "Avid Electronics Corp." }, - { 0x052E, "Standard Microsystems Corp. (1)" }, - { 0x052F, "Unicore Software, Inc." }, - { 0x0530, "American Microsystems Inc." }, - { 0x0531, "Wacom Technology Corp." }, - { 0x0532, "Systech Corporation" }, - { 0x0533, "Alcatel Mobile Phones" }, - { 0x0534, "Motorola" }, - { 0x0535, "LIH TZU Electric Co., Ltd." }, - { 0x0536, "Hand Held Products (Honeywell International Inc.)" }, - { 0x0537, "Inventec Corporation" }, - { 0x0538, "The SCO Group" }, - { 0x0539, "Shyh Shiun Terminals Co. LTD" }, - { 0x053A, "Preh KeyTec GmbH" }, - { 0x053B, "Global Village Communication" }, - { 0x053C, "Institut of Microelectronic & Mechatronic Systems" }, - { 0x053D, "Silicon Architect" }, - { 0x053E, "Mobility Electronics" }, - { 0x053F, "Synopsys, Inc." }, - { 0x0540, "UniAccess AB" }, - { 0x0541, "Sirf Technology, Inc" }, - { 0x0542, "MICOM Communications Corp." }, - { 0x0543, "ViewSonic Corporation" }, - { 0x0544, "Cristie Electronics Ltd." }, - { 0x0545, "Veo" }, - { 0x0546, "Polaroid Corporation" }, - { 0x0547, "Anchor Chips Inc." }, - { 0x0548, "Tyan Computer Corp." }, - { 0x0549, "Pixera Corporation" }, - { 0x054A, "Fujitsu Microelectronics, Inc." }, - { 0x054B, "New Media Corporation" }, - { 0x054C, "Sony Corporation" }, - { 0x054D, "Try Corporation" }, - { 0x054E, "Proside Corporation" }, - { 0x054F, "WYSE Technology Taiwan" }, - { 0x0550, "Fuji Xerox Co., Ltd." }, - { 0x0551, "CompuTrend Systems, Inc." }, - { 0x0552, "Philips Monitors" }, - { 0x0553, "STMicroelectronics Imaging Division" }, - { 0x0554, "Dictaphone Corp." }, - { 0x0555, "ANAM S&T Co., Ltd." }, - { 0x0556, "Asahi Kasei Microdevices Corporation" }, - { 0x0557, "ATEN International Co. Ltd." }, - { 0x0558, "Truevision, Inc." }, - { 0x0559, "Cadence Design Systems, Inc." }, - { 0x055A, "Kenwood USA" }, - { 0x055B, "KnowledgeTek, Inc." }, - { 0x055C, "Proton Electronic Ind." }, - { 0x055D, "Samsung Electro-Mechanics Co." }, - { 0x055E, "Optoma Corporation" }, - { 0x055F, "Mustek Systems Inc." }, - { 0x0560, "Interface Corporation" }, - { 0x0561, "Oasis Design, Inc." }, - { 0x0562, "Telex Communications Inc." }, - { 0x0563, "Immersion Corporation" }, - { 0x0564, "Kodak Digital Product Center, Japan Ltd." }, - { 0x0565, "Peracom Networks, Inc." }, - { 0x0566, "Monterey International Corp." }, - { 0x0567, "Xyratex" }, - { 0x0568, "Quartz Ingenierie" }, - { 0x0569, "SegaSoft" }, - { 0x056A, "WACOM Co., Ltd." }, - { 0x056B, "Decicon Incorporated" }, - { 0x056C, "Belkin Research & Development" }, - { 0x056D, "EIZO Corporation" }, - { 0x056E, "Elecom Co., Ltd." }, - { 0x056F, "Korea Data Systems Co., Ltd." }, - { 0x0570, "Epson America" }, - { 0x0571, "XLR8, Inc." }, - { 0x0572, "Conexant Systems, Inc." }, - { 0x0573, "Zoran Corporation" }, - { 0x0574, "City University of Hong Kong" }, - { 0x0575, "Philips Creative Display Solutions" }, - { 0x0576, "BAFO/Quality Computer Accessories" }, - { 0x0577, "ELSA" }, - { 0x0578, "Intrinsix Corp." }, - { 0x0579, "GVC Corporation" }, - { 0x057A, "Samsung Electronics America" }, - { 0x057B, "Y-E Data, Inc." }, - { 0x057C, "AVM GmbH" }, - { 0x057D, "Shark Multimedia Inc." }, - { 0x057E, "Nintendo Co., Ltd." }, - { 0x057F, "QuickShot Limited" }, - { 0x0580, "Denron Inc." }, - { 0x0581, "Racal Data Group" }, - { 0x0582, "Roland Corporation" }, - { 0x0583, "Padix Co., Ltd." }, - { 0x0584, "RATOC Systems, Inc." }, - { 0x0585, "FlashPoint Technology, Inc." }, - { 0x0586, "ZyXEL Communications Corp" }, - { 0x0587, "Matsushita Kotobuki Electronics Industries America" }, - { 0x0588, "Sapien Design" }, - { 0x0589, "Victron" }, - { 0x058A, "Nohau Corporation" }, - { 0x058B, "Infineon Technologies" }, - { 0x058C, "In Focus Systems" }, - { 0x058D, "Micrel Semiconductor" }, - { 0x058E, "Tripath Technology Inc." }, - { 0x058F, "Alcor Micro, Corp." }, - { 0x0590, "OMRON Corporation" }, - { 0x0591, "Questra Consulting" }, - { 0x0592, "Powerware Corporation" }, - { 0x0593, "Incite" }, - { 0x0594, "Princeton Graphic Systems" }, - { 0x0595, "Zoran Microelectronics Ltd." }, - { 0x0596, "3M Touch Systems" }, - { 0x0597, "Trisignal Communications" }, - { 0x0598, "Niigata Canotec Co., Inc." }, - { 0x0599, "Brilliance Semiconductor Inc." }, - { 0x059A, "Spectrum Signal Processing Inc." }, - { 0x059B, "Iomega Corporation" }, - { 0x059C, "A-Trend Technology Co., Ltd." }, - { 0x059D, "Advanced Input Devices" }, - { 0x059E, "Intelligent Instrumentation" }, - { 0x059F, "LaCie" }, - { 0x05A0, "Vetronix Corporation" }, - { 0x05A1, "UKC Electronics Corporation" }, - { 0x05A2, "Fuji Film Microdevices Co. Ltd." }, - { 0x05A3, "TransDimension-NH LLC" }, - { 0x05A4, "Ortek Technology, Inc." }, - { 0x05A5, "Sampo Technology Corp." }, - { 0x05A6, "Cisco Systems, Inc." }, - { 0x05A7, "Bose Corporation" }, - { 0x05A8, "Spacetec IMC Corporation" }, - { 0x05A9, "OmniVision Technologies, Inc." }, - { 0x05AA, "Utilux South China Ltd." }, - { 0x05AB, "In-System Design" }, - { 0x05AC, "Apple" }, - { 0x05AD, "Y.C. Cable U.S.A., Inc" }, - { 0x05AE, "Synopsys, Inc.(2)" }, - { 0x05AF, "Sunrex Technology Corp." }, - { 0x05B0, "Fountain Technologies, Inc" }, - { 0x05B1, "First International Computer, Inc." }, - { 0x05B2, "Focus Electronics" }, - { 0x05B4, "HYUNDAI Electronics Industries Co., Ltd." }, - { 0x05B5, "Dialogic Corp" }, - { 0x05B6, "Proxima Corporation" }, - { 0x05B7, "Medianix Semiconductor, Inc." }, - { 0x05B8, "Sysgration" }, - { 0x05B9, "Philips Research Laboratories" }, - { 0x05BA, "DigitalPersona, Inc." }, - { 0x05BB, "Grey Cell Systems" }, - { 0x05BD, "RAFI GmbH & Co. KG" }, - { 0x05BE, "Tyco Electronics Corp., a TE Connectivity Ltd. company" }, - { 0x05BF, "S & S Research" }, - { 0x05C0, "Keil Software" }, - { 0x05C1, "MegaChips Corporation" }, - { 0x05C2, "Media Phonics (Suisse) S.A." }, - { 0x05C3, "VME Microsystems" }, - { 0x05C5, "Digi International Inc." }, - { 0x05C6, "Qualcomm, Inc" }, - { 0x05C7, "Qtronix Corp" }, - { 0x05C8, "Foxlink/Cheng Uei Precision Industry Co., Ltd" }, - { 0x05C9, "Semtech" }, - { 0x05CA, "Ricoh Company Ltd." }, - { 0x05CB, "PowerVision Technologies Inc." }, - { 0x05CC, "Neue ELSA GmbH" }, - { 0x05CD, "Silicom LTD." }, - { 0x05CE, "sci-worx GmbH" }, - { 0x05CF, "Sung Forn Co. LTD." }, - { 0x05D0, "GE Medical Systems Lunar" }, - { 0x05D1, "Brainboxes Limited" }, - { 0x05D2, "Wave Systems Corp." }, - { 0x05D3, "Tohoku Ricoh Co., Ltd." }, - { 0x05D5, "Super Gate Technology Co., LTD" }, - { 0x05D6, "Philips Semiconductors, CICT" }, - { 0x05D7, "Thomas & Betts" }, - { 0x05D8, "Ultima Electronics Corp." }, - { 0x05D9, "TPG IPB, Inc." }, - { 0x05DA, "Microtek International Inc." }, - { 0x05DB, "Sun Corporation" }, - { 0x05DC, "Lexar Media, Inc." }, - { 0x05DD, "Delta Electronics Inc." }, - { 0x05DE, "Crucial Technology" }, - { 0x05DF, "Silicon Vision Inc." }, - { 0x05E0, "Symbol Technologies" }, - { 0x05E1, "Syntek Semiconductor Co., Ltd." }, - { 0x05E2, "ElecVision Inc." }, - { 0x05E3, "Genesys Logic, Inc." }, - { 0x05E4, "Red Wing Corporation" }, - { 0x05E5, "Fuji Electric Co., Ltd." }, - { 0x05E6, "Keithley Instruments" }, - { 0x05E7, "EIZO Nanao Technologies Inc." }, - { 0x05E8, "ICC, Inc." }, - { 0x05E9, "Kawasaki Microelectronics America, Inc." }, - { 0x05EA, "Evergreen Systems International" }, - { 0x05EB, "FFC Limited" }, - { 0x05EC, "COM21, Inc." }, - { 0x05EE, "Cytechinfo Inc." }, - { 0x05EF, "Anko Electronic Co., Ltd." }, - { 0x05F0, "Canopus Co., Ltd." }, - { 0x05F2, "Dexin Corporation, Ltd." }, - { 0x05F3, "PI Engineering, Inc." }, - { 0x05F4, "Davis AS" }, - { 0x05F5, "Unixtar Technology Inc." }, - { 0x05F6, "Envision Peripherals, Inc." }, - { 0x05F7, "Silicon Portals Inc." }, - { 0x05F8, "Phase Metrics" }, - { 0x05F9, "Datalogic ADC" }, - { 0x05FA, "Siemens Telecommunications Systems Limited" }, - { 0x05FC, "Harman Multimedia" }, - { 0x05FD, "STD Manufacturing Ltd." }, - { 0x05FE, "CHIC TECHNOLOGY CORP" }, - { 0x05FF, "LeCroy Corporation" }, - { 0x0600, "Barco" }, - { 0x0601, "Jazz Hipster Corporation" }, - { 0x0602, "Vista Imaging Inc." }, - { 0x0603, "Novatek Microelectronics Corp." }, - { 0x0604, "Jean Co, Ltd." }, - { 0x0605, "Anchor C&C Co., Ltd." }, - { 0x0606, "Royal Information Electronics Co., Ltd." }, - { 0x0607, "Bridge Information Co., Ltd." }, - { 0x0608, "Genrad Ads" }, - { 0x0609, "SMK Manufacturing Inc." }, - { 0x060A, "Worth Data, Inc." }, - { 0x060B, "Solid Year Co., LTD." }, - { 0x060C, "EEH Datalink Gmbh" }, - { 0x060D, "Auctor Corporation" }, - { 0x060E, "Transmonde Technologies, Inc." }, - { 0x060F, "Joinsoon Electronics Mfg. Co., Ltd." }, - { 0x0610, "Costar Electronics Inc." }, - { 0x0611, "JVCKENWOOD Nagaoka Corp." }, - { 0x0612, "TV Interactive Corp." }, - { 0x0613, "TransAct Technologies Incorporated" }, - { 0x0614, "Bio-Rad Laboratories" }, - { 0x0615, "Quabbin Wire & Cable Co., INC." }, - { 0x0616, "Future Techno Designs PVT. LTD." }, - { 0x0617, "Swiss Federal Institute of Technology" }, - { 0x0618, "Chia Shin Technology Corp." }, - { 0x0619, "Seiko Instruments Inc." }, - { 0x061A, "Veridicom2" }, - { 0x061B, "Promptus Communications, Inc." }, - { 0x061C, "Act Labs, Ltd." }, - { 0x061D, "Quatech, Inc." }, - { 0x061E, "Nissei Electric Co." }, - { 0x0620, "Alaris, Inc." }, - { 0x0621, "ODU-Steckverbindungssysteme GmbH & Co. KG" }, - { 0x0622, "Iotech, Inc." }, - { 0x0623, "Littelfuse, Inc." }, - { 0x0624, "Avocent Corporation" }, - { 0x0625, "TiMedia Technology Co., Ltd." }, - { 0x0626, "Nippon Systems Development Co., Ltd." }, - { 0x0627, "Adomax Technology Co., Ltd." }, - { 0x0628, "Tasking Software Inc." }, - { 0x0629, "Zida Technologies Limited" }, - { 0x062A, "MosArt Semiconductor Corp." }, - { 0x062B, "Greatlink Electronics Taiwan Ltd." }, - { 0x062C, "Institute for Information Industry" }, - { 0x062D, "Taiwan Tai-Hao Enterprises Co. Ltd." }, - { 0x062E, "JPC-MAIN SUPER Inc." }, - { 0x062F, "Sin Sheng Terminal & Machine Inc." }, - { 0x0630, "ORL" }, - { 0x0631, "JUJO Electronics Corporation" }, - { 0x0632, "Marquette Medical Systems, Inc." }, - { 0x0633, "Cyrix Corporation" }, - { 0x0634, "Micron Technology, Inc." }, - { 0x0635, "Methode Electronics, Inc." }, - { 0x0636, "Sierra Imaging, Inc." }, - { 0x0637, "Gunz Limited" }, - { 0x0638, "Avision, Inc." }, - { 0x0639, "Chrontel, Inc." }, - { 0x063A, "Techwin Corporation" }, - { 0x063B, "Taugagreining HF (2)" }, - { 0x063C, "Yamaichi Electronics Co., Ltd. (Sakura)" }, - { 0x063D, "Fong Kai Industrial Co., Ltd." }, - { 0x063E, "RealMedia Technology, Inc." }, - { 0x063F, "New Technology Cable Ltd." }, - { 0x0640, "Hitex Development Tools" }, - { 0x0641, "Woods Industries, Inc." }, - { 0x0642, "VIA Medical Corporation" }, - { 0x0643, "NOVATUS, Inc." }, - { 0x0644, "TEAC Corporation" }, - { 0x0645, "Ethentica Inc." }, - { 0x0647, "Acton Research Corporation" }, - { 0x0649, "Weli Science Co., Ltd" }, - { 0x064A, "Technical Corp." }, - { 0x064B, "Analog Devices, Inc. Development Tools" }, - { 0x064C, "Ji-Haw Industrial Co., Ltd" }, - { 0x064D, "TriTech Microelectronics Ltd" }, - { 0x064E, "Suyin Corporation" }, - { 0x064F, "WIBU-Systems AG" }, - { 0x0650, "Dynapro Systems" }, - { 0x0651, "Likom Technology Sdn. Bhd." }, - { 0x0652, "Stargate Solutions, Inc." }, - { 0x0653, "CNF Inc." }, - { 0x0654, "Granite Microsystems, Inc." }, - { 0x0655, "Space Shuttle Hi-Tech Co.,Ltd." }, - { 0x0656, "Glory Mark Electronic Ltd." }, - { 0x0657, "Tekcon Electronics Corp." }, - { 0x0658, "Sigma Designs, Inc." }, - { 0x0659, "AETHRA" }, - { 0x065A, "Optoelectronics Co., Ltd." }, - { 0x065B, "Tracewell Systems" }, - { 0x065C, "Brentwood Medical Technology Corp." }, - { 0x065D, "ATTO Technology, Inc." }, - { 0x065E, "Silicon Graphics" }, - { 0x065F, "Good Way Technology Co., Ltd. & GWC technology Inc" }, - { 0x0660, "TSAY-E (BVI) International Inc." }, - { 0x0661, "Hamamatsu Photonics K.K." }, - { 0x0662, "Kansai Electric Co., Ltd." }, - { 0x0663, "Topmax Electronic Co., Ltd." }, - { 0x0664, "ET&T" }, - { 0x0665, "WayTech Development, Inc." }, - { 0x0667, "Antona Corporation" }, - { 0x0668, "WordWand" }, - { 0x0669, "Oce' Printing Systems GmbH" }, - { 0x066A, "Total Technologies, Ltd." }, - { 0x066B, "SCM Microsystems Japan, Inc." }, - { 0x066C, "ASK ASA" }, - { 0x066D, "Entrega Technologies Inc." }, - { 0x066E, "Acer Semiconductor America, Inc." }, - { 0x066F, "Freescale Semiconductor, Inc. - Sigmatel" }, - { 0x0670, "Sequel Imaging, Inc." }, - { 0x0671, "Keisoku Giken Co., Ltd." }, - { 0x0672, "Labtec Inc." }, - { 0x0673, "HCL Peripherals Limited" }, - { 0x0674, "Key Mouse Electronic Enterprise Co., Ltd." }, - { 0x0675, "DrayTek Corp." }, - { 0x0676, "Teles AG" }, - { 0x0677, "Aiwa Co., Ltd." }, - { 0x0678, "ACARD Technology Corp." }, - { 0x0679, "WaterGate Software, Inc." }, - { 0x067A, "ADS ANKER GmbH" }, - { 0x067B, "Prolific Technology, Inc." }, - { 0x067C, "Efficient Networks, Inc." }, - { 0x067D, "Hohner Corp." }, - { 0x067E, "Intermec Technologies (S) Pte Ltd." }, - { 0x067F, "Virata Ltd." }, - { 0x0680, "Realtek Semiconductor Corp., CPP Div." }, - { 0x0681, "Siemens Information and Communication Products" }, - { 0x0683, "Dataq Instruments, Inc." }, - { 0x0684, "Cytec Corporation" }, - { 0x0685, "ISDN*tek" }, - { 0x0686, "KONICA MINOLTA TECHNOLOGY CENTER, INC." }, - { 0x0687, "Sycard Technology" }, - { 0x0688, "Microprocess Ingenierie" }, - { 0x0689, "Elesys Inc." }, - { 0x068A, "Pertech Inc." }, - { 0x068B, "Potrans International, Inc." }, - { 0x068C, "Tokin Corporation, Card Media Systems Department" }, - { 0x068D, "Medical Measurement Systems B.V." }, - { 0x068E, "CH Products" }, - { 0x068F, "Nihon Kohden Corporation" }, - { 0x0690, "Golden Bridge Electech Inc." }, - { 0x0691, "Denter System Co., Ltd." }, - { 0x0692, "Klippel GmbH" }, - { 0x0693, "Hagiwara Solutions Co., Ltd." }, - { 0x0694, "The LEGO Company" }, - { 0x0695, "ODU-USA, Inc." }, - { 0x0696, "Carroll Touch" }, - { 0x0697, "Oxford Instruments (Medical Systems Division)" }, - { 0x0698, "Chuntex (CTX)" }, - { 0x0699, "Tektronix, Inc." }, - { 0x069A, "Askey Computer Corporation" }, - { 0x069B, "Technicolor SA" }, - { 0x069C, "HST High Soft Tech GmbH" }, - { 0x069D, "Hughes Network Systems (HNS)" }, - { 0x069E, "Welcat Inc." }, - { 0x069F, "Tron b.v." }, - { 0x06A0, "USB Systems Design" }, - { 0x06A1, "Alexon Co., Ltd." }, - { 0x06A2, "Topro Technology Inc." }, - { 0x06A3, "Logitech Europe S.A." }, - { 0x06A4, "Xiamen Doowell Electron Co., Ltd." }, - { 0x06A5, "Divio" }, - { 0x06A7, "MicroStore, Inc." }, - { 0x06A8, "Topaz Systems, Inc." }, - { 0x06A9, "Westell" }, - { 0x06AA, "Sysgration Ltd." }, - { 0x06AB, "Johnathon Freeman Technologies" }, - { 0x06AC, "Fujitsu Laboratories of America, Inc." }, - { 0x06AD, "Greatland Electronics Taiwan Ltd." }, - { 0x06AE, "Eurofins Digital Testing Belgium" }, - { 0x06AF, "Harting, Inc. of North America" }, - { 0x06B0, "Alva B.V." }, - { 0x06B1, "Signtech USA, Ltd." }, - { 0x06B2, "N*ABLE Technologies, Inc." }, - { 0x06B3, "Galil Motion Control" }, - { 0x06B4, "Citron GmbH" }, - { 0x06B5, "Stanford Research Systems" }, - { 0x06B6, "Leda Media Products" }, - { 0x06B8, "Pixela Corporation" }, - { 0x06B9, "Thomson Telecom" }, - { 0x06BA, "Smooth Cord & Connector Co., Ltd." }, - { 0x06BB, "EDA Inc." }, - { 0x06BC, "Oki Data Corporation" }, - { 0x06BD, "AGFA-Gevaert NV" }, - { 0x06BE, "AME Optimedia Technology Co. Ltd." }, - { 0x06BF, "Leoco Corporation" }, - { 0x06C0, "AllSpirit Co., Ltd." }, - { 0x06C2, "Microlynx Systems Ltd." }, - { 0x06C3, "Foss Tecator AB" }, - { 0x06C4, "Bizlink Technology, Inc." }, - { 0x06C5, "Hagenuk, GmbH" }, - { 0x06C6, "Infowave Software Inc." }, - { 0x06C7, "Storm Technology Inc." }, - { 0x06C8, "SIIG, Inc." }, - { 0x06C9, "Taxan (Europe) Ltd." }, - { 0x06CA, "Newer Technology, Inc." }, - { 0x06CB, "Synaptics Inc." }, - { 0x06CC, "Terayon Communication Systems" }, - { 0x06CD, "Keyspan" }, - { 0x06CE, "Contec Co., Ltd." }, - { 0x06CF, "Spheron VR- Bonnet und Steuerwald GdbR" }, - { 0x06D0, "LapLink, Inc." }, - { 0x06D1, "Daewoo Electronics Co Ltd" }, - { 0x06D2, "Pioneer Microsystems" }, - { 0x06D3, "Mitsubishi Electric Corporation" }, - { 0x06D4, "Cisco Systems(2)" }, - { 0x06D5, "Toshiba America Electronic Components, Inc." }, - { 0x06D6, "Aashima Technology B.V." }, - { 0x06D7, "Network Computing Devices (NCD)" }, - { 0x06D8, "Technical Marketing Research, Inc." }, - { 0x06D9, "Atmel-TEMIC Semiconductor GmbH" }, - { 0x06DA, "Phoenixtec Power Co., Ltd." }, - { 0x06DB, "Paradyne" }, - { 0x06DC, "Foxlink Image Technology Co., Ltd." }, - { 0x06DD, "Impact Technologies" }, - { 0x06DE, "Heisei Technology Co., Ltd." }, - { 0x06E0, "Multi-Tech Systems, Inc." }, - { 0x06E1, "ADS Technologies, Inc." }, - { 0x06E2, "Trio Motion Technology Limited" }, - { 0x06E4, "Alcatel Microelectronics" }, - { 0x06E5, "Lusher Technologies" }, - { 0x06E6, "Tiger Jet Network, Inc." }, - { 0x06E7, "Universal Electronics Inc." }, - { 0x06E8, "Braemar Inc." }, - { 0x06E9, "Nippon Electric Industry Co., Ltd." }, - { 0x06EA, "Sirius Technologies Limited" }, - { 0x06EB, "PC Expert Tech. Co., Ltd." }, - { 0x06EC, "ADInstruments Ltd." }, - { 0x06ED, "Datastor Technology" }, - { 0x06EF, "I.A.C. Geometrische Ingenieurs B.V." }, - { 0x06F0, "T.N.C Industrial Co., Ltd." }, - { 0x06F1, "Opcode Systems Inc." }, - { 0x06F2, "Emine Technology Company" }, - { 0x06F3, "Flexion Systems Ltd." }, - { 0x06F4, "First Person Gaming" }, - { 0x06F5, "Midian Production Distribution" }, - { 0x06F6, "Wintrend Technology Co., Ltd." }, - { 0x06F7, "Wish Technologies" }, - { 0x06F8, "Guillemot Corporation" }, - { 0x06F9, "Asyst Electronic" }, - { 0x06FA, "HSD S.r.L" }, - { 0x06FB, "Hitachi Device Engineering Ltd." }, - { 0x06FC, "Motorola Semiconductor Products Sector/US" }, - { 0x06FD, "Boston Acoustics" }, - { 0x06FE, "Gallant Computer, Inc." }, - { 0x06FF, "Mediacom Technologies Pte Ltd." }, - { 0x0701, "Supercomal Wire & Cable SDN. BHD." }, - { 0x0702, "PixStream Incorporated" }, - { 0x0703, "Bvtech Industry Inc." }, - { 0x0704, "Vorum Research Corporation" }, - { 0x0705, "NKK Corporation" }, - { 0x0706, "Ariel Corporation" }, - { 0x0707, "SMC Networks, Inc." }, - { 0x0708, "Putercom Co., Ltd." }, - { 0x0709, "Parthus Technologies" }, - { 0x070A, "Oki Electric Industry Co., Ltd." }, - { 0x070B, "Hasco Int., Inc." }, - { 0x070C, "Titan Electronics Inc." }, - { 0x070D, "Comoss Electronic Co., Ltd." }, - { 0x070E, "Excel Cell Electronic Co., Ltd." }, - { 0x070F, "Oce' -Technologies B.V." }, - { 0x0710, "Connect Tech Inc." }, - { 0x0711, "Magic Control Technology Corp." }, - { 0x0712, "Verity Instruments, Inc." }, - { 0x0713, "Interval Research Corp." }, - { 0x0714, "New Motion International Co., Ltd" }, - { 0x0715, "Liang Tei Co., Ltd." }, - { 0x0716, "Oxus Research S.A." }, - { 0x0717, "ZNK Corporation" }, - { 0x0718, "Imation Corp." }, - { 0x0719, "Tremon Enterprises Co., Ltd." }, - { 0x071A, "FLIR Explosives" }, - { 0x071B, "Domain Technologies, Inc." }, - { 0x071C, "Xionics Document Technologies, Inc." }, - { 0x071D, "Dialogic Corporation" }, - { 0x071E, "Ariston Technologies" }, - { 0x071F, "ARS Technologies Ltd." }, - { 0x0720, "Keyence Corporation" }, - { 0x0721, "HMedia Technology Inc." }, - { 0x0722, "Consero" }, - { 0x0723, "Centillium Communications Corporation" }, - { 0x0724, "Lawson Labs, Inc." }, - { 0x0725, "Applied Precision Inc." }, - { 0x0726, "Vanguard International Semiconductor-America" }, - { 0x0727, "C&H Technologies, Inc." }, - { 0x0728, "Avermedia" }, - { 0x0729, "CY&S Industrial Co., Ltd." }, - { 0x072A, "Luminex Corporation" }, - { 0x072B, "Dnova Corporation" }, - { 0x072C, "OTSO" }, - { 0x072D, "Able Communications, Inc." }, - { 0x072E, "Sunix Co., Ltd." }, - { 0x072F, "Advanced Card Systems Ltd." }, - { 0x0730, "Indus Instruments" }, - { 0x0731, "Susteen, Inc." }, - { 0x0732, "Goldfull Electronics & Telecommunications Corp." }, - { 0x0733, "ViewQuest Technologies, Inc." }, - { 0x0734, "LASAT Communications A/S" }, - { 0x0735, "Asuscom Network, Inc." }, - { 0x0736, "Lorom Industrial Co., Ltd." }, - { 0x0737, "Snap-on Diagnostics" }, - { 0x0738, "Mad Catz, Inc." }, - { 0x0739, "Cue Network Corporation" }, - { 0x073A, "Chaplet Systems, Inc." }, - { 0x073B, "Suncom Technologies" }, - { 0x073C, "Industrial Electronic Engineers, Inc." }, - { 0x073D, "Eutronsec Spa" }, - { 0x073E, "Sigma Itec, Inc." }, - { 0x073F, "Data Electronics (Aust) Pty, Ltd." }, - { 0x0740, "Full Enterprise Corp." }, - { 0x0741, "Momentum US Inc." }, - { 0x0742, "Stollmann EtV GmbH" }, - { 0x0743, "Bonig und Kallenback oHG" }, - { 0x0744, "GMK Electronic Design GmbH" }, - { 0x0745, "Syntech Information Co., Ltd." }, - { 0x0746, "ONKYO Corporation" }, - { 0x0747, "Labway Corporation" }, - { 0x0748, "Strong Man Enterprise Co., Ltd." }, - { 0x0749, "EVer Electronics Corp." }, - { 0x074A, "Ming Fortune Industry Co., Ltd." }, - { 0x074B, "Polestar Tech. Corp." }, - { 0x074C, "C-C-C Group PLC" }, - { 0x074D, "Micronas GmbH" }, - { 0x074E, "Digital Stream Corporation" }, - { 0x074F, "Microflip, Inc" }, - { 0x0750, "Innovative Integration" }, - { 0x0751, "Info Network Systems" }, - { 0x0752, "Non-Standard, TSG" }, - { 0x0753, "Mocom Softeare GmbH & Co. KG" }, - { 0x0754, "SyQuest Technology" }, - { 0x0755, "Aureal Semiconductor" }, - { 0x0756, "RSI Systems" }, - { 0x0757, "Network Technologies, Inc." }, - { 0x0758, "Carl Zeiss Jena GmbH" }, - { 0x0759, "Cellvision Systems, Inc." }, - { 0x075A, "SEL Inc." }, - { 0x075B, "Sophisticated Circuits, Inc." }, - { 0x075C, "Ulan Co., Ltd." }, - { 0x075D, "Microdowell SRL" }, - { 0x075E, "ABIT Corporation" }, - { 0x075F, "CITEL Technologies, Ltd." }, - { 0x0760, "JL Cooper Electronics" }, - { 0x0761, "MasTech, Inc." }, - { 0x0762, "Coretex Corporation" }, - { 0x0763, "M-Audio" }, - { 0x0764, "Cyber Power Systems, Inc." }, - { 0x0765, "X-Rite Incorporated" }, - { 0x0766, "Jess-Link Products Co., Ltd. (JPC)" }, - { 0x0767, "Tokheim Corporation" }, - { 0x0768, "Camtel Technology Corp." }, - { 0x0769, "SURECOM Technology Corp." }, - { 0x076A, "Conceptual Systems" }, - { 0x076B, "HID Global GmbH" }, - { 0x076C, "Partner Tech" }, - { 0x076D, "Denso Corporation" }, - { 0x076E, "Kuan Tech Enterprise Co., Ltd." }, - { 0x076F, "Jhen Vei Electronic Co., Ltd." }, - { 0x0770, "Welch Allyn, Inc - Medical Division" }, - { 0x0771, "MicroCraft" }, - { 0x0772, "TFL LAN, Inc" }, - { 0x0773, "Spital Sangyo Co., Ltd." }, - { 0x0774, "AmTRAN Technology Co., Ltd." }, - { 0x0775, "Longshine Electronics Corp." }, - { 0x0776, "Inalways Corporation" }, - { 0x0777, "Comda Advanced Technology Corporation" }, - { 0x0778, "Volex, Inc." }, - { 0x0779, "Fairchild Semiconductor" }, - { 0x077A, "NIDEC SANKYO CORPORATION" }, - { 0x077B, "Linksys" }, - { 0x077C, "Forward Electronics Co., Ltd." }, - { 0x077D, "Griffin Technology LLC" }, - { 0x077E, "Softing GmbH" }, - { 0x077F, "Well Excellent & Most Corp." }, - { 0x0780, "ORGA Kartensysteme GmbH" }, - { 0x0781, "Western Digital, Sandisk" }, - { 0x0782, "Trackerball" }, - { 0x0783, "C3PO, S.L." }, - { 0x0784, "Pretec Corporation" }, - { 0x0785, "Willnet Inc." }, - { 0x0786, "Jeil Data Systems Co., Ltd." }, - { 0x0787, "Abera System Corp" }, - { 0x0788, "3Cam Technology, Inc" }, - { 0x0789, "Logitec Corporation" }, - { 0x078A, "Tandy Electronics (China) Ltd." }, - { 0x078B, "Happ Controls" }, - { 0x078C, "CalComp" }, - { 0x078D, "Presto Technologies Inc." }, - { 0x078E, "San Shih Electrical Enterprise Co. Ltd." }, - { 0x078F, "Troy XCD, Inc." }, - { 0x0790, "Pro-Image Manufacturing Co., Ltd" }, - { 0x0791, "Copartner Technology Corporation" }, - { 0x0792, "Axis Communications AB" }, - { 0x0793, "Wha Yu Industrial Co., Ltd." }, - { 0x0794, "ABL Electronics Corporation" }, - { 0x0795, "RealChip Inc." }, - { 0x0796, "Certicom Corp." }, - { 0x0797, "Grandtech Semiconductor Corporation" }, - { 0x0798, "F.J. Tieman BV" }, - { 0x0799, "Boulder Creek Engineering" }, - { 0x079A, "Aptec Instruments" }, - { 0x079B, "Sagem SA" }, - { 0x079C, "Sun Communications Inc." }, - { 0x079D, "Alfadata Computer Corp." }, - { 0x079E, "Tokin Corporation" }, - { 0x079F, "VMETRO asa" }, - { 0x07A0, "Leiderdorp Instruments" }, - { 0x07A1, "Digicom Spa" }, - { 0x07A2, "National Technical Systems" }, - { 0x07A3, "ONNTO Corp." }, - { 0x07A4, "Be Incorporated" }, - { 0x07A5, "Tietech Co., Ltd." }, - { 0x07A6, "Infineon-ADMtek Co., Ltd." }, - { 0x07A7, "Mediatronix BV" }, - { 0x07A8, "Home Office PSDB" }, - { 0x07A9, "Sandmartin Company Ltd." }, - { 0x07AA, "Corega Inc." }, - { 0x07AB, "Freecom Technologies" }, - { 0x07AC, "Fortress U&T Ltd." }, - { 0x07AD, "ECO Chemie" }, - { 0x07AE, "C&C Technic Taiwan Co., Ltd." }, - { 0x07AF, "Microtech International, Inc." }, - { 0x07B0, "Billion Electric Co., Ltd" }, - { 0x07B1, "IMP, Inc." }, - { 0x07B2, "Motorola BCS" }, - { 0x07B3, "Plustek, Inc." }, - { 0x07B4, "OLYMPUS CORPORATION" }, - { 0x07B5, "Mega World International Ltd." }, - { 0x07B6, "Marubun Corp." }, - { 0x07B7, "TIME Interconnect Ltd." }, - { 0x07B8, "AboCom Systems, Inc." }, - { 0x07B9, "Reynolds Medical" }, - { 0x07BA, "Accurate Technologies, Inc." }, - { 0x07BB, "Intelogis Inc" }, - { 0x07BC, "Canon Computer Systems, Inc." }, - { 0x07BD, "Webgear Inc." }, - { 0x07BE, "Veridicom" }, - { 0x07BF, "TestQuest, Inc." }, - { 0x07C0, "Code Mercenaries" }, - { 0x07C1, "Keisokugiken Corporation" }, - { 0x07C2, "Varatouch Technology Inc." }, - { 0x07C3, "J-Works, Inc." }, - { 0x07C4, "Datafab Systems Inc." }, - { 0x07C5, "APG Cash Drawer" }, - { 0x07C6, "ShareWave, Inc." }, - { 0x07C7, "Powertech Industrial Co., Ltd." }, - { 0x07C8, "B.U.G., Inc." }, - { 0x07C9, "Allied Telesis Inc" }, - { 0x07CA, "AVerMedia Technologies, Inc." }, - { 0x07CB, "Kingmax Technology Inc." }, - { 0x07CC, "LIWANLI Innovation Co., Ltd" }, - { 0x07CD, "Hteck Corp." }, - { 0x07CE, "Nidec-Shimpo Corp." }, - { 0x07CF, "Casio Computer Co., Ltd." }, - { 0x07D0, "Dazzle Multimedia" }, - { 0x07D2, "Aptio Products Inc." }, - { 0x07D3, "Cyberdata Corp." }, - { 0x07D4, "Aloka Co., Ltd." }, - { 0x07D5, "Radiant Systems, Inc." }, - { 0x07D6, "MENICX International Co., Ltd." }, - { 0x07D7, "GCC Technologies, Inc." }, - { 0x07D8, "Network Suginami Kokoto" }, - { 0x07D9, "Compuapps" }, - { 0x07DA, "Arasan Chip Systems Inc." }, - { 0x07DB, "Mental Models, Inc." }, - { 0x07DC, "OCTAL-Engenharia de Sistemas S.A." }, - { 0x07DD, "Hampshire Company, Inc." }, - { 0x07DE, "Best Data Products" }, - { 0x07DF, "David Electronics Company, Ltd." }, - { 0x07E0, "NCP Engineering" }, - { 0x07E1, "Acer Netxus Incorporated" }, - { 0x07E2, "Elmeg GmbH & Co., Ltd." }, - { 0x07E3, "Planex Communications, Inc." }, - { 0x07E4, "Movado Enterprise Co., Ltd." }, - { 0x07E5, "QPS, Inc." }, - { 0x07E6, "Allied Cable Corporation" }, - { 0x07E7, "Mirvo Toys, Inc." }, - { 0x07E8, "Labsystems" }, - { 0x07E9, "Sanyo Technosound Co., Ltd." }, - { 0x07EA, "Iwatsu Electric Co., Ltd." }, - { 0x07EB, "Double-H Technology Co., Ltd." }, - { 0x07EC, "Taiyo Electric Wire & Cable Co., Ltd." }, - { 0x07ED, "Precision MicroDynamics, Inc." }, - { 0x07EE, "Logware GmbH" }, - { 0x07EF, "Suite Technology Systems" }, - { 0x07F0, "PS Communications Ltd." }, - { 0x07F1, "Picostar, Inc." }, - { 0x07F2, "BPT Enterprises" }, - { 0x07F3, "L3 Systems" }, - { 0x07F4, "Joritel International B.V." }, - { 0x07F5, "Amiable Technologies, Inc." }, - { 0x07F6, "Circuit Assembly Corp." }, - { 0x07F7, "Century Corporation" }, - { 0x07F8, "Eskape Labs" }, - { 0x07F9, "Dotop Technology, Inc." }, - { 0x07FA, "FHLP" }, - { 0x07FB, "Digi-Tek, Inc." }, - { 0x07FC, "Protec Microsystems" }, - { 0x07FD, "Mark of the Unicorn, Inc." }, - { 0x07FE, "Net Eyes, Inc." }, - { 0x07FF, "Sectra AB" }, - { 0x0800, "Kortex International" }, - { 0x0801, "Mag-Tek" }, - { 0x0802, "Mako Technologies, LLC" }, - { 0x0803, "Zoom Telephonics, Inc." }, - { 0x0804, "Neuron Corporation" }, - { 0x0805, "Iruma Soft Co., Ltd." }, - { 0x0806, "Clinton Electronics Corp." }, - { 0x0807, "SIIX Corporation" }, - { 0x0808, "InfiMed, Inc." }, - { 0x0809, "Genicom LP" }, - { 0x080A, "Evermuch Technology Co., Ltd." }, - { 0x080B, "Cross Match Technologies, Inc." }, - { 0x080C, "Datalogic S.p.A." }, - { 0x080D, "TECO Image Systems Co., Ltd." }, - { 0x080E, "Sound Technology, Inc." }, - { 0x080F, "Deschutes Corporation" }, - { 0x0810, "Personal Communication Systems, Inc." }, - { 0x0811, "Fimet" }, - { 0x0812, "E-Tech, Inc." }, - { 0x0813, "Mattel, Inc." }, - { 0x0814, "EBI Systems, Inc." }, - { 0x0815, "Scintrex" }, - { 0x0816, "ABB Automation Products AB" }, - { 0x0817, "Interzeag Medical Technology" }, - { 0x0818, "NTT Electronics Corporation" }, - { 0x0819, "Syncrosoft GMBH" }, - { 0x081A, "MG Logic Pte Ltd." }, - { 0x081B, "Indigita Corporation" }, - { 0x081C, "MIPSYS" }, - { 0x081D, "VlerZwo Software GbR" }, - { 0x081E, "AlphaSmart, Inc." }, - { 0x081F, "Totsu Engineering, Inc." }, - { 0x0820, "Verax Engineering" }, - { 0x0821, "A.T. Cross" }, - { 0x0822, "REUDO Corporation" }, - { 0x0823, "Tactex Controls, Inc." }, - { 0x0824, "M.S.E. GmbH" }, - { 0x0825, "GC Protronics" }, - { 0x0826, "Data Transit" }, - { 0x0827, "BroadLogic, Inc." }, - { 0x0828, "Sato Corporation" }, - { 0x0829, "DirecTV Broadband" }, - { 0x082A, "Object Co., Ltd." }, - { 0x082B, "TrophyTrex" }, - { 0x082C, "Japan Digital Laboratory Co., Ltd." }, - { 0x082D, "Handspring, Inc." }, - { 0x082E, "Suni Imaging Microsystems, Inc." }, - { 0x082F, "ACACIA" }, - { 0x0830, "Palm Inc." }, - { 0x0831, "Chong Tsi Su Enterprise Co., Ltd" }, - { 0x0832, "Kouwell Electronics Corp." }, - { 0x0833, "Sourcenext Corporation" }, - { 0x0834, "Ciponic Technology Co., Ltd." }, - { 0x0835, "Action Star Technology Co., Ltd." }, - { 0x0836, "Evertz Microsystems Ltd." }, - { 0x0837, "Renishaw PLC" }, - { 0x0838, "Precision MicroControl Corporation" }, - { 0x0839, "Samsung Techwin" }, - { 0x083A, "Accton Technology Corporation" }, - { 0x083B, "Dr. Neuhaus Telekommunikation GmbH" }, - { 0x083C, "Jaeger Messtechnik GmbH" }, - { 0x083D, "Nakayo Telecommunication, Inc." }, - { 0x083E, "2-Tel B.V." }, - { 0x083F, "Boca Global, Inc." }, - { 0x0840, "Argosy Research Inc." }, - { 0x0841, "Rioport.com Inc." }, - { 0x0842, "ESA MESSTECHNIK GMBH" }, - { 0x0843, "Mcom As" }, - { 0x0844, "Welland Industrial Co., Ltd." }, - { 0x0845, "EES Technik fur Musik" }, - { 0x0846, "NETGEAR, Inc." }, - { 0x0847, "Interack Communications Inc." }, - { 0x0848, "Accton Technology Co., Ltd." }, - { 0x0849, "SC&T International, Inc." }, - { 0x084A, "Wipro Limited" }, - { 0x084B, "Castlewood Systems" }, - { 0x084C, "The Japan Steel Works, Ltd." }, - { 0x084D, "Minton Optic Industry Co., Ltd." }, - { 0x084E, "KidBoard, Inc. dba KBGear Interactive" }, - { 0x084F, "EMPEG Ltd" }, - { 0x0850, "FastPoint Technologies, Inc." }, - { 0x0851, "Macronix International Co., Ltd." }, - { 0x0852, "CSEM" }, - { 0x0853, "Topre Corporation" }, - { 0x0854, "Active Wire, Inc." }, - { 0x0855, "JMBS Developpements" }, - { 0x0856, "B&B Electronics" }, - { 0x0857, "Gerber Scientific Products, Inc." }, - { 0x0858, "Hitachi Maxell Ltd." }, - { 0x0859, "Minolta Systems Laboratory, Inc." }, - { 0x085A, "Xircom" }, - { 0x085B, "Kurt Manufacturing" }, - { 0x085C, "Color Vision Inc." }, - { 0x085D, "Ambient Technologies, Inc." }, - { 0x085E, "NaftEL Technologies LTD." }, - { 0x085F, "Canberra Industries" }, - { 0x0860, "Momentum Data System" }, - { 0x0861, "Cambridge Research Systems Ltd." }, - { 0x0862, "Teletrol Systems, Inc." }, - { 0x0863, "Filanet Corporation" }, - { 0x0864, "Roper International Ltd." }, - { 0x0865, "MICROLAB" }, - { 0x0866, "PEI Electronics, Inc." }, - { 0x0867, "Data Translation, Inc." }, - { 0x0868, "Electrical Geodesics, Inc." }, - { 0x0869, "Visual Interaction" }, - { 0x086A, "Emagic Soft-und Hardware Gmbh" }, - { 0x086B, "ROHM Co. Ltd." }, - { 0x086C, "DeTeWe" }, - { 0x086D, "ICE Technology" }, - { 0x086E, "System TALKS Inc." }, - { 0x086F, "MEC IMEX INC-HPT" }, - { 0x0870, "Metricom, Inc." }, - { 0x0871, "Merge Technologies Inc." }, - { 0x0872, "Broadxent, Inc." }, - { 0x0873, "Xpeed Inc." }, - { 0x0874, "A-Tec Subsystem, Inc." }, - { 0x0875, "Mecel AB" }, - { 0x0876, "3M Home Health Systems" }, - { 0x0877, "Lew Engineering" }, - { 0x0878, "SYSTEC Computer Gmbh" }, - { 0x0879, "Comtrol Corporation" }, - { 0x087A, "Getemed GmbH" }, - { 0x087B, "Cornerstone Peripherals Technology" }, - { 0x087C, "ADESSO/Kbtek America Inc." }, - { 0x087D, "JATON Corporation" }, - { 0x087E, "Fujitsu Computer Products of America" }, - { 0x087F, "QualCore Logic Inc" }, - { 0x0880, "APT Technologies Inc." }, - { 0x0881, "Sistemas Y Redes Telematicas, Sire S.L." }, - { 0x0882, "Rightec Research" }, - { 0x0883, "Recording Industry Association of America (RIAA)" }, - { 0x0884, "USB Systems" }, - { 0x0885, "Boca Research, Inc." }, - { 0x0887, "Hannstar Electronics Corp." }, - { 0x0889, "Current Works, Inc." }, - { 0x088A, "TechTools" }, - { 0x088B, "MassWorks" }, - { 0x088C, "Swecoin AB" }, - { 0x088D, "Engineering Spirit" }, - { 0x088E, "Pace Anti-Piracy, Inc." }, - { 0x088F, "Husky Computers Limited" }, - { 0x0890, "Consultronics Ltd." }, - { 0x0891, "Drager Medizintechnik Gmbh." }, - { 0x0892, "DioGraphy Inc." }, - { 0x0893, "Bartec" }, - { 0x0894, "TSI Incorporated" }, - { 0x0895, "Kanitech A/S" }, - { 0x0896, "Starseed Enterprises AG" }, - { 0x0897, "Lauterbach GmbH" }, - { 0x0898, "3M Canada" }, - { 0x0899, "Grieshaber & Co. AG" }, - { 0x089A, "Koepruelue Engineering" }, - { 0x089B, "Digital-3, LLC." }, - { 0x089C, "United Technologies Research Cntr." }, - { 0x089D, "Icron Technologies Corporation" }, - { 0x089E, "NST Co., Ltd." }, - { 0x089F, "Primex Aerospace Co." }, - { 0x08A0, "Logic Meca Co., Ltd." }, - { 0x08A1, "Studio Zee" }, - { 0x08A2, "Millennia Systems, Inc." }, - { 0x08A3, "Hyowon Software" }, - { 0x08A4, "YTG Smartech Inc." }, - { 0x08A5, "e9 Inc." }, - { 0x08A6, "Toshiba Tec Corporation" }, - { 0x08A7, "General Cybernetics Inc." }, - { 0x08A8, "Andrea Electronics" }, - { 0x08A9, "CWAV" }, - { 0x08AA, "Kernel Productions, Inc." }, - { 0x08AB, "Innolab Pte. Ltd." }, - { 0x08AC, "Macraigor Systems LLC" }, - { 0x08AD, "Toyota Technical Development Corporation (TTDC)" }, - { 0x08AE, "Macally (Mace Group, Inc.)" }, - { 0x08AF, "Hamilton Co." }, - { 0x08B0, "Metrohm Ltd." }, - { 0x08B1, "High Technology Laboratory s.r.l" }, - { 0x08B2, "BIOTRONIK GmbH & Co." }, - { 0x08B3, "Voice It Worldwide, Inc." }, - { 0x08B4, "Sorenson Communications" }, - { 0x08B5, "Correlator.com" }, - { 0x08B6, "Imagek, Inc." }, - { 0x08B7, "NATSU Corporation Limited" }, - { 0x08B8, "J. Gordon Electronic Design, Inc." }, - { 0x08B9, "General Wireless Operations Inc" }, - { 0x08BA, "Fujitsu General Limited" }, - { 0x08BB, "Texas Instruments Japan" }, - { 0x08BC, "Dr. G. Schuhfried GmbH" }, - { 0x08BD, "Citizen Watch Co., Ltd." }, - { 0x08BE, "Meilenstein GmbH" }, - { 0x08BF, "Nova Engineering, Inc." }, - { 0x08C0, "Braintronics B.V." }, - { 0x08C1, "Timestep Electronics Ltd." }, - { 0x08C2, "ArgoCraft Co., Ltd." }, - { 0x08C3, "Precise Biometrics" }, - { 0x08C4, "Proxim CBU" }, - { 0x08C5, "Moreton Bay" }, - { 0x08C6, "Scalex Corporation" }, - { 0x08C7, "TAI TWUN ENTERPRISE CO., LTD." }, - { 0x08C8, "2Wire, Inc" }, - { 0x08C9, "Nippon Telegraph and Telephone Corp." }, - { 0x08CA, "AIPTEK International Inc." }, - { 0x08CB, "Cyber Innovate, Inc." }, - { 0x08CC, "ifak system GmbH" }, - { 0x08CD, "Jue Hsun Ind. Corp." }, - { 0x08CE, "Long Well Electronics Corp." }, - { 0x08CF, "Productivity Enhancement Products" }, - { 0x08D0, "Tasco Electronics Co., Inc." }, - { 0x08D1, "Smartbridges Pte. Ltd." }, - { 0x08D2, "Dialog4 System Engineering Gmbh." }, - { 0x08D3, "Virtual Ink" }, - { 0x08D4, "Siemens PC Systeme GmbH" }, - { 0x08D5, "Cambridge Heart, Inc." }, - { 0x08D6, "Itautec Philco S.A." }, - { 0x08D7, "Opticon, Inc." }, - { 0x08D8, "Huntsville Microsystems, Inc." }, - { 0x08D9, "Increment P Corporation" }, - { 0x08DA, "A W Electronics, Inc." }, - { 0x08DB, "IXXAT Automation GmbH" }, - { 0x08DC, "Animo Limited" }, - { 0x08DD, "Billionton Systems, Inc." }, - { 0x08DE, "Touchstone Software" }, - { 0x08DF, "Spyrus Inc." }, - { 0x08E0, "Geodesic Designs, Inc." }, - { 0x08E1, "LSI JAPAN Co., Ltd" }, - { 0x08E2, "SafeNet China Ltd." }, - { 0x08E3, "OLITEC" }, - { 0x08E4, "Pioneer Corporation" }, - { 0x08E5, "LITRONIC" }, - { 0x08E6, "Gemalto SA" }, - { 0x08E7, "PAN-INTERNATIONAL WIRE & CABLE (M) SDN BHD" }, - { 0x08E8, "Integrated Memory Logic" }, - { 0x08E9, "Extended Systems, Inc." }, - { 0x08EA, "Ericsson Inc." }, - { 0x08EB, "Asulab SA" }, - { 0x08EC, "M-Systems Flash Disk Pioneers" }, - { 0x08ED, "Instrumentation Metrics, Inc." }, - { 0x08EE, "CCSI/HESSO" }, - { 0x08EF, "PixelVision" }, - { 0x08F0, "CardScan Inc." }, - { 0x08F1, "CTI Electronics Corporation" }, - { 0x08F2, "Constance Technology Co., Ltd." }, - { 0x08F3, "Wintime Electronics Corp." }, - { 0x08F4, "Telia ProSoft AB" }, - { 0x08F5, "SYSTEC Co., Ltd." }, - { 0x08F6, "Logic 3 International Limited" }, - { 0x08F7, "Vernier Software" }, - { 0x08F8, "Keen Top International Enterprise Co., Ltd." }, - { 0x08F9, "Wipro Technologies" }, - { 0x08FA, "CAERE" }, - { 0x08FB, "Socket Mobile, Inc." }, - { 0x08FC, "Sicon International" }, - { 0x08FD, "Digianswer A/S" }, - { 0x08FE, "GDSYSTEMS" }, - { 0x08FF, "AuthenTec, Inc." }, - { 0x0901, "VST Technologies" }, - { 0x0902, "iDream Technologies Pte Ltd" }, - { 0x0903, "Infolibria" }, - { 0x0904, "Frank Audiodata" }, - { 0x0905, "ISDG" }, - { 0x0906, "FARADAY Technology Corp." }, - { 0x0907, "Addison Technology Europe B.V." }, - { 0x0908, "Siemens Automation & Drives" }, - { 0x0909, "Audio-Technica Corp." }, - { 0x090A, "Trumpion Microelectronics Inc" }, - { 0x090B, "Neurosmith" }, - { 0x090C, "Silicon Motion, Inc. - Taiwan" }, - { 0x090D, "MULTIPORT Computer Vertriebs GmbH" }, - { 0x090E, "Shining Technology, Inc." }, - { 0x090F, "Fujitsu Devices Inc." }, - { 0x0910, "Alation Systems, Inc." }, - { 0x0911, "Philips Speech Processing" }, - { 0x0912, "Voquette, Inc." }, - { 0x0913, "Asante' Technologies, Inc." }, - { 0x0914, "Bally Gaming, Inc." }, - { 0x0915, "GlobespanVirata, Inc." }, - { 0x0916, "DH electronics GmbH" }, - { 0x0917, "SmartDisk Corporation" }, - { 0x0918, "Planet Portal.com" }, - { 0x0919, "Sound Vision Inc." }, - { 0x091A, "Inter-Cable Systems, Inc." }, - { 0x091B, "Raleigh Technology Corporation" }, - { 0x091C, "Bormann EDV + Zubehoer GmbH" }, - { 0x091D, "A. K. Barns Ltd." }, - { 0x091E, "Garmin International" }, - { 0x091F, "U-JIN Mesco Co., Ltd." }, - { 0x0920, "Echelon Corporation" }, - { 0x0921, "GoHubs, inc." }, - { 0x0922, "Dymo Corporation" }, - { 0x0923, "IC Media Corporation" }, - { 0x0924, "Xerox Corporation" }, - { 0x0925, "Lakeview Research" }, - { 0x0926, "Sound Devices, LLC" }, - { 0x0927, "Summus, Ltd." }, - { 0x0928, "Oxford Semiconductor Ltd." }, - { 0x0929, "American Biometric Company" }, - { 0x092A, "Toshiba Information & Industrial Sys. And Services" }, - { 0x092B, "Sena Technologies, Inc." }, - { 0x092C, "Shanghai Bell Company Limited" }, - { 0x092D, "OYO Instruments" }, - { 0x092E, "Markpoint AB" }, - { 0x092F, "Northern Embedded Science" }, - { 0x0930, "Toshiba Corporation" }, - { 0x0931, "Harmonic Data Systems Ltd." }, - { 0x0932, "Crescentec Corporation" }, - { 0x0933, "Quantum Corp." }, - { 0x0934, "Spirent Communications" }, - { 0x0935, "Accurite Technologies, Inc." }, - { 0x0936, "DynamicNakedAudio Inc." }, - { 0x0937, "Scania CV AB" }, - { 0x0938, "Virtual DSP Corporation" }, - { 0x0939, "Lumberg, Inc." }, - { 0x093A, "Pixart Imaging, Inc." }, - { 0x093B, "Plextor LLC" }, - { 0x093C, "Intrepid Control Systems, Inc." }, - { 0x093D, "InnoSync, Inc." }, - { 0x093E, "J.S.T. Mfg. Co., Ltd." }, - { 0x093F, "OLYMPIA Telecom Vertriebs GmbH" }, - { 0x0940, "Japan Storage Battery Co., Ltd." }, - { 0x0941, "Photobit Corporation" }, - { 0x0942, "i2Go.com, LLC" }, - { 0x0943, "HCL Technologies Ltd." }, - { 0x0944, "KORG, Inc." }, - { 0x0945, "PASCO Scientific" }, - { 0x0946, "GEMSTAR TECHOLOGY DEVELOPMENT LIMITED" }, - { 0x0947, "Videonics, Inc." }, - { 0x0948, "Kronauer Music In Digital" }, - { 0x0949, "Hitachi Kokusai Electric Inc." }, - { 0x094A, "Luckytech Technology Co., Ltd" }, - { 0x094B, "Linkup Systems Corporation" }, - { 0x094C, "Metanetics Corporation" }, - { 0x094D, "Cable Television Laboratories" }, - { 0x094E, "Head Acoustics" }, - { 0x094F, "Yano Electric Co., Ltd." }, - { 0x0950, "TechniSat Sateliltenfernsehprodukte Gmbh" }, - { 0x0951, "Kingston Technology Company" }, - { 0x0952, "DCOM Enterprise Co., Ltd." }, - { 0x0953, "PLG" }, - { 0x0954, "RPM Systems Corporation" }, - { 0x0955, "NVIDIA" }, - { 0x0956, "BSquare Corporation" }, - { 0x0957, "Agilent Technologies, Inc." }, - { 0x0958, "BioLink Technologies International, Inc." }, - { 0x0959, "Cologne Chip AG" }, - { 0x095A, "Portsmith" }, - { 0x095B, "Medialogic Corporation" }, - { 0x095C, "K-Tec Electronics" }, - { 0x095D, "Polycom, Inc." }, - { 0x095E, "USB Design Labs" }, - { 0x095F, "TTO Engineering" }, - { 0x0960, "Bcom Electronics, Inc." }, - { 0x0961, "Portatec Corporation" }, - { 0x0962, "SAMx" }, - { 0x0963, "Instrument Solutions" }, - { 0x0964, "Bitran Corporation" }, - { 0x0965, "PAR Technologies, Inc." }, - { 0x0966, "HanGo Electronics Co., Ltd." }, - { 0x0967, "Acer NeWeb Corporation" }, - { 0x0969, "Magellan Corp." }, - { 0x096A, "Koizumi Computer, Inc." }, - { 0x096B, "ML Electronics Ltd." }, - { 0x096C, "GOPEL electronic GmbH" }, - { 0x096D, "PennyLan" }, - { 0x096E, "Feitian Technologies Co., Ltd." }, - { 0x096F, "Memory Link" }, - { 0x0970, "K.S. Vector Co., Ltd." }, - { 0x0971, "GretagMacbeth AG" }, - { 0x0972, "Musicbird" }, - { 0x0973, "Axalto" }, - { 0x0974, "Eye Communication Systems, Inc" }, - { 0x0975, "OL'E Communications, Inc." }, - { 0x0976, "Adirondack Wire & Cable" }, - { 0x0977, "Lightsurf Technologies" }, - { 0x0978, "Beckhoff Gmbh" }, - { 0x0979, "Jeilin Technology Corp., Ltd." }, - { 0x097A, "Minds At Work LLC" }, - { 0x097B, "Knudsen Engineering Limited" }, - { 0x097C, "Marunix Co., Ltd." }, - { 0x097D, "Rosun Technologies, Inc." }, - { 0x097E, "Biopac Systems Inc." }, - { 0x097F, "Barun Electronics Co. Ltd." }, - { 0x0980, "Posh Mfg. Ltd." }, - { 0x0981, "Oak Technology Ltd." }, - { 0x0982, "Covadis S.A." }, - { 0x0983, "Nissha Printing Co., Ltd." }, - { 0x0984, "Apricorn" }, - { 0x0985, "Cab Produkttechnik" }, - { 0x0986, "Panasonic Electric Works Co., Ltd." }, - { 0x0987, "MicroSpeed Inc" }, - { 0x0988, "Teraoka Seiko Co. Ltd" }, - { 0x0989, "Digitel Co. LTD" }, - { 0x098A, "Neopost" }, - { 0x098B, "Kingtel Telecommunication Corp." }, - { 0x098C, "Vitana Corporation" }, - { 0x098D, "INDesign" }, - { 0x098E, "Integrated Intellectual Property Inc." }, - { 0x098F, "TEXIO CORPORATION" }, - { 0x0990, "General Instrument Corp." }, - { 0x0992, "Bandai Co., Ltd." }, - { 0x0993, "NuvoMedia, Inc." }, - { 0x0994, "Dionex Softron GmbH" }, - { 0x0995, "Simple Jet Technology Co., Ltd." }, - { 0x0996, "Integrated Telecom Express, Inc." }, - { 0x0997, "Xerox Corporation/Non-Networked Products" }, - { 0x0998, "Atech Totalsolution Co., Ltd." }, - { 0x0999, "Ocean Optics, Inc." }, - { 0x099A, "ZIPPY TECHNOLOGY CORP." }, - { 0x099B, "HIROTA SEISAKUSHO LTD." }, - { 0x099C, "Florida Probe, Inc." }, - { 0x099D, "NEC San-ei Instruments, Ltd." }, - { 0x099E, "Trimble" }, - { 0x099F, "Summa N.V." }, - { 0x09A0, "Altec Computersysteme GmbH" }, - { 0x09A1, "ELMO COMPANY, LIMITED" }, - { 0x09A2, "Telemann Co., Ltd." }, - { 0x09A3, "PairGain Technologies" }, - { 0x09A4, "Contech Research, Inc." }, - { 0x09A5, "VCON Telecommunications" }, - { 0x09A6, "Poinchips" }, - { 0x09A7, "Data Transmission Network Corp." }, - { 0x09A8, "Lin Shiung Enterprise Co., Ltd." }, - { 0x09A9, "Smart Card Technologies Co., Ltd." }, - { 0x09AA, "Intersil Corporation" }, - { 0x09AB, "Japan Cash Machine Co., Ltd." }, - { 0x09AC, "DIGIGRAM" }, - { 0x09AD, "The MITRE Corporation" }, - { 0x09AE, "Tripp Lite" }, - { 0x09AF, "G.i.N. mbH" }, - { 0x09B0, "Fargo Electronics, Inc." }, - { 0x09B1, "Ositech Communications Incorporated" }, - { 0x09B2, "Franklin Electronic Publishers" }, - { 0x09B3, "Simplex Solution Inc." }, - { 0x09B4, "MDS Gateways" }, - { 0x09B5, "Celltrix Technology Co., Ltd." }, - { 0x09B6, "SmithMyers Communications Limited" }, - { 0x09B7, "FAIRLIGHT ESP" }, - { 0x09B8, "PhoeniX . Incorporated" }, - { 0x09B9, "CentLand inc." }, - { 0x09BA, "Chumtronix N.V." }, - { 0x09BB, "Eule Industrie- & Datentechnik GmbH & Co. KG" }, - { 0x09BC, "Audivo GmbH" }, - { 0x09BD, "Haptix Creation Pte Ltd" }, - { 0x09BE, "Prosisa Overseas LLC" }, - { 0x09BF, "Auerswald GmbH & Co. KG" }, - { 0x09C0, "Molecular Devices LLC" }, - { 0x09C1, "ARRIS International" }, - { 0x09C2, "NISCA Corporation" }, - { 0x09C3, "ACTIVCARD, INC." }, - { 0x09C4, "ACTiSYS Corporation" }, - { 0x09C5, "Memory Corporation" }, - { 0x09C6, "Inovatec S.p.A." }, - { 0x09C7, "PUBCOMPANY s.r.l." }, - { 0x09C8, "Carrot Systems Inc." }, - { 0x09C9, "U.S. Digital Corp." }, - { 0x09CA, "BMC Messsysteme GmbH" }, - { 0x09CB, "Flir Systems" }, - { 0x09CC, "Workbit Corporation" }, - { 0x09CD, "Psion Connect Ltd." }, - { 0x09CE, "City Electronics Ltd." }, - { 0x09CF, "Electronics Testing Center, Taiwan" }, - { 0x09D1, "NeoMagic Inc." }, - { 0x09D2, "Vreelin Engineering Inc." }, - { 0x09D3, "COM ONE" }, - { 0x09D4, "Asahi Engineering Co., Ltd." }, - { 0x09D5, "DigiTech" }, - { 0x09D6, "Berkeley Varitronics Systems" }, - { 0x09D7, "NovAtel Inc." }, - { 0x09D8, "Elatec GmbH" }, - { 0x09D9, "Jungo" }, - { 0x09DA, "A-FOUR TECH CO., LTD." }, - { 0x09DB, "Measurement Computing Corporation" }, - { 0x09DC, "AIMEX Corporation" }, - { 0x09DD, "Fellowes Inc." }, - { 0x09DE, "ViQuest Technology" }, - { 0x09DF, "Addonics Technologies Corp." }, - { 0x09E0, "Johnson Matthey PLC, Trading as Tracerco" }, - { 0x09E1, "Intellon Corporation" }, - { 0x09E2, "Surface Imaging Systems (S.I.S.)" }, - { 0x09E3, "WIZnet" }, - { 0x09E4, "Unidata" }, - { 0x09E5, "Jo-Dan International, Inc." }, - { 0x09E6, "Silutia, Inc." }, - { 0x09E7, "Real 3D, Inc." }, - { 0x09E8, "AKAI professional M.I. Corp." }, - { 0x09E9, "CHEN-SOURCE INC." }, - { 0x09EA, "ShareCall Technologies" }, - { 0x09EB, "Sonicbox, Inc." }, - { 0x09EC, "COINT Multimedia Systems" }, - { 0x09ED, "Viking Sewing Machines AB" }, - { 0x09EE, "Jesmay Electronics Co., Ltd." }, - { 0x09EF, "XITEL PTY Limited" }, - { 0x09F0, "Perpetual Technologies, LLC" }, - { 0x09F1, "Eshed Robotec" }, - { 0x09F2, "hema Elektronik GmbH" }, - { 0x09F3, "GoFlight, Inc." }, - { 0x09F4, "Microlink Corporation" }, - { 0x09F5, "ARESCOM" }, - { 0x09F6, "RocketChips, Inc." }, - { 0x09F7, "EDU-SCIENCE (H.K.) LIMITED" }, - { 0x09F8, "SoftConnex Technologies, Inc." }, - { 0x09F9, "Bay Associates" }, - { 0x09FA, "Mtek Vision" }, - { 0x09FB, "Altera" }, - { 0x09FC, "Silicon Mountain Design" }, - { 0x09FD, "MM - Manager Memory" }, - { 0x09FE, "Goldteck International Inc." }, - { 0x09FF, "Gain Technology Corp." }, - { 0x0A00, "Liquid Audio" }, - { 0x0A01, "ViA, Inc." }, - { 0x0A02, "DIATECNIC" }, - { 0x0A03, "Globe Wireless, Inc." }, - { 0x0A04, "Star, Inc." }, - { 0x0A05, "University of Kansas" }, - { 0x0A06, "BSQUARE Slicon Valley" }, - { 0x0A07, "Ontrak Control Systems Inc." }, - { 0x0A08, "Lorenz GmbH" }, - { 0x0A09, "Datadesk Technologies Inc." }, - { 0x0A0A, "LIEWENTHAL ELECTRONICS LTD." }, - { 0x0A0B, "Cybex Computer Products Corporation" }, - { 0x0A0C, "MIRAD" }, - { 0x0A0D, "VIPS France" }, - { 0x0A0E, "AGFEO" }, - { 0x0A0F, "Liesegang" }, - { 0x0A10, "Combinova AB" }, - { 0x0A11, "Xentec Incorporated" }, - { 0x0A12, "Cambridge Silicon Radio Ltd." }, - { 0x0A13, "Telebyte Inc." }, - { 0x0A14, "Spacelabs Healthcare" }, - { 0x0A15, "Scalar Corporation" }, - { 0x0A16, "Trek Technology (S) Pte Ltd" }, - { 0x0A17, "HOYA Corporation" }, - { 0x0A18, "Heidelberger Druckmaschinen AG" }, - { 0x0A19, "Hua Geng Technologies Inc." }, - { 0x0A1A, "Astro-Med, Inc." }, - { 0x0A1B, "Wolfvision GmbH" }, - { 0x0A1C, "Micro Systemation AB" }, - { 0x0A1D, "T-Nova Deutsche Telekom Innovationsgesellschaft" }, - { 0x0A1E, "Netcraft (Pty) Ltd." }, - { 0x0A1F, "Tesco Co." }, - { 0x0A20, "SystemBase Co., Ltd." }, - { 0x0A21, "Physio-Control, Inc." }, - { 0x0A22, "Century Semiconductor USA, Inc." }, - { 0x0A23, "NDS Technologies Israel Ltd." }, - { 0x0A24, "Boca Design, Inc." }, - { 0x0A25, "3M Germany" }, - { 0x0A26, "Cyberware" }, - { 0x0A27, "Datacard Group" }, - { 0x0A28, "Ensure Technologies, Inc." }, - { 0x0A29, "Marketcast" }, - { 0x0A2A, "Fortune Electronics & Plastic (International) Ltd." }, - { 0x0A2B, "Muller & Sebastiani Elektronik GmbH" }, - { 0x0A2C, "Ak Modul Bus Computer GmbH" }, - { 0x0A2D, "Advanced Measurement Technology" }, - { 0x0A2E, "ONE-O-ONE iSOLUTIONS" }, - { 0x0A2F, "Prime Systems, Inc." }, - { 0x0A30, "WAW-Tronics" }, - { 0x0A31, "Data System Co., Ltd." }, - { 0x0A32, "Addatel ApS" }, - { 0x0A33, "Intermind Inc." }, - { 0x0A34, "TG3 Electronics, Inc." }, - { 0x0A35, "Radikal Technologies" }, - { 0x0A36, "GS Technical Support Center" }, - { 0x0A37, "Concept Development" }, - { 0x0A38, "I.R.I.S." }, - { 0x0A39, "Gilat Satellite Networks Ltd." }, - { 0x0A3A, "PentaMedia Co., Ltd." }, - { 0x0A3B, "Hitachi Information Technology Co., Ltd." }, - { 0x0A3C, "NTT DoCoMo,Inc." }, - { 0x0A3D, "Varo Vision" }, - { 0x0A3E, "REINHARDT System- und Messelectronic GmbH" }, - { 0x0A3F, "Swissonic AG" }, - { 0x0A40, "PaloDEx Group Oy" }, - { 0x0A41, "SEKONIC corporation" }, - { 0x0A42, "Medtronic Functional Diagnostics" }, - { 0x0A43, "Boca Systems Inc." }, - { 0x0A44, "TurboLinux" }, - { 0x0A45, "Look&Say co., Ltd." }, - { 0x0A46, "Davicom Semiconductor, Inc." }, - { 0x0A47, "Hirose Electric Co., Ltd." }, - { 0x0A48, "I/O Interconnect" }, - { 0x0A4A, "propagamma kommunikation" }, - { 0x0A4B, "Fujitsu Media Devices Limited" }, - { 0x0A4C, "COMPUTEX Co., Ltd." }, - { 0x0A4D, "Evolution Electronics Ltd." }, - { 0x0A4E, "Steinberg Soft-und Hardware GmbH" }, - { 0x0A4F, "Litton Systems Inc." }, - { 0x0A50, "Mimaki Engineering Co., Ltd." }, - { 0x0A51, "Sony Electronics Inc." }, - { 0x0A52, "JEBSEE ELECTRONICS CO., LTD." }, - { 0x0A53, "Portable Peripheral Co., Ltd." }, - { 0x0A54, "Applied Signal Technology, Inc." }, - { 0x0A55, "ThermoQuest Corporation" }, - { 0x0A56, "EAE electronics GmbH" }, - { 0x0A57, "Joachim Koopmann Software" }, - { 0x0A58, "DIGIDENT LTD." }, - { 0x0A59, "Convergence Instruments" }, - { 0x0A5B, "EASICS NV" }, - { 0x0A5C, "Broadcom Corp." }, - { 0x0A5D, "Diatrend Corporation" }, - { 0x0A5E, "Spinnaker Systems Inc." }, - { 0x0A5F, "Zebra Technologies" }, - { 0x0A60, "Future Networks, Inc." }, - { 0x0A61, "DTI sa" }, - { 0x0A62, "MPMan.com, Inc." }, - { 0x0A63, "Prism Media Products Ltd." }, - { 0x0A64, "Padcom Inc." }, - { 0x0A65, "FullAudio, Inc." }, - { 0x0A66, "ClearCube Technology" }, - { 0x0A67, "Medeli Electronics Co, Ltd." }, - { 0x0A68, "COMAIDE Corporation" }, - { 0x0A69, "Chroma ate Inc." }, - { 0x0A6A, "Newcom Inc." }, - { 0x0A6B, "Green House Co., Ltd." }, - { 0x0A6C, "Integrated Circuit Systems Inc." }, - { 0x0A6D, "UPS Manufacturing" }, - { 0x0A6E, "Benwin" }, - { 0x0A6F, "Core Technology, Inc." }, - { 0x0A70, "International Game Technology" }, - { 0x0A71, "VIPColor Technologies USA, Inc." }, - { 0x0A72, "Sanwa Denshi" }, - { 0x0A73, "SYDEC N.V." }, - { 0x0A74, "Adaptive Networks, Inc." }, - { 0x0A75, "Jeol USA, Inc." }, - { 0x0A76, "I-Jam Multi-Media, LLC" }, - { 0x0A77, "Janome Sewing Machine Co., Ltd." }, - { 0x0A78, "GREATSUN" }, - { 0x0A79, "Geocast Network Systems, Inc." }, - { 0x0A7A, "Towitoko AG" }, - { 0x0A7B, "R & D Co., Ltd." }, - { 0x0A7C, "QUANCOM Informationssysteme GmbH" }, - { 0x0A7D, "Intertek NSTL" }, - { 0x0A7E, "Octagon Systems Corporation" }, - { 0x0A7F, "AVerMedia MicroSystems" }, - { 0x0A80, "Rexon Technology Corp., Ltd" }, - { 0x0A81, "CHESEN ELECTRONICS CORP." }, - { 0x0A82, "SYSCAN" }, - { 0x0A83, "NextComm, Inc." }, - { 0x0A84, "Maui Innovative Peripherals" }, - { 0x0A85, "IDEXX LABS" }, - { 0x0A86, "NITGen Co., Ltd." }, - { 0x0A87, "Tucker-Davis Technologies, Inc." }, - { 0x0A88, "PAH-RAN TECH., INC." }, - { 0x0A89, "Active Company" }, - { 0x0A8A, "American Magnetics" }, - { 0x0A8B, "Intelliworxx Inc." }, - { 0x0A8C, "Tecmar" }, - { 0x0A8D, "Picturetel" }, - { 0x0A8E, "Japan Aviation Electronics Industry Ltd. (JAE)" }, - { 0x0A8F, "Young Chang Co. Ltd." }, - { 0x0A90, "Candy Technology Co., Ltd." }, - { 0x0A91, "Globlink Technology Inc." }, - { 0x0A92, "EGO SYStems Inc." }, - { 0x0A93, "C Technologies AB (publ)" }, - { 0x0A94, "Intersense" }, - { 0x0A95, "Origin Instruments Corporation" }, - { 0x0A96, "Evation.com" }, - { 0x0A97, "Guardware Systems Ltd." }, - { 0x0A98, "TECHNO ART CO., LTD" }, - { 0x0A99, "Talon Technology" }, - { 0x0A9A, "Business Navigator" }, - { 0x0A9B, "Input/Output Inc." }, - { 0x0A9C, "Applied Cytometry Systems" }, - { 0x0A9D, "Jung & Dusch GmbH" }, - { 0x0A9E, "Performance Concepts, Inc." }, - { 0x0A9F, "Sim-Addicts Design Group" }, - { 0x0AA0, "Vtech Communications Ltd." }, - { 0x0AA1, "Amer.com" }, - { 0x0AA2, "Delta Tau Data Systems, Inc." }, - { 0x0AA3, "Lava Computer Mfg. Inc." }, - { 0x0AA4, "Develco Elektronik" }, - { 0x0AA5, "First International Digital" }, - { 0x0AA6, "Perception Digital Limited" }, - { 0x0AA7, "Wincor Nixdorf GmbH & Co KG" }, - { 0x0AA8, "TriGem Computer, Inc." }, - { 0x0AA9, "Baromtec Co." }, - { 0x0AAA, "Japan CBM Corporation" }, - { 0x0AAB, "Vision Shape Europe SA." }, - { 0x0AAC, "iCompression Inc." }, - { 0x0AAD, "Rohde & Schwarz GmbH & Co. KG" }, - { 0x0AAE, "NEC infrontia Corporation" }, - { 0x0AAF, "digitalway co., ltd." }, - { 0x0AB0, "Arrow Strong Electronics CO. LTD" }, - { 0x0AB1, "Feig Electronic GmbH" }, - { 0x0AB2, "Sintefex Audio LDA" }, - { 0x0AB3, "CANON FINETECH INC." }, - { 0x0AB4, "esd electronic system design gmbh" }, - { 0x0AB5, "Beckman Coulter, Inc." }, - { 0x0AB6, "Labsystems Oy" }, - { 0x0AB7, "Cross electronics, inc." }, - { 0x0AB8, "TelePhotogenics, Inc." }, - { 0x0AB9, "Identcode Ltd." }, - { 0x0ABA, "University of Geneva" }, - { 0x0ABB, "Travsys BV" }, - { 0x0ABC, "Life-Tech, Inc." }, - { 0x0ABD, "Wako Rubber Industries Co., Ltd." }, - { 0x0ABE, "STEREOLINK.COM" }, - { 0x0ABF, "DeVaSys" }, - { 0x0AC0, "Nidek Co., Ltd." }, - { 0x0AC1, "MicroDatec GmbH" }, - { 0x0AC2, "BrainMaster Technologies, Inc." }, - { 0x0AC3, "ON Semiconductor (System Solutions Co., Ltd)" }, - { 0x0AC4, "LECO CORPORATION" }, - { 0x0AC5, "I & C Corporation" }, - { 0x0AC6, "Singing Electrons, Inc." }, - { 0x0AC7, "Panwest Corporation" }, - { 0x0AC8, "Vimicro Corporation" }, - { 0x0AC9, "Micro Solutions, Inc." }, - { 0x0ACA, "The Open Group" }, - { 0x0ACB, "DEICY CORPORATION" }, - { 0x0ACC, "Koga Electronics Co." }, - { 0x0ACD, "ID Tech" }, - { 0x0ACE, "ZyDAS Technology Corporation" }, - { 0x0ACF, "Intoto, Inc." }, - { 0x0AD0, "Intellix Corp." }, - { 0x0AD1, "Remotec Technology Ltd." }, - { 0x0AD2, "Service & Quality Technology Co., Ltd." }, - { 0x0AD3, "Bolton Engineering, Inc." }, - { 0x0AD4, "TIGEREX ENTERPRISE CO., LTD." }, - { 0x0AD5, "kuwatec, Inc." }, - { 0x0AD6, "Vir A/S" }, - { 0x0AD7, "Lynium L.L.C." }, - { 0x0AD8, "Aidonic Corporation" }, - { 0x0AD9, "Avolites Ltd." }, - { 0x0ADA, "Data Encryption Systems Ltd" }, - { 0x0ADB, "T.A.M. Co., Ltd." }, - { 0x0ADC, "KE Knestel Elektronik GmbH" }, - { 0x0ADD, "Alliance Distribution" }, - { 0x0ADE, "Microft Co., Ltd." }, - { 0x0ADF, "Arial Phone L.L.C." }, - { 0x0AE0, "Collins Medical" }, - { 0x0AE1, "Protein Solutions, Inc." }, - { 0x0AE2, "NERA SATCOM ASA" }, - { 0x0AE3, "Allion Labs, Inc." }, - { 0x0AE4, "Taito Corporation" }, - { 0x0AE5, "MacroSystem Digital Video AG" }, - { 0x0AE6, "EVI, Inc." }, - { 0x0AE7, "Neodym Systems Inc." }, - { 0x0AE8, "System Support Co., Ltd." }, - { 0x0AE9, "North Shore Circuit Design L.L.P." }, - { 0x0AEA, "SciEssence, LLC" }, - { 0x0AEB, "TTP Communications Ltd." }, - { 0x0AEC, "Neodio Technologies Corporation" }, - { 0x0AED, "ScottCare Corporation" }, - { 0x0AEE, "Max Co., Ltd." }, - { 0x0AEF, "Simple Systems, Ltd." }, - { 0x0AF0, "Option NV" }, - { 0x0AF1, "KYOEI Co., Ltd." }, - { 0x0AF2, "CARTS, LLC" }, - { 0x0AF3, "Scale Master Technology, LLC." }, - { 0x0AF4, "ARTRONICS CO. LTD" }, - { 0x0AF5, "Nakamichi" }, - { 0x0AF6, "SILVER I CO., LTD." }, - { 0x0AF7, "B2C2, Inc." }, - { 0x0AF8, "Taiwan Regular Electronics Co., Ltd." }, - { 0x0AF9, "NEW AFA TECHNOLOGY CO., LTD" }, - { 0x0AFA, "DMC Co., Ltd." }, - { 0x0AFB, "OO-ALC/TISMD-CAPRE" }, - { 0x0AFC, "Zaptronix Ltd" }, - { 0x0AFD, "Tateno Dennou, Inc." }, - { 0x0AFE, "Cummins Engine Company" }, - { 0x0AFF, "Jump Zone Network Products, Inc." }, - { 0x0B00, "INGENICO" }, - { 0x0B01, "Techno-Holon Corporation" }, - { 0x0B02, "Avery Weigh-Tronix" }, - { 0x0B03, "ARCA TECHNOLOGIES, LTD." }, - { 0x0B04, "EURESYS S.A." }, - { 0x0B05, "ASUSTek Computer Inc." }, - { 0x0B06, "Digital Ink, Inc." }, - { 0x0B07, "Telebau GmbH" }, - { 0x0B08, "Lightwell Co., Ltd ZAX Division" }, - { 0x0B09, "Allophonic Electronics L.t.d." }, - { 0x0B0A, "FARO Technologies INC." }, - { 0x0B0B, "Datamax Corporation" }, - { 0x0B0C, "Todos Data System AB" }, - { 0x0B0D, "Project Lab" }, - { 0x0B0E, "GN Audio" }, - { 0x0B0F, "AVID Technology" }, - { 0x0B10, "Pcally" }, - { 0x0B11, "I Tech Solutions Co., Ltd." }, - { 0x0B12, "T-Metrics, Inc." }, - { 0x0B13, "Practical Micro Design, Inc." }, - { 0x0B14, "Real Sport, Inc." }, - { 0x0B15, "Actia Do Brasil Ind. E. Com. Ltda." }, - { 0x0B16, "onscreen24" }, - { 0x0B17, "Scantron Corporation" }, - { 0x0B18, "Shimizu Works, Hitachi Air Conditioning Systems Co" }, - { 0x0B19, "Color Kinetics Inc." }, - { 0x0B1B, "Bematech Ind. Com. Equip. Elect. S.A." }, - { 0x0B1C, "York Electronics Centre" }, - { 0x0B1D, "Erich Jaeger GmbH" }, - { 0x0B1E, "Electronic Warfare Associates, Inc. (EWA)" }, - { 0x0B1F, "Insyde Software Corp." }, - { 0x0B20, "TransDimension Inc." }, - { 0x0B21, "Yokogawa Electric Corporation" }, - { 0x0B22, "Japan System Development Co. Ltd." }, - { 0x0B23, "Pan-Asia Electronics Co., Ltd." }, - { 0x0B24, "ITX E-Globaledge Corporation" }, - { 0x0B25, "Advanced Programming Concepts, Inc." }, - { 0x0B26, "Applied Scientific Instrumentation Inc." }, - { 0x0B27, "Ritek Corporation" }, - { 0x0B28, "Kenwood Corporation" }, - { 0x0B29, "Intertex Data AB" }, - { 0x0B2A, "Glotrex Co., Ltd." }, - { 0x0B2C, "Village Center, Inc." }, - { 0x0B2D, "Akatsuki Electronic work & study Corp." }, - { 0x0B2E, "CTL Inc." }, - { 0x0B2F, "Clarkspur Design, Inc." }, - { 0x0B30, "NewHeights Software" }, - { 0x0B31, "Kyowa Electronic Instruments Co., Ltd." }, - { 0x0B32, "Utrecht University MBF" }, - { 0x0B33, "Contour Design, Inc." }, - { 0x0B34, "KNP Technologies" }, - { 0x0B35, "Solutions Cubed" }, - { 0x0B36, "Iizuna Signal Processing Lab Inc." }, - { 0x0B37, "Hitachi ULSI Systems Co., Ltd." }, - { 0x0B39, "Omnidirectional Control Technology Inc." }, - { 0x0B3A, "IPaxess" }, - { 0x0B3B, "Bromax Communications, Inc." }, - { 0x0B3C, "Olivetti S.p.A" }, - { 0x0B3E, "Kikusui Electronics Corporation" }, - { 0x0B3F, "Mitec Systems, Inc." }, - { 0x0B40, "RF Solutions Ltd." }, - { 0x0B41, "Hal Corporation" }, - { 0x0B42, "LENZE GmbH & Co KG" }, - { 0x0B43, "Sixth Avenue Designs" }, - { 0x0B44, "Programa Tools, Inc." }, - { 0x0B45, "Event Electronics, LLC" }, - { 0x0B46, "Nuark Co., Ltd." }, - { 0x0B47, "Sportbug.com, Inc" }, - { 0x0B48, "TechnoTrend AG" }, - { 0x0B49, "ASCII Corporation" }, - { 0x0B4A, "Pocket Pyro, Inc." }, - { 0x0B4B, "XFX Creation Inc." }, - { 0x0B4C, "Comvurgent" }, - { 0x0B4D, "Graphtec" }, - { 0x0B4E, "Musical Electronics Ltd." }, - { 0x0B4F, "Neuralog, Inc." }, - { 0x0B50, "Starlight Marketing (H.K.) Ltd." }, - { 0x0B51, "USB KITS" }, - { 0x0B52, "Zight Corporation" }, - { 0x0B54, "Sinbon Electronics Co., Ltd." }, - { 0x0B55, "Sendtek Corporation" }, - { 0x0B56, "TYI Systems Ltd." }, - { 0x0B57, "Hanwang Technology Co., LTD." }, - { 0x0B59, "Lake Communications Ltd." }, - { 0x0B5A, "Corel Corporation" }, - { 0x0B5B, "Anritsu Corporation" }, - { 0x0B5C, "IDEAL Industries Inc." }, - { 0x0B5D, "Music Playground Inc." }, - { 0x0B5E, "Luciol Instruments" }, - { 0x0B5F, "Green Electronics Co., Ltd." }, - { 0x0B60, "SiConnect Ltd." }, - { 0x0B61, "NEC Display Solutions, Ltd." }, - { 0x0B62, "Orange Micro, Inc." }, - { 0x0B63, "ADLink Technology Inc." }, - { 0x0B64, "Wonderful Wire Cable Co., Ltd" }, - { 0x0B65, "Expert Magnetics Corp." }, - { 0x0B66, "Cybiko Inc." }, - { 0x0B67, "Fairbanks Scales" }, - { 0x0B68, "SenDEC Corporation" }, - { 0x0B69, "CacheVision" }, - { 0x0B6A, "Maxim Integrated Products" }, - { 0x0B6B, "Ashling Microsystems Ltd." }, - { 0x0B6C, "FreeSystems Pte Ltd" }, - { 0x0B6D, "The Graphics Network Limited" }, - { 0x0B6E, "Neurosoft, Inc." }, - { 0x0B6F, "Nagano Japan Radio Co., Ltd" }, - { 0x0B70, "PortalPlayer, Inc." }, - { 0x0B71, "SHIN-EI Sangyo Co., Ltd." }, - { 0x0B72, "Embedded Wireless Technology Co. Ltd." }, - { 0x0B73, "Computone Corp." }, - { 0x0B75, "Roland DG Corporation" }, - { 0x0B76, "Pro-Tech Services Inc." }, - { 0x0B77, "RJS, Inc." }, - { 0x0B78, "ATSKY" }, - { 0x0B79, "Sunrise Telecom, Inc." }, - { 0x0B7A, "Zeevo, Inc." }, - { 0x0B7B, "Taiko Denki Co., Ltd." }, - { 0x0B7C, "ITRAN Communications Ltd." }, - { 0x0B7D, "Astrodesign, Inc." }, - { 0x0B7E, "Kurusugawa Electronics Incorporate" }, - { 0x0B7F, "Scantech BV" }, - { 0x0B80, "Omtronix Engineering Corp." }, - { 0x0B81, "id3 Semiconductors" }, - { 0x0B82, "TravRoute, a division of ALK Associates, Inc." }, - { 0x0B83, "OCTAX Microscience" }, - { 0x0B84, "Rextron Technology, Inc." }, - { 0x0B85, "Elkat Electronics (M) SDN. BHD." }, - { 0x0B86, "Exputer Systems, Inc." }, - { 0x0B87, "Plus-One I & T Inc." }, - { 0x0B88, "Sigma Koki Co., Ltd. Technology Center" }, - { 0x0B89, "Advanced Digital Broadcast Ltd." }, - { 0x0B8A, "YARC Systems Corporation" }, - { 0x0B8B, "American Microsystems, Ltd." }, - { 0x0B8C, "SMART Technologies Inc." }, - { 0x0B8D, "Microsystems Development Technologies, Inc." }, - { 0x0B8E, "Dartcom" }, - { 0x0B8F, "Visual Environment" }, - { 0x0B90, "DACTRON INC." }, - { 0x0B91, "DesignTech International, Inc." }, - { 0x0B92, "SINAR AG" }, - { 0x0B93, "Marantz Japan, Inc." }, - { 0x0B94, "NEOREX Co., Ltd." }, - { 0x0B95, "ASIX Electronics Corporation" }, - { 0x0B96, "SEWON TELECOM" }, - { 0x0B97, "O2Micro, Inc." }, - { 0x0B98, "Playmates Toys Inc." }, - { 0x0B99, "Audio International, Inc." }, - { 0x0B9A, "Namco Limited" }, - { 0x0B9B, "Dipl.-Ing. Stefan Kunde" }, - { 0x0B9C, "Melco Embroidery Systems" }, - { 0x0B9D, "Softprotec Co." }, - { 0x0B9E, "Asylum Research" }, - { 0x0B9F, "Chippo Technologies" }, - { 0x0BA0, "Turtle Industry Co., Ltd." }, - { 0x0BA1, "Jowit Company Limited" }, - { 0x0BA2, "Line Media Research CO., LTD." }, - { 0x0BA3, "Taiko Electric Works, Ltd." }, - { 0x0BA4, "Nagano Oki Electric Co., Ltd." }, - { 0x0BA5, "Clemex Technologies Inc." }, - { 0x0BA6, "3DM Devices Inc" }, - { 0x0BA7, "CVC Networks Co., Ltd." }, - { 0x0BA8, "CastleNet Technology Inc." }, - { 0x0BA9, "Misawa Homes Co., Ltd." }, - { 0x0BAA, "Dr. Gerhard Schmidt GmbH" }, - { 0x0BAB, "House Ear Institute" }, - { 0x0BAC, "Biometric Access Corporation" }, - { 0x0BAD, "Festo Didactic Ltd/Ltee" }, - { 0x0BAE, "IGEN International, Inc." }, - { 0x0BAF, "U.S. Robotics" }, - { 0x0BB0, "Concord Camera Corp." }, - { 0x0BB1, "Infinilink Corporation" }, - { 0x0BB2, "Ambit Microsystems Corporation" }, - { 0x0BB3, "Ofuji Technology" }, - { 0x0BB4, "HTC Corporation" }, - { 0x0BB5, "Murata Manufacturing Co., Ltd." }, - { 0x0BB6, "Network Alchemy" }, - { 0x0BB7, "Joytech Computer Company Limited" }, - { 0x0BB8, "Renesas Technology Sales Co., Ltd." }, - { 0x0BB9, "Eiger M & C CO., LTD." }, - { 0x0BBA, "ZACCESS Systems" }, - { 0x0BBB, "General Meters Corporation" }, - { 0x0BBC, "Assistive Technology, Inc." }, - { 0x0BBD, "System Connection, Inc" }, - { 0x0BBE, "ShibaSoku Co., Ltd." }, - { 0x0BBF, "Algo Communication Products Ltd." }, - { 0x0BC0, "Knilink Technology Inc." }, - { 0x0BC1, "FUW YNG ELECTRONICS COMPANY LTD" }, - { 0x0BC2, "Seagate Technology LLC" }, - { 0x0BC3, "IPWireless, Inc." }, - { 0x0BC4, "Microcube Corp." }, - { 0x0BC5, "JCN Co., Ltd." }, - { 0x0BC6, "ExWAY Inc." }, - { 0x0BC7, "X10 Wireless Technology, Inc." }, - { 0x0BC8, "Telmax Communications" }, - { 0x0BC9, "ECI Telecom Ltd" }, - { 0x0BCA, "Startek Engineering Incorporated" }, - { 0x0BCB, "Perfect Technic Enterprise Co. LTD" }, - { 0x0BCC, "Dolphin Interactive" }, - { 0x0BCD, "Mbeware Inc." }, - { 0x0BCE, "I-TEC hanshin Incorporated Company" }, - { 0x0BCF, "Chuo-Engineering Ltd." }, - { 0x0BD0, "Trenz Electronic" }, - { 0x0BD1, "Blue Sky Labs, Inc." }, - { 0x0BD2, "Union Biometrica" }, - { 0x0BD3, "OPHIR OPTRONICS LTD" }, - { 0x0BD4, "NISSIN INC." }, - { 0x0BD5, "Rabbit House Corporation" }, - { 0x0BD6, "Renaissance Learning Inc." }, - { 0x0BD7, "Andrew Pargeter & Associates" }, - { 0x0BD8, "Gamry Instruments, Inc." }, - { 0x0BD9, "Liberty Instruments, Inc." }, - { 0x0BDA, "Realtek Semiconductor Corp." }, - { 0x0BDB, "Ericsson AB" }, - { 0x0BDC, "Y Media Corporation" }, - { 0x0BDD, "Orange PCS" }, - { 0x0BDE, "Thuris Corporation" }, - { 0x0BDF, "PopcomNet Co., Ltd" }, - { 0x0BE0, "Silicon Magic Co., LTD" }, - { 0x0BE1, "COM DEV Wireless" }, - { 0x0BE2, "Kanda Tsushin Kogyo Co., LTD" }, - { 0x0BE3, "TOYO Corporation" }, - { 0x0BE4, "Elka International Ltd." }, - { 0x0BE5, "DOME Imaging Systems, Inc" }, - { 0x0BE6, "Wonderful Photoelectricity (DongGuan), Co., Ltd." }, - { 0x0BE7, "Zanthic Technologies Inc." }, - { 0x0BE8, "M@inNet Communication" }, - { 0x0BE9, "Realistic Interactive, Inc." }, - { 0x0BEA, "Bryce Office Systems" }, - { 0x0BEB, "RPA Electronics Design, LLC" }, - { 0x0BEC, "Idaho Technology" }, - { 0x0BED, "MEI, Inc." }, - { 0x0BEE, "LTK International Limited" }, - { 0x0BEF, "Way2Call Communications" }, - { 0x0BF0, "Pace Micro Technology PLC" }, - { 0x0BF1, "Intracom S.A." }, - { 0x0BF2, "Konexx" }, - { 0x0BF3, "CTI Co., Ltd." }, - { 0x0BF4, "Kuraya-Sanseido Co., Ltd." }, - { 0x0BF5, "Xactex Corporation" }, - { 0x0BF6, "Addonics Technologies, Inc." }, - { 0x0BF7, "Sunny Giken Inc." }, - { 0x0BF8, "Fujitsu Technology Solutions GmbH" }, - { 0x0BF9, "QPICT, Inc." }, - { 0x0BFA, "NKE Corporation" }, - { 0x0BFB, "Grass Valley Group" }, - { 0x0BFC, "Zero Mass Products Inc." }, - { 0x0BFD, "KVASER AB" }, - { 0x0BFE, "Morphy Planning & Co., Ltd" }, - { 0x0BFF, "Damotech Inc." }, - { 0x0C00, "ATM Computer" }, - { 0x0C01, "K-One Telecom Co., Ltd." }, - { 0x0C02, "Shinko Seisakusho Co., LTD" }, - { 0x0C03, "SAXA Inc." }, - { 0x0C04, "MOTO Development Group, Inc." }, - { 0x0C05, "Appian Graphics" }, - { 0x0C06, "Hasbro, Inc." }, - { 0x0C07, "Infinite Data Storage LTD" }, - { 0x0C08, "ei Corporation" }, - { 0x0C09, "Comjet Information System" }, - { 0x0C0A, "Highpoint Technologies, Inc." }, - { 0x0C0B, "Dura Micro, Inc." }, - { 0x0C0C, "OPTIKON 2000 S.P.A." }, - { 0x0C0D, "Callify Communications & Software Ltd." }, - { 0x0C0E, "Korea eBook Inc." }, - { 0x0C0F, "IDS Innomic GmbH" }, - { 0x0C10, "Silicon Wave" }, - { 0x0C11, "Multigon Industries" }, - { 0x0C12, "Zeroplus Technology Co; LTD" }, - { 0x0C13, "Orion Electronics International" }, - { 0x0C14, "Parallel Technologies, Inc." }, - { 0x0C15, "Iris Graphics" }, - { 0x0C16, "Gyration, Inc." }, - { 0x0C17, "Cyberboard A/S" }, - { 0x0C18, "SynerTek Korea, Inc." }, - { 0x0C19, "cyberPIXIE, Inc." }, - { 0x0C1A, "Silicon Motion, Inc." }, - { 0x0C1B, "MIPS TECHNOLOGIES" }, - { 0x0C1C, "Hang Zhou Silan Microelectronics Co. Ltd" }, - { 0x0C1D, "Digital Audio Corporation" }, - { 0x0C1E, "TAKAYA CORP." }, - { 0x0C1F, "Magicard Ltd" }, - { 0x0C20, "Viditec Inc." }, - { 0x0C21, "Lunatronic" }, - { 0x0C22, "TallyGenicom LP" }, - { 0x0C23, "Lernout + Hauspie (L + H)" }, - { 0x0C24, "Taiyo Yuden Co., Ltd." }, - { 0x0C25, "Sampo Corporation" }, - { 0x0C26, "Icom Inc." }, - { 0x0C27, "RF Ideas" }, - { 0x0C28, "ICCC" }, - { 0x0C29, "SOGECLAIR aerospace" }, - { 0x0C2A, "AFP Imaging Corp." }, - { 0x0C2B, "AT system" }, - { 0x0C2C, "Controller Technologies Corporation" }, - { 0x0C2D, "Scientific Data Systems, Inc." }, - { 0x0C2E, "Honeywell Scanning & Mobility" }, - { 0x0C2F, "Starcover GmbH" }, - { 0x0C30, "MUTOH EUROPE N.V." }, - { 0x0C31, "Cosmo Techs Co., Ltd." }, - { 0x0C32, "Weibel Scientific A/S" }, - { 0x0C33, "GN Otometrics A/S" }, - { 0x0C34, "Interisa Electronica" }, - { 0x0C35, "Eagletron Inc." }, - { 0x0C36, "E INK CORPORATION" }, - { 0x0C37, "e.Digital" }, - { 0x0C38, "Der An Electric Wire & Cable Co. Ltd." }, - { 0x0C39, "Aeroflex" }, - { 0x0C3A, "Furui Precise Component (Kunshan) Co., Ltd" }, - { 0x0C3B, "Komatsu Ltd." }, - { 0x0C3C, "Radius Co., Ltd." }, - { 0x0C3D, "Innocom, Inc." }, - { 0x0C3E, "NEXTCELL INC." }, - { 0x0C3F, "Street Smart Security" }, - { 0x0C40, "Navini Networks, Inc" }, - { 0x0C41, "findtheDOT" }, - { 0x0C42, "OMAX Corporation" }, - { 0x0C43, "BIOMETRIKA" }, - { 0x0C44, "Motorola iDEN" }, - { 0x0C45, "Sonix Technology Co., Ltd." }, - { 0x0C46, "WaveRider Communications, Inc" }, - { 0x0C47, "TECAN Group AG" }, - { 0x0C48, "MARPOSS S.p.A." }, - { 0x0C49, "Gigahertz-Optik GmbH" }, - { 0x0C4A, "ALGE-TIMING GmbH & Co" }, - { 0x0C4B, "REINER Kartengeraete GmbH & Co.KG" }, - { 0x0C4C, "Needham's Electronics Inc" }, - { 0x0C4D, "ICHIRO.ORG" }, - { 0x0C4E, "Sonic Innovations, Inc." }, - { 0x0C4F, "01dB-Stell" }, - { 0x0C50, "Forvus Research Inc." }, - { 0x0C51, "Trax Softworks, Inc." }, - { 0x0C52, "Sealevel Systems, Inc." }, - { 0x0C53, "ViewPLUS Inc." }, - { 0x0C54, "GLORY LTD." }, - { 0x0C55, "Spectrum Digital Inc." }, - { 0x0C56, "Billion Bright (HK) Corporation Limited" }, - { 0x0C57, "Imaginative Design Operation Co. Ltd." }, - { 0x0C58, "Vidar Systems Corporation" }, - { 0x0C59, "Dong Guan Shinko Wire Co., Ltd." }, - { 0x0C5A, "TRS International Mfg., Inc." }, - { 0x0C5B, "EDEC Co., Ltd." }, - { 0x0C5C, "Obbligato Objectives" }, - { 0x0C5D, "Musitronics GmbH" }, - { 0x0C5E, "Xytronix Research & Design" }, - { 0x0C5F, "WAVESYSTEMS" }, - { 0x0C60, "Apogee Electronics Corporation" }, - { 0x0C61, "Network Security Technology Co." }, - { 0x0C62, "Chant Sincere Co., Ltd" }, - { 0x0C63, "Toko, Inc." }, - { 0x0C64, "Signality System Engineering Co., Ltd." }, - { 0x0C65, "Eminence Enterprise Co., Ltd." }, - { 0x0C66, "REXON ELECTRONICS CORP." }, - { 0x0C67, "Concept Telecom Ltd" }, - { 0x0C68, "Whanam Electronics Co., Ltd." }, - { 0x0C69, "COMPUTechnic AG" }, - { 0x0C6A, "Ackerman Computer Sciences" }, - { 0x0C6B, "Spectrum Techniques, Inc" }, - { 0x0C6C, "JETI Technische Instrumente GmbH" }, - { 0x0C6D, "Aardvark" }, - { 0x0C6E, "Zaxus Limited" }, - { 0x0C6F, "SCC Research" }, - { 0x0C70, "MCT Elektronikladen" }, - { 0x0C71, "Fa. Hydrotechnik" }, - { 0x0C72, "PEAK-System-Technik" }, - { 0x0C73, "Omega Well Monitoring" }, - { 0x0C74, "Optronic Laboratories, Inc." }, - { 0x0C75, "Ripmax Plc" }, - { 0x0C76, "Solid State System Co., Ltd." }, - { 0x0C77, "SIPIX GROUP LIMITED" }, - { 0x0C78, "Detto Corporation" }, - { 0x0C79, "NuConnex Technologies PTE LTD" }, - { 0x0C7A, "Wing-Span Enterprise Co., Ltd." }, - { 0x0C7B, "Link Instruments, Inc." }, - { 0x0C7C, "TMS International BV" }, - { 0x0C7E, "KIRK telecom" }, - { 0x0C7F, "SoftBaugh, Inc." }, - { 0x0C80, "Optim Electronics" }, - { 0x0C81, "Dragon State Ltd." }, - { 0x0C82, "Impeccable Instruments, LLC" }, - { 0x0C83, "Cylink" }, - { 0x0C84, "Howell Instruments, Inc." }, - { 0x0C85, "Lectra Systemes" }, - { 0x0C86, "NDA Technologies, Inc." }, - { 0x0C87, "Aubit, Ltd." }, - { 0x0C88, "Kyocera Wireless Inc." }, - { 0x0C89, "Honda Tsushin Kogyo Co., Ltd" }, - { 0x0C8A, "Cast Lighting Limited" }, - { 0x0C8B, "Wavefly Corporation" }, - { 0x0C8C, "Coactive Networks" }, - { 0x0C8D, "Greenlee Textron, Inc." }, - { 0x0C8E, "Cesscom Co., Ltd." }, - { 0x0C8F, "Applied Microsystems" }, - { 0x0C90, "American Arium" }, - { 0x0C91, "FPGA Information" }, - { 0x0C92, "Nixvue Systems PTE LTD" }, - { 0x0C93, "Alara Inc." }, - { 0x0C94, "SAGEM Denmark" }, - { 0x0C95, "Kyushu-Kyohan Co., Ltd." }, - { 0x0C96, "TOPCON Positioning Systems" }, - { 0x0C97, "GRE America, Inc." }, - { 0x0C98, "Berkshire Products, Inc." }, - { 0x0C99, "Innochips Co., Ltd." }, - { 0x0C9A, "Hanool Robotics Corp" }, - { 0x0C9B, "Jobin Yvon, Inc." }, - { 0x0C9C, "Brand Innovators" }, - { 0x0C9D, "DyOcean" }, - { 0x0C9E, "PLEXUS MULTIMEDIA PTE LTD" }, - { 0x0C9F, "Extenex Corporation" }, - { 0x0CA0, "Robert Bosch GmbH - Automotive Aftermarket" }, - { 0x0CA1, "Mentor Engineering, Inc." }, - { 0x0CA2, "Zyfer" }, - { 0x0CA3, "SEGA CORPORATION" }, - { 0x0CA4, "ST&T INSTRUMENT CORP." }, - { 0x0CA5, "BAE SYSTEMS CANADA INC." }, - { 0x0CA6, "Castles Technology Co. Ltd." }, - { 0x0CA7, "Information Systems Laboratories" }, - { 0x0CA8, "Digital Audio Labs, Inc." }, - { 0x0CA9, "Institut fuer Rundfunktechnik" }, - { 0x0CAA, "Allied Telesis K.K." }, - { 0x0CAB, "Melon Technos Co., Ltd." }, - { 0x0CAC, "NEC Electronics (Europe) GmbH" }, - { 0x0CAD, "Motorola Solutions" }, - { 0x0CAE, "swissvoice ag" }, - { 0x0CAF, "Buslink" }, - { 0x0CB0, "Flying Pig Systems" }, - { 0x0CB1, "Innovonics, Inc." }, - { 0x0CB2, "Softmark" }, - { 0x0CB3, "FitzSimons Automation" }, - { 0x0CB4, "PalmMicro Communications, Inc." }, - { 0x0CB5, "Esel International Company Ltd." }, - { 0x0CB6, "Celestix Networks PTE LTD" }, - { 0x0CB7, "Singatron Enterprise Co. Ltd." }, - { 0x0CB8, "Opticis Co., Ltd." }, - { 0x0CB9, "VTECH INFORMATIONS LTD." }, - { 0x0CBA, "Trust Electronic (Shanghai) Co., Ltd." }, - { 0x0CBB, "Shanghai Darong Electronics Co., Ltd." }, - { 0x0CBC, "PALMAX Technology Co., Ltd." }, - { 0x0CBD, "Pentel Co., Ltd. (Electronics Equipment Div.)" }, - { 0x0CBE, "Keryx Technologies, Inc." }, - { 0x0CBF, "Union Genius Computer Co., Ltd" }, - { 0x0CC0, "Kuon Yi Industrial Corp." }, - { 0x0CC2, "Timex Corporation" }, - { 0x0CC3, "Rimage Corporation" }, - { 0x0CC4, "emsys Embedded Systems GmbH" }, - { 0x0CC5, "SENDO" }, - { 0x0CC6, "INTERMAGIC CORP." }, - { 0x0CC7, "Kontron Medical AG" }, - { 0x0CC8, "Technotools Corporation" }, - { 0x0CC9, "BroadMAX Technologies, Inc." }, - { 0x0CCA, "Amphenol Corporation" }, - { 0x0CCB, "SKNET CORPORATION LTD." }, - { 0x0CCC, "DOMEX TECHNOLOGY CORPORATION" }, - { 0x0CCD, "TerraTec Electronic GmbH" }, - { 0x0CCE, "Optical Imaging Inc." }, - { 0x0CCF, "T&D CORPORATION" }, - { 0x0CD0, "Art Haven 9 Co., Ltd" }, - { 0x0CD1, "Premier Technologies, Inc." }, - { 0x0CD2, "C-MAP SRL" }, - { 0x0CD3, "Pretorian Manufacturing Ltd" }, - { 0x0CD4, "Amplex" }, - { 0x0CD5, "Colorado Circuitworks, Inc." }, - { 0x0CD6, "Scheldt & Bachmann GmbH" }, - { 0x0CD7, "NEWCHIP S.r.l." }, - { 0x0CD8, "JS Digitech, Inc." }, - { 0x0CD9, "Shin Din Cable Ltd." }, - { 0x0CDA, "INTERFACE K.K." }, - { 0x0CDB, "OSMOOZE S.A." }, - { 0x0CDC, "HIJI HIGH-TECH CO., LTD." }, - { 0x0CDD, "Fidelica Microsystems, Inc." }, - { 0x0CDE, "Z-Com INC." }, - { 0x0CDF, "BUZZ-VC" }, - { 0x0CE0, "ZAPEX Research Ltd." }, - { 0x0CE1, "Pepperoni Light" }, - { 0x0CE2, "Eltech Solutions Inc." }, - { 0x0CE3, "MaxVision Corporation" }, - { 0x0CE4, "JOOHONG" }, - { 0x0CE5, "Hemisphere West" }, - { 0x0CE6, "First Silicon Solutions, Inc." }, - { 0x0CE7, "Bakker IT Services BV" }, - { 0x0CE8, "Interflex Datensysteme GmbH" }, - { 0x0CE9, "Pico Technology Limited" }, - { 0x0CEA, "PRO TECH COMMUNICATIONS INC." }, - { 0x0CEB, "Sophia Systems Co., Ltd." }, - { 0x0CEC, "Cyverse Corp." }, - { 0x0CED, "MAYCOM Audio Systems b.v." }, - { 0x0CEE, "Gaitmat II" }, - { 0x0CEF, "Contex A/S" }, - { 0x0CF0, "Cadac Electronics plc." }, - { 0x0CF1, "e-CONN ELECTRONIC CO., LTD." }, - { 0x0CF2, "ENE Technology Inc." }, - { 0x0CF3, "Qualcomm Atheros, Inc." }, - { 0x0CF4, "Fomtex Corporation" }, - { 0x0CF5, "Cellink Co., Ltd." }, - { 0x0CF6, "Compucable Corporation" }, - { 0x0CF7, "ishoni Networks" }, - { 0x0CF8, "Clarisys Incorporated" }, - { 0x0CF9, "Central System Research Co., Ltd." }, - { 0x0CFA, "Inviso, Inc." }, - { 0x0CFB, "SEnergy Corporation" }, - { 0x0CFC, "Konica-Minolta" }, - { 0x0CFD, "Hitex UK Ltd." }, - { 0x0CFE, "L.J. Technical Systems Ltd." }, - { 0x0CFF, "SAFA MEDIA CO., LTD." }, - { 0x0D00, "Polar Instruments Ltd" }, - { 0x0D01, "Red Bird LLC" }, - { 0x0D02, "Vestibular Technolgies" }, - { 0x0D03, "Triad Spectrum Ltd." }, - { 0x0D04, "Addmaster Corporation" }, - { 0x0D05, "Chung Nam Electronics Co. Ltd." }, - { 0x0D06, "telos EDV Systementwicklung GmbH" }, - { 0x0D07, "TAUREUS s.r.o." }, - { 0x0D08, "UTStarcom (Hangzhou) Telecom Co., Ltd" }, - { 0x0D09, "MMELECTRONICS" }, - { 0x0D0A, "Colourfull Creations" }, - { 0x0D0B, "Contemporary Controls" }, - { 0x0D0C, "Astron Electronics Co., Ltd." }, - { 0x0D0D, "MKNet Corporation" }, - { 0x0D0E, "Hybrid Networks, Inc" }, - { 0x0D0F, "Feng Shin Cable Co. Ltd." }, - { 0x0D10, "Elastic Networks" }, - { 0x0D11, "Maspro Denkoh Corp." }, - { 0x0D12, "Hansol Electronics Inc." }, - { 0x0D13, "BMF CORPORATION" }, - { 0x0D14, "Array Comm, Inc." }, - { 0x0D15, "OnStream b.v." }, - { 0x0D16, "Hi-Touch Imaging Technologies Co., Ltd." }, - { 0x0D17, "NALTEC, Inc." }, - { 0x0D18, "coaXmedia" }, - { 0x0D19, "Shanghai Hank Connection Co., Ltd." }, - { 0x0D1A, "COMTECH SYSTEMS, INC" }, - { 0x0D1B, "EC Engineering, LLC" }, - { 0x0D1C, "MACSEMA, INC" }, - { 0x0D1D, "GEMAC mbH" }, - { 0x0D1E, "Eone Inc." }, - { 0x0D1F, "imc MessSysteme GmbH" }, - { 0x0D20, "Malcom Co., Ltd." }, - { 0x0D22, "Rojone Pty Ltd" }, - { 0x0D23, "SATAKE USA INC." }, - { 0x0D24, "Trapper Data AB" }, - { 0x0D25, "PENTTECH Engineering Systems AB" }, - { 0x0D26, "Micro-Vu" }, - { 0x0D27, "CLEARJET GmbH" }, - { 0x0D28, "ARM Ltd" }, - { 0x0D29, "Eng Resource Inc" }, - { 0x0D2A, "FIELDSERVER TECHNOLOGIES" }, - { 0x0D2B, "DAINIPPON SCREEN" }, - { 0x0D2C, "3M Library Systems" }, - { 0x0D2D, "GigaSysNet" }, - { 0x0D2E, "Feedback Instruments Ltd" }, - { 0x0D2F, "Andamiro Co., Ltd." }, - { 0x0D30, "Vision Electronics Co., Ltd." }, - { 0x0D31, "Arizona Cooperative Power" }, - { 0x0D32, "Leo Hui Electric Wire & Cable Co., Ltd." }, - { 0x0D33, "AirSpeak Inc." }, - { 0x0D34, "Moxi Digital, Inc." }, - { 0x0D35, "Dah Kun Co., Ltd." }, - { 0x0D36, "Tellabs" }, - { 0x0D37, "PRISM" }, - { 0x0D38, "Nihon Culture-soft Service Co., Ltd." }, - { 0x0D3A, "Posiflex Technologies, Inc." }, - { 0x0D3B, "SANYO TECNICA Co., Ltd." }, - { 0x0D3C, "SRI CABLE TECHNOLOGY LTD." }, - { 0x0D3D, "TANGTOP TECHNOLOGY CO., LTD." }, - { 0x0D3E, "Fitcom, inc." }, - { 0x0D3F, "MTS Systems Corporation" }, - { 0x0D40, "Ascor Inc." }, - { 0x0D41, "Ta Yun Electronic Technology Co., Ltd." }, - { 0x0D42, "FULL DER CO., LTD." }, - { 0x0D43, "iCableSystem Co., Ltd." }, - { 0x0D44, "AFG Elektronik GmbH" }, - { 0x0D45, "Union Data Corporation" }, - { 0x0D46, "KOBIL Systems GmbH" }, - { 0x0D47, "KOPEK PACIFIC LTD." }, - { 0x0D48, "PROMETHEAN" }, - { 0x0D49, "Maxtor" }, - { 0x0D4A, "NF Corporation" }, - { 0x0D4B, "Grape Systems Inc." }, - { 0x0D4C, "TEDAS AG" }, - { 0x0D4D, "Coherent Inc." }, - { 0x0D4E, "Agere Systems Netherland BV" }, - { 0x0D4F, "EADS AIRBUS FRANCE" }, - { 0x0D50, "Cleware GmbH" }, - { 0x0D51, "Volex (Asia) Pte Ltd" }, - { 0x0D52, "YAMAHA Motor Co., Ltd" }, - { 0x0D53, "HMI Co., Ltd." }, - { 0x0D54, "HOLON Corporation" }, - { 0x0D55, "ASKA Technologies Inc." }, - { 0x0D56, "AVLAB Technology, Inc." }, - { 0x0D57, "SOLOMON Microtech Ltd." }, - { 0x0D59, "CDS electronics bv" }, - { 0x0D5A, "Hoshino Metal Industries, Ltd." }, - { 0x0D5B, "LOGIC CORPORATION" }, - { 0x0D5C, "Eumitcom Technology Inc." }, - { 0x0D5D, "Telesis Technologies, Inc." }, - { 0x0D5E, "MYACOM LTD" }, - { 0x0D5F, "CSI, Inc." }, - { 0x0D60, "IVL Technologies Ltd." }, - { 0x0D61, "MEILU ELECTRONICS (SHENZHEN) CO., LTD." }, - { 0x0D62, "Darfon Electronics Corp." }, - { 0x0D63, "Fritz Gegauf AG" }, - { 0x0D64, "DXG Technology Corp." }, - { 0x0D65, "KMJP CO., LTD." }, - { 0x0D66, "TMT" }, - { 0x0D67, "Advanet Inc." }, - { 0x0D68, "Super Link Electronics Co., Ltd." }, - { 0x0D69, "NSI" }, - { 0x0D6A, "eMegaTech International Corp." }, - { 0x0D6B, "And-Or Logic" }, - { 0x0D6C, "CANMAX Technology Ltd." }, - { 0x0D6D, "Mitsubishi Elec. Micro-Computer App. Software Co." }, - { 0x0D6E, "Forum Trading Ltd. (UK)" }, - { 0x0D70, "Try Computer Co. LTD." }, - { 0x0D71, "Hirakawa Hewtech Corp." }, - { 0x0D72, "Winmate Communication Inc." }, - { 0x0D73, "Hit's Communications INC." }, - { 0x0D74, "Dreams Come True Co., Ltd." }, - { 0x0D75, "LET'S Corporation, Ltd." }, - { 0x0D76, "MFP Korea, Inc." }, - { 0x0D77, "Power Sentry/Newpoint" }, - { 0x0D78, "Japan Distributor Corporation" }, - { 0x0D79, "Assistive Technology Engineering Lab" }, - { 0x0D7A, "MARX CryptoTech LP" }, - { 0x0D7B, "Wellco Technology Co., Ltd." }, - { 0x0D7C, "Taiwan Line Tek Electronic Co., Ltd." }, - { 0x0D7D, "Add-On Technology Co., Ltd." }, - { 0x0D7E, "American Computer & Digital Components" }, - { 0x0D7F, "Essential Reality LLC" }, - { 0x0D80, "H.R. Silvine Electronics Inc." }, - { 0x0D81, "TechnoVision" }, - { 0x0D83, "Think Outside, Inc." }, - { 0x0D84, "ELECTRO-SYSTEM Co., Ltd." }, - { 0x0D85, "Identix Incorporated" }, - { 0x0D86, "Marconi" }, - { 0x0D87, "Dolby Laboratories Inc." }, - { 0x0D88, "Miyoshi Corp." }, - { 0x0D89, "Oz Software" }, - { 0x0D8A, "KING JIM CO., LTD." }, - { 0x0D8B, "Ascom Telecommunications Ltd." }, - { 0x0D8C, "C-MEDIA ELECTRONICS INC." }, - { 0x0D8D, "Promotion & Display Technology Ltd." }, - { 0x0D8E, "Global Sun Technology Inc." }, - { 0x0D8F, "Pitney Bowes" }, - { 0x0D90, "Sure-Fire Electrical Corporation" }, - { 0x0D91, "ALPHA PROJECT Co., Ltd." }, - { 0x0D92, "Mega & Game" }, - { 0x0D93, "Nishitomo Co., Ltd." }, - { 0x0D94, "Advanced Logic Technology (ALT)" }, - { 0x0D95, "Numonics Corp." }, - { 0x0D96, "Skanhex Technology Inc." }, - { 0x0D97, "Santa Barbara Instrument Group (SBIG)" }, - { 0x0D98, "Mars Semiconductor Corp." }, - { 0x0D99, "Trazer Technologies Inc." }, - { 0x0D9A, "RTX Telecom A/S" }, - { 0x0D9B, "Tat Shing Electrical Co." }, - { 0x0D9C, "Chee Chen Hi-Technology Co., Ltd." }, - { 0x0D9D, "Sanwa Supply Inc" }, - { 0x0D9E, "Avaya" }, - { 0x0D9F, "Powercom Co., Ltd." }, - { 0x0DA0, "Danger Research" }, - { 0x0DA1, "Suzhou Peter's Precise Industrial Co., Ltd." }, - { 0x0DA2, "Land Instruments International Ltd." }, - { 0x0DA3, "Nippon Electro-Sensory Devices Corporation" }, - { 0x0DA4, "POLAR ELECTRO OY" }, - { 0x0DA5, "TOKYO MAGNETIC PRINTING CO., LTD." }, - { 0x0DA6, "Aimtron Technology Corp." }, - { 0x0DA7, "IOGEAR, Inc." }, - { 0x0DA8, "softDSP Co., Ltd." }, - { 0x0DA9, "DigiLife Technology Inc." }, - { 0x0DAA, "Derelek" }, - { 0x0DAB, "Diasonic Technology Co., Ltd." }, - { 0x0DAC, "Smart Card Technology, Inc." }, - { 0x0DAD, "Westover Scientific" }, - { 0x0DAE, "SERIAL SYSTEM LTD" }, - { 0x0DAF, "NXTV, Inc." }, - { 0x0DB0, "Micro-Star International Co., Ltd." }, - { 0x0DB1, "Wen Te Electronics Co., Ltd." }, - { 0x0DB2, "Shian Hwi Plug Parts, Plastic Factory" }, - { 0x0DB3, "Tekram Technology Co. Ltd." }, - { 0x0DB4, "Chung Fu Chen Yeh Enterprise Corporation" }, - { 0x0DB5, "Azio Ltd." }, - { 0x0DB6, "SIMS Valley Co., Ltd." }, - { 0x0DB7, "ELCON Systemtechnik GmbH" }, - { 0x0DB8, "Garear Taiwan Co., Ltd." }, - { 0x0DB9, "EMKAY" }, - { 0x0DBA, "DIGIDESIGN" }, - { 0x0DBB, "Luna Analytics, Inc." }, - { 0x0DBC, "A&D Company, Limited" }, - { 0x0DBD, "Bruker Biospin" }, - { 0x0DBE, "Jiuh Shiuh Precision Industry Co., Ltd." }, - { 0x0DBF, "Jess-Link International" }, - { 0x0DC0, "G7 Solutions" }, - { 0x0DC1, "Tamagawa Seiki Co., Ltd." }, - { 0x0DC3, "Athena Smartcard Solutions Inc." }, - { 0x0DC4, "inXtron, Inc." }, - { 0x0DC5, "SDK Co, Ltd." }, - { 0x0DC6, "Precision Squared Technology Corporation" }, - { 0x0DC7, "First Cable Line, Inc." }, - { 0x0DC8, "WINTEC Corporation" }, - { 0x0DC9, "Arvel Corp." }, - { 0x0DCA, "SMaL Camera Technologies, Inc." }, - { 0x0DCB, "RocketPod, Inc." }, - { 0x0DCC, "Largan Digital" }, - { 0x0DCD, "NetworkFab Corporation" }, - { 0x0DCE, "E-MU Systems, Inc., d.b.a. E-MU/ENSONIQ" }, - { 0x0DCF, "Analytik Jena AG" }, - { 0x0DD0, "Access Solutions" }, - { 0x0DD1, "Contek Electronics Co., Ltd." }, - { 0x0DD2, "Power Quotient International Co., Ltd." }, - { 0x0DD3, "MediaQ" }, - { 0x0DD4, "Custom Engineering SPA" }, - { 0x0DD5, "California Micro Devices" }, - { 0x0DD6, "TECHKON GmbH" }, - { 0x0DD7, "KOCOM CO., LTD" }, - { 0x0DD8, "Netac Technology Co., Ltd." }, - { 0x0DD9, "HighSpeed Surfing" }, - { 0x0DDA, "Integrated Silicon Solution, Inc" }, - { 0x0DDB, "Tamarack Inc." }, - { 0x0DDC, "Takaotec" }, - { 0x0DDD, "Datelink Technology Co., Ltd." }, - { 0x0DDE, "UBICOM, INC" }, - { 0x0DDF, "DriveCam Video Systems" }, - { 0x0DE1, "Vidicode Datacommunicatie BV" }, - { 0x0DE2, "Acom Data" }, - { 0x0DE3, "RFTECH CO., LTD." }, - { 0x0DE4, "Aron Digital Inc." }, - { 0x0DE5, "Secure2Net, Inc. USA" }, - { 0x0DE6, "Dentsply Int'l - Gendex Dental Division" }, - { 0x0DE7, "USBmicro" }, - { 0x0DE8, "Delsy Electronic Components AG" }, - { 0x0DE9, "Technische Industrie TACX BV" }, - { 0x0DEA, "UTECH Electronic (D.G.) Co., Ltd." }, - { 0x0DEB, "Lean Horn Co." }, - { 0x0DEC, "Callserve Communications Ltd." }, - { 0x0DED, "Novasonics" }, - { 0x0DEE, "Lifetime Memory Products" }, - { 0x0DEF, "Full Rise Electronic Co., Ltd." }, - { 0x0DF0, "GE Yokogawa Medical Systems, Ltd." }, - { 0x0DF1, "Envoy Medical Corporation" }, - { 0x0DF2, "Nisshin Electronics Co., Ltd." }, - { 0x0DF3, "VeriTek Co., Ltd." }, - { 0x0DF4, "Net & Sys Co., Ltd." }, - { 0x0DF5, "Yamatake Corporation" }, - { 0x0DF6, "Sitecom Europe B.V." }, - { 0x0DF7, "Mobile Action Technology Inc." }, - { 0x0DF8, "Hoya Computer Co., Ltd." }, - { 0x0DF9, "Nice Fountain Industrial Co., Ltd." }, - { 0x0DFA, "Toyo Networks & System Integration Co., Ltd." }, - { 0x0DFB, "Daisy Technology" }, - { 0x0DFC, "General Touch Technology Co., Ltd." }, - { 0x0DFD, "Suruga Seiki Co., Ltd." }, - { 0x0DFE, "Interactive Metronome" }, - { 0x0DFF, "Deodeo Corporation" }, - { 0x0E00, "Novar GmbH" }, - { 0x0E01, "Sheng Xiang Investment Ltd." }, - { 0x0E02, "Doowon Co., LTD" }, - { 0x0E03, "Nippon Systemware Co., Ltd." }, - { 0x0E04, "PowerCom Technology Co., Ltd." }, - { 0x0E05, "Nordic ID" }, - { 0x0E06, "Personal Telecom, Inc." }, - { 0x0E07, "Viewtek Co., Ltd" }, - { 0x0E08, "Winbest Technology Co., Ltd." }, - { 0x0E09, "Winskon Cabling Specialist Co., Ltd." }, - { 0x0E0A, "JAEIK Information & Communication Co., Ltd." }, - { 0x0E0B, "Fujitsu Denso Ltd." }, - { 0x0E0C, "Gesytec GmbH" }, - { 0x0E0D, "Picoquant GmbH" }, - { 0x0E0E, "Fuji Data System Co., Ltd." }, - { 0x0E0F, "VMWare, Inc." }, - { 0x0E10, "TERUMO Corporation (Suruga Factory)" }, - { 0x0E11, "Neurotec" }, - { 0x0E12, "Danam Communications Inc." }, - { 0x0E13, "Lugh Networks, Inc." }, - { 0x0E14, "Hunter Engineering Co." }, - { 0x0E15, "Tellert Elektronik GmbH" }, - { 0x0E16, "JMTEK, LLC" }, - { 0x0E17, "Walex Electronic Ltd." }, - { 0x0E18, "UNIWIDE Technologies" }, - { 0x0E19, "OeRSTED, Inc." }, - { 0x0E1A, "RDM Corporation" }, - { 0x0E1B, "Crewave Co., Ltd." }, - { 0x0E1C, "Beijing Hi-tech Wealth Software Technology Co." }, - { 0x0E1D, "International Parts & Information Co., Ltd." }, - { 0x0E1E, "Green Hills Software, Inc." }, - { 0x0E1F, "Cabin Industrial Co., Ltd." }, - { 0x0E20, "Pegasus Technologies Ltd." }, - { 0x0E21, "Cowon Systems, Inc." }, - { 0x0E22, "Symbian Ltd." }, - { 0x0E23, "Liou Yuane International Ltd." }, - { 0x0E24, "Samson Electric Wire Co., Ltd." }, - { 0x0E25, "VinChip Systems, Inc." }, - { 0x0E26, "J-Phone East Co., Ltd." }, - { 0x0E27, "Thunder Island Limited" }, - { 0x0E28, "Industrial Control Systems" }, - { 0x0E29, "CB Sciences, Inc." }, - { 0x0E2A, "Flight Link Inc." }, - { 0x0E2B, "Kumamoto Techno Corporation" }, - { 0x0E2C, "Intersoft Electronics N.V." }, - { 0x0E2D, "SKF Condition Monitoring" }, - { 0x0E2E, "Brady Corporation" }, - { 0x0E2F, "Daisen Electronic Industrial Co., Ltd." }, - { 0x0E30, "HeartMath LLC" }, - { 0x0E31, "Biosign" }, - { 0x0E32, "ICONAG - Intelligent Control AG" }, - { 0x0E33, "Luna Innovations, Inc." }, - { 0x0E34, "Micro Computer Control Corp." }, - { 0x0E35, "3Pea Technologies, Inc." }, - { 0x0E36, "TiePie engineering" }, - { 0x0E37, "Alpha Data Corp." }, - { 0x0E38, "Stratitec, Inc." }, - { 0x0E39, "Smart Modular Technologies, Inc." }, - { 0x0E3A, "Neostar Technology Co., Ltd." }, - { 0x0E3B, "Mansella Ltd." }, - { 0x0E3C, "Raytec Electronic Co., Ltd." }, - { 0x0E3D, "Metex Corporation" }, - { 0x0E3E, "Good Technology, Inc." }, - { 0x0E3F, "AM Group Corp." }, - { 0x0E40, "Proteq LTDA" }, - { 0x0E41, "Line 6, Inc." }, - { 0x0E42, "Puretek Industrial Co., Ltd." }, - { 0x0E43, "Holly Lin International Technology Inc." }, - { 0x0E44, "Sun-Riseful Technology Co., Ltd." }, - { 0x0E45, "SafeNet B.V." }, - { 0x0E46, "Delphi Corporation" }, - { 0x0E47, "AMANO Corporation" }, - { 0x0E48, "Julia Corporation Limited" }, - { 0x0E49, "Ingenieurbuero Chanda AG" }, - { 0x0E4A, "Shenzhen Bao Hing Electric Wire & Cable Mfr. Co." }, - { 0x0E4B, "System General Corp." }, - { 0x0E4C, "Radica Games Ltd." }, - { 0x0E4D, "Hong Shi Precision Corp." }, - { 0x0E4E, "Lih Duo Intl. Co., Ltd." }, - { 0x0E4F, "Data Ray Corp." }, - { 0x0E50, "TDi GmbH TechnoData Interware" }, - { 0x0E51, "Therapy Information & Communication System Inc." }, - { 0x0E52, "Mindready Solutions (NI) Ltd." }, - { 0x0E53, "King Tester Corporation" }, - { 0x0E54, "KDE, Inc." }, - { 0x0E55, "Speed Dragon Multimedia Ltd." }, - { 0x0E56, "Cenix Digicom Co., Ltd." }, - { 0x0E57, "Loas Co., Ltd" }, - { 0x0E58, "Technology For Energy Corp." }, - { 0x0E59, "Bourns, Inc." }, - { 0x0E5A, "ACTIVE CO., LTD." }, - { 0x0E5B, "Union Power Information Industrial Co., Ltd." }, - { 0x0E5C, "Shenzhen Bitland Information Technology Co., Ltd." }, - { 0x0E5D, "Neltron Industrial Co., Ltd." }, - { 0x0E5E, "Conwise Technology Co., Ltd." }, - { 0x0E5F, "Entone Technologies" }, - { 0x0E60, "XAVi Technologies Corp." }, - { 0x0E61, "E-Pen InMotion Inc." }, - { 0x0E62, "Shandong CVIC Software Engineering Co., Ltd." }, - { 0x0E63, "SECUREPIA Inc." }, - { 0x0E64, "Nida Corporation" }, - { 0x0E65, "Skycom Tek Co., Ltd" }, - { 0x0E66, "Hawking Technologies, Inc." }, - { 0x0E67, "Fossil" }, - { 0x0E68, "Artec" }, - { 0x0E69, "A Global Partner Corporation" }, - { 0x0E6A, "Megawin Technology Co., Ltd." }, - { 0x0E6B, "DMA Korea Co., Ltd" }, - { 0x0E6C, "E & D Co., Ltd." }, - { 0x0E6D, "Tenovis Business Communication" }, - { 0x0E6E, "Volvo Car Corporation" }, - { 0x0E6F, "Performance Designed Products, LLC" }, - { 0x0E70, "Tokyo Electronic Industry Co, LTD." }, - { 0x0E71, "Schwarzer GmbH" }, - { 0x0E72, "Hsi-Chin Electronics Co., Ltd." }, - { 0x0E73, "MCK Communications, Inc." }, - { 0x0E74, "Accu-Automation Corp." }, - { 0x0E75, "TVS Electronics Limited" }, - { 0x0E76, "Seiko S-Yard Co., Ltd" }, - { 0x0E77, "Weinzierl Engineering GmbH" }, - { 0x0E78, "Ascom Powerline Communications Ltd." }, - { 0x0E79, "ARCHOS SA" }, - { 0x0E7A, "Indocomp Systems Inc." }, - { 0x0E7B, "On-Tech Industry Co., Ltd." }, - { 0x0E7C, "Legend Holdings Limited" }, - { 0x0E7D, "Eutectics Inc." }, - { 0x0E7E, "G.Mate, Inc." }, - { 0x0E7F, "Keysight Technologies, Inc. - AFM division" }, - { 0x0E80, "GateHouse A/S" }, - { 0x0E81, "System Consultants Co., Ltd." }, - { 0x0E82, "Ching Tai Electric Wire & Cable Co., Ltd." }, - { 0x0E83, "Shin An Wire & Cable Co." }, - { 0x0E84, "Elelux International Ltd." }, - { 0x0E85, "Dynavox Systems LLC" }, - { 0x0E86, "Watthour Engineering Co., Inc." }, - { 0x0E87, "Internet Security Co., Ltd" }, - { 0x0E88, "ELBIO" }, - { 0x0E89, "PRT Manufacturing Ltd." }, - { 0x0E8A, "FinePoint Innovations, Inc." }, - { 0x0E8B, "KAO SHIN PRECISION INDUSTRY CO., LTD." }, - { 0x0E8C, "Well Force Electronic Co., Ltd" }, - { 0x0E8D, "MediaTek Inc." }, - { 0x0E8E, "Stuart Tyrrell Developments" }, - { 0x0E8F, "Pansignal Technology Inc." }, - { 0x0E90, "CRU" }, - { 0x0E91, "VTech Engineering Canada Ltd." }, - { 0x0E92, "C'S GLORY ENTERPRISE CO., LTD." }, - { 0x0E93, "eM Technics Co., Ltd." }, - { 0x0E94, "Sirona Dental Systems GmbH" }, - { 0x0E95, "Future Technology Co., Ltd" }, - { 0x0E96, "APLUX Communications Ltd." }, - { 0x0E97, "Fingerworks, Inc." }, - { 0x0E98, "Advanced Analogic Technologies, Inc." }, - { 0x0E99, "Parallel Dice Co., Ltd." }, - { 0x0E9A, "TA HSING INDUSTRIES LTD." }, - { 0x0E9B, "ADTEC CORPORATION" }, - { 0x0E9C, "StreamZap, Inc." }, - { 0x0E9D, "Hitron Technologies, Inc." }, - { 0x0E9E, "Japan System Design Co." }, - { 0x0E9F, "TAMURA CORPORATION" }, - { 0x0EA0, "Ours Technology Inc." }, - { 0x0EA1, "Infinite Communication Terminals Ltd." }, - { 0x0EA2, "Triumph Technology Corp." }, - { 0x0EA3, "Rion Co., Ltd." }, - { 0x0EA4, "Intelligent Hearing Systems" }, - { 0x0EA5, "DATA SYSTEM TECHNOLOGY CO., LTD." }, - { 0x0EA6, "Nihon Computer Co., Ltd." }, - { 0x0EA7, "MSL Enterprises Corp." }, - { 0x0EA8, "CenDyne, Inc." }, - { 0x0EA9, "J&J ENGINEERING INC." }, - { 0x0EAA, "TOKYO SOKKI KENKYUJO CO., LTD." }, - { 0x0EAB, "Yiso Telecom" }, - { 0x0EAC, "ALCATech GmbH" }, - { 0x0EAD, "HUMAX Co., Ltd." }, - { 0x0EAE, "Alcon Labs" }, - { 0x0EAF, "Grandex International Corporation" }, - { 0x0EB0, "Amigo Technology Co., Ltd." }, - { 0x0EB1, "WIS Technologies, Inc." }, - { 0x0EB2, "Y-S ELECTRONIC CO., LTD." }, - { 0x0EB3, "Saint Technology Corp." }, - { 0x0EB4, "IPLAN Inc." }, - { 0x0EB5, "@pos.com" }, - { 0x0EB6, "GAMEPARK, Inc." }, - { 0x0EB7, "Endor AG" }, - { 0x0EB8, "Mettler-Toledo (Albstadt) GmbH" }, - { 0x0EB9, "SKY Electronics" }, - { 0x0EBA, "iWOW Connections Pte Ltd" }, - { 0x0EBB, "Thermo Nicolet Corp." }, - { 0x0EBC, "CHOIS Technology" }, - { 0x0EBD, "Kyowa Electronics Co., Ltd." }, - { 0x0EBE, "VWEB Corporation" }, - { 0x0EBF, "Omega Technology Inc." }, - { 0x0EC0, "LHI Technology (China) Co., Ltd." }, - { 0x0EC1, "ABIT Computer Corporation" }, - { 0x0EC2, "Sweetray Industrial Ltd." }, - { 0x0EC3, "Axell Corporation" }, - { 0x0EC4, "Ballracing Developments Ltd." }, - { 0x0EC5, "GT Information System Co., Ltd." }, - { 0x0EC6, "InnoVISION Multimedia Limited" }, - { 0x0EC7, "Theta Link Corporation" }, - { 0x0EC8, "Mitechno Co., Ltd." }, - { 0x0EC9, "HemoCue AB" }, - { 0x0ECA, "Mit System Co., Ltd." }, - { 0x0ECB, "Harman Kardon" }, - { 0x0ECC, "Samsung SDS" }, - { 0x0ECD, "Lite-On IT Corp." }, - { 0x0ECE, "TaiSol Electronics Co., Ltd." }, - { 0x0ECF, "Phogenix Imaging, LLC" }, - { 0x0ED0, "LANergy Limited" }, - { 0x0ED1, "Tai Guen Enterprise Co., Ltd." }, - { 0x0ED2, "Kyoto Micro Computer Co., LTD." }, - { 0x0ED3, "Wing-Tech Enterprise Co., Ltd." }, - { 0x0ED4, "Ross Video" }, - { 0x0ED5, "ChronoLogic Pty. Ltd." }, - { 0x0ED6, "TECHNOS JAPAN Co., LTD." }, - { 0x0ED7, "COSMODOG, LTD." }, - { 0x0ED8, "ASAHI SPECTRA CO., LTD." }, - { 0x0ED9, "Holy Stone Enterprise Co., Ltd." }, - { 0x0EDA, "NORITAKE ITRON CORPORATION" }, - { 0x0EDB, "AboveTech, Inc." }, - { 0x0EDC, "GALTRONICS" }, - { 0x0EDD, "KOWA COMPANY, LTD." }, - { 0x0EDE, "TOD Co., Ltd." }, - { 0x0EDF, "e-MDT Co., Ltd." }, - { 0x0EE0, "SHIMA SEIKI MFG., LTD." }, - { 0x0EE1, "Sarotech Co., Ltd." }, - { 0x0EE2, "AMI Semiconductor Inc." }, - { 0x0EE3, "ComTrue Technology Corporation (Taiwan)" }, - { 0x0EE4, "Sunrich Technology (H.K.) Ltd." }, - { 0x0EE5, "Medical Graphics Corporation" }, - { 0x0EE6, "Takacom Corporation" }, - { 0x0EE7, "Furuno Electric Co., Ltd." }, - { 0x0EE8, "Triz Communications Group" }, - { 0x0EE9, "JPK Systems Limited" }, - { 0x0EEA, "William Demant Holding A/S" }, - { 0x0EEB, "Design Of Systems On Silicon, S.A. (DS2)" }, - { 0x0EEC, "Tritek Co., Ltd." }, - { 0x0EED, "CCP Co., Ltd." }, - { 0x0EEE, "Digital STREAM Technology, Inc." }, - { 0x0EEF, "eGalax Inc." }, - { 0x0EF0, "Hitachi Cable, Ltd." }, - { 0x0EF1, "Aichi Micro Intelligent Corporation" }, - { 0x0EF2, "I/OMAGIC CORPORATION" }, - { 0x0EF3, "Lynn Products, Inc." }, - { 0x0EF4, "DSI Datotech" }, - { 0x0EF5, "PointChips" }, - { 0x0EF6, "Yield Microelectronics Corp." }, - { 0x0EF7, "SM Tech Co., Ltd." }, - { 0x0EF8, "ECT Inc." }, - { 0x0EF9, "eHome TV, Inc. DBA Fuze3 Technologies" }, - { 0x0EFA, "Corepro Entertainment" }, - { 0x0EFB, "ARKRAY, Inc." }, - { 0x0EFC, "ELMEX COMPANY Ltd." }, - { 0x0EFD, "Oasis Semiconductor" }, - { 0x0EFE, "WEM TECHNOLOGY INC." }, - { 0x0EFF, "CSIRO-TIP" }, - { 0x0F00, "ndd Medizintechnik AG" }, - { 0x0F01, "EXPAN Electronics Co., Ltd." }, - { 0x0F02, "MobileAria" }, - { 0x0F03, "Jet Power Technology Co., Ltd." }, - { 0x0F04, "Softlok International Limited" }, - { 0x0F05, "Quanta Network Systems Inc." }, - { 0x0F06, "Visual Frontier Precision Corp." }, - { 0x0F07, "Pakon" }, - { 0x0F08, "CSL Wire & Plug (Shen Zhen) Company" }, - { 0x0F09, "Sandel Arionics Inc." }, - { 0x0F0B, "Great Computer Corporation" }, - { 0x0F0C, "CAS Corporation" }, - { 0x0F0D, "HORI CO., LTD." }, - { 0x0F0E, "Energyfull & Hi-Top International Ltd." }, - { 0x0F0F, "NANOPTIX INC." }, - { 0x0F10, "Personal Information Systems Co., Ltd." }, - { 0x0F11, "Leybold Didactic GMBH" }, - { 0x0F12, "MARS ENGINEERING CORPORATION" }, - { 0x0F13, "Acetek Technology Co., Ltd." }, - { 0x0F14, "XIRING" }, - { 0x0F15, "PlayMore Corporation" }, - { 0x0F16, "GLOBAL VIEW CO. LTD." }, - { 0x0F17, "Correlant Communications" }, - { 0x0F18, "Finger Lakes Instrumentation, LLC" }, - { 0x0F19, "ORACOM CO., Ltd." }, - { 0x0F1A, "General Information Systems Ltd." }, - { 0x0F1B, "Onset Computer Corporation" }, - { 0x0F1C, "Funai Electric Co., Ltd." }, - { 0x0F1D, "Iwill Corporation" }, - { 0x0F1E, "INVAIR Technologies AG" }, - { 0x0F1F, "Laxtha" }, - { 0x0F20, "GENNUM CORPORATION" }, - { 0x0F21, "IOI Technology Corporation" }, - { 0x0F22, "SENIOR INDUSTRIES, INC." }, - { 0x0F23, "Leader Tech Manufacturer Co., Ltd" }, - { 0x0F24, "FLEX-P INDUSTRIES SDN.BHD." }, - { 0x0F25, "Primera Technology Inc." }, - { 0x0F26, "B.G. Technologies, Inc." }, - { 0x0F27, "Alpes DEIS" }, - { 0x0F28, "ESEC SA" }, - { 0x0F29, "TIPTEL AG" }, - { 0x0F2A, "Marconi Data Systems" }, - { 0x0F2B, "XEMICS SA" }, - { 0x0F2D, "ViPower, Inc." }, - { 0x0F2E, "Good Man Corporation" }, - { 0x0F2F, "Priva Design Services" }, - { 0x0F30, "Jess Technology Co., Ltd." }, - { 0x0F31, "Chrysalis Development" }, - { 0x0F32, "YFC-BonEagle Electric Co., Ltd." }, - { 0x0F33, "Futek Electronics, Co., Ltd." }, - { 0x0F34, "Hokuto Denshi Co., Ltd." }, - { 0x0F35, "Kinpo Electronics, Inc." }, - { 0x0F36, "Philips Medical Systems Ultrasound" }, - { 0x0F37, "Kokuyo Co., Ltd." }, - { 0x0F38, "Nien-Yi Industrial Corp." }, - { 0x0F39, "Heng Yu Technology (HK) Ltd." }, - { 0x0F3A, "Aidensi Giken" }, - { 0x0F3B, "IR-LINK" }, - { 0x0F3C, "Numesa, Inc." }, - { 0x0F3D, "AirPrime Inc." }, - { 0x0F3E, "Aastra Broadband" }, - { 0x0F3F, "FEI Electron Optics B.V." }, - { 0x0F40, "Denver Instrument Company" }, - { 0x0F41, "RDC Semiconductor Co., Ltd." }, - { 0x0F42, "Nital Consulting Services, Inc." }, - { 0x0F43, "LiteON Semiconductor Corp." }, - { 0x0F44, "Polhemus Incorporated" }, - { 0x0F45, "International Road Dynamics" }, - { 0x0F46, "KIHOKU Electronic Co., Ltd." }, - { 0x0F47, "SN Systems Ltd." }, - { 0x0F48, "Durand Interstellar, Inc." }, - { 0x0F49, "Evolis" }, - { 0x0F4A, "Planmeca Oy" }, - { 0x0F4B, "St. John Technology Co., Ltd." }, - { 0x0F4C, "WORLDWIDE CABLE OPTO CORP." }, - { 0x0F4D, "Microtune, Inc." }, - { 0x0F4E, "Freedom Scientific" }, - { 0x0F4F, "INVENTEL" }, - { 0x0F50, "LeadingSpect Corporation" }, - { 0x0F51, "Zeta Broadband Inc." }, - { 0x0F52, "Wing Kei Electrical Production Ltd." }, - { 0x0F53, "Taiyo Cable (Dongguan) Co. Ltd." }, - { 0x0F54, "Kawai Musical Instruments Mfg. Co., Ltd." }, - { 0x0F55, "AmbiCom, Inc." }, - { 0x0F56, "SecureTech Corp." }, - { 0x0F57, "WavePlus Tech. Co., Ltd." }, - { 0x0F58, "JASCO Corporation" }, - { 0x0F59, "NCI/Newcomb Company, Inc." }, - { 0x0F5A, "Cogency Semiconductor Inc." }, - { 0x0F5B, "Ritech International Ltd." }, - { 0x0F5C, "PRAIRIECOMM, INC." }, - { 0x0F5D, "NewAge International, LLC" }, - { 0x0F5E, "LEADER ELECTRONICS CORP." }, - { 0x0F5F, "Key Technology Corporation" }, - { 0x0F60, "GuangZhou Chief Tech Electronic Technology Co. Ltd." }, - { 0x0F61, "Varian Inc." }, - { 0x0F62, "Acrox Technologies Co., Ltd." }, - { 0x0F63, "Leapfrog Enterprises" }, - { 0x0F64, "ZAE Research, Inc." }, - { 0x0F65, "Dataflex Design Communications Limited" }, - { 0x0F66, "Toshiba Global Commerce Solutions" }, - { 0x0F67, "Quantum3D, Inc." }, - { 0x0F68, "UQUEST, LTD." }, - { 0x0F69, "DIONEX CORPORATION" }, - { 0x0F6A, "Vibren Technologies Inc." }, - { 0x0F6B, "OHM ELECTRIC CO., LTD." }, - { 0x0F6C, "DnC Tech., Inc." }, - { 0x0F6D, "WillPoD Co., Ltd." }, - { 0x0F6E, "INTELLIGENT SYSTEMS CO., LTD." }, - { 0x0F6F, "Samtec GmbH" }, - { 0x0F70, "YOZAN Inc." }, - { 0x0F71, "Systems Integration Solutions Inc." }, - { 0x0F72, "Robert Bosch GmbH - Chassis Systems Control" }, - { 0x0F73, "DFI" }, - { 0x0F74, "KOSUGI GIKEN Co, Ltd." }, - { 0x0F75, "Future Internet" }, - { 0x0F76, "Vacon Plc" }, - { 0x0F77, "Fasstech" }, - { 0x0F78, "Guntermann & Drunck GmbH" }, - { 0x0F79, "Transonic Systems, Inc." }, - { 0x0F7A, "EE Tools, Inc." }, - { 0x0F7B, "Hivertec Inc." }, - { 0x0F7C, "DQ Technology, Inc." }, - { 0x0F7D, "NetBotz, Inc." }, - { 0x0F7E, "Fluke" }, - { 0x0F7F, "Lansmont Corporation" }, - { 0x0F80, "OCULUS Optikgeraete GmbH" }, - { 0x0F81, "DP Computers Pte. Ltd." }, - { 0x0F82, "IMedia Semiconductor Corporation" }, - { 0x0F83, "Ernst Reiner GmbH & Co. KG" }, - { 0x0F84, "A.E.B. S.R.L." }, - { 0x0F85, "IDX Company, Ltd." }, - { 0x0F86, "Cedar Audio Limited" }, - { 0x0F87, "HUMANDATA LTD." }, - { 0x0F88, "VTech Holdings Ltd." }, - { 0x0F89, "Leading Edge Co., Ltd." }, - { 0x0F8A, "Centro De Tecnologia de las Comunicaciones, S.A." }, - { 0x0F8B, "Yazaki Corporation" }, - { 0x0F8C, "Young Generation International Corp." }, - { 0x0F8D, "Uniwill Computer Corp." }, - { 0x0F8E, "Kingnet Technology Co., Ltd." }, - { 0x0F8F, "SOMA NETWORKS" }, - { 0x0F90, "Quad Engineering Solutions LLC" }, - { 0x0F91, "UNIPULSE Corporation" }, - { 0x0F92, "JASTEC CO., LTD." }, - { 0x0F93, "Sondex Limited" }, - { 0x0F94, "FALCOM GmbH" }, - { 0x0F95, "TOKYO SOKUSHIN CO., LTD." }, - { 0x0F96, "NEC-Mitsubishi Electric Visual Systems Corp." }, - { 0x0F97, "CviLux Corporation" }, - { 0x0F98, "CYBERBANK CORP." }, - { 0x0F99, "Biopia Co., Ltd." }, - { 0x0F9A, "Sistel S.R.L." }, - { 0x0F9B, "G-Card Technology Co., Ltd." }, - { 0x0F9C, "HYUN WON INC." }, - { 0x0F9D, "Opteon Corporation" }, - { 0x0F9E, "Lucent Technologies" }, - { 0x0F9F, "Racewood Technology Co., Ltd." }, - { 0x0FA0, "TRITTON TECHNOLOGIES" }, - { 0x0FA1, "AIJI System Co., Ltd." }, - { 0x0FA2, "TAG Systems Racing Products, Inc." }, - { 0x0FA3, "Chief Land Electronic Co., Ltd." }, - { 0x0FA4, "ATL Technology" }, - { 0x0FA5, "SOTEC CO., LTD." }, - { 0x0FA6, "CMD AG" }, - { 0x0FA7, "EPOX COMPUTER CO., LTD." }, - { 0x0FA8, "Logic Controls, Inc." }, - { 0x0FA9, "Shenzhen Motion Control Technology Co., Ltd." }, - { 0x0FAA, "Changrime Telecom Co., Ltd." }, - { 0x0FAB, "ISZ" }, - { 0x0FAC, "Current Stone Co., Ltd." }, - { 0x0FAD, "Ultravision Ltd." }, - { 0x0FAE, "Redsun Technology Corp." }, - { 0x0FAF, "Winpoint Electronic Corp." }, - { 0x0FB0, "Haurtian Wire & Cable Co., Ltd." }, - { 0x0FB1, "SuperGate Technologies" }, - { 0x0FB2, "Conteck Co., Ltd." }, - { 0x0FB3, "SYMAGERY MICROSYSTEMS INC." }, - { 0x0FB4, "Smiths Detection" }, - { 0x0FB5, "NIHON DENJI SOKKI CO., LTD." }, - { 0x0FB6, "Heber Ltd." }, - { 0x0FB7, "East Press Co., Ltd." }, - { 0x0FB8, "Wistron Corporation" }, - { 0x0FB9, "AACOM CORPORATION" }, - { 0x0FBA, "SAN SHING ELECTRONICS CO., LTD.." }, - { 0x0FBB, "Bitwise Systems, Inc." }, - { 0x0FBC, "Schick Technologies" }, - { 0x0FBD, "Siblings Investment Inc. (dba vantecusa)" }, - { 0x0FBE, "Applied Diabetes Research, Inc." }, - { 0x0FBF, "Certifiable Innovations" }, - { 0x0FC0, "NUDIAN ELECTRON CO., LTD." }, - { 0x0FC1, "MITAC INTERNATIONAL CORP." }, - { 0x0FC2, "PLUG AND JACK INDUSTRIAL INC." }, - { 0x0FC3, "BRAINTREE COMMUNICATIONS" }, - { 0x0FC4, "Yamato Electric Industry Co., Ltd." }, - { 0x0FC5, "Delcom Engineering" }, - { 0x0FC6, "Dataplus Supplies, Inc." }, - { 0x0FC7, "BES Technology Group" }, - { 0x0FC8, "Phoenix Co., Ltd." }, - { 0x0FC9, "Tecom Co., Ltd." }, - { 0x0FCA, "BlackBerry Limited" }, - { 0x0FCB, "Suzuken Co., Ltd." }, - { 0x0FCC, "Marushin-Denshi Co., Ltd." }, - { 0x0FCD, "Centurion, Inc." }, - { 0x0FCE, "Sony Mobile Communications" }, - { 0x0FCF, "Dynastream Innovations Inc." }, - { 0x0FD0, "2L international B.V." }, - { 0x0FD1, "Giant Electronics Ltd." }, - { 0x0FD2, "SEAC BANCHE S.P.A." }, - { 0x0FD3, "Marconi Applied Technologies Ltd." }, - { 0x0FD4, "Tenovis GmbH & Co., KG" }, - { 0x0FD5, "Direct Access Technology, Inc." }, - { 0x0FD6, "Mexmal Mayorista S.A. de C.V." }, - { 0x0FD7, "Jeulin S.A." }, - { 0x0FD8, "LARSEN & BRUSGAARD" }, - { 0x0FD9, "El Gato Software LLC" }, - { 0x0FDA, "Quantec Networks GmbH" }, - { 0x0FDB, "Comtech EF Data" }, - { 0x0FDC, "Micro Plus" }, - { 0x0FDD, "Yuyama Mfg. Co., Ltd." }, - { 0x0FDE, "IDT DATA SYSTEM LIMITED" }, - { 0x0FDF, "Foveon Inc." }, - { 0x0FE0, "AONEPROTECH Co., Ltd." }, - { 0x0FE1, "MADWAVES ApS" }, - { 0x0FE2, "Air Techniques, Inc." }, - { 0x0FE3, "ACCEL CORP." }, - { 0x0FE4, "IN-TECH ELECTRONICS LIMITED" }, - { 0x0FE5, "TC&C ELECTRONIC CO.,LTD (SUNTECC, INC.)" }, - { 0x0FE6, "Sospita ASA" }, - { 0x0FE7, "Mitutoyo Corporation" }, - { 0x0FE8, "TurboComm Tech. Inc." }, - { 0x0FE9, "DVICO Inc." }, - { 0x0FEA, "United Computer Accessories" }, - { 0x0FEB, "CRS ELECTRONIC CO., LTD." }, - { 0x0FEC, "UMC Electronics Co., Ltd." }, - { 0x0FED, "ACCESS CO., LTD." }, - { 0x0FEE, "Xsido Corporation" }, - { 0x0FEF, "MJ RESEARCH, INC." }, - { 0x0FF0, "Physical Electronics" }, - { 0x0FF1, "Minato Electronics, Inc." }, - { 0x0FF2, "EZMAX CO., LTD." }, - { 0x0FF3, "Dimentor" }, - { 0x0FF4, "POLYMATECH CO., LTD." }, - { 0x0FF5, "OYO-ELECTRIC CO., LTD." }, - { 0x0FF6, "Core Valley Co., Ltd." }, - { 0x0FF7, "CHI SHING COMPUTER ACCESSORIES CO., LTD." }, - { 0x0FF8, "iXs Research Corporation" }, - { 0x0FF9, "FHC., Inc. Frederick Haer & Co." }, - { 0x0FFA, "ELENTEC CO., LTD." }, - { 0x0FFB, "Avail Corporation" }, - { 0x0FFC, "Clavia Digital Musical Instruments AB" }, - { 0x0FFD, "AKATSUKI ELECTRIC MFG. CO., LTD." }, - { 0x0FFE, "ASKA Corporation" }, - { 0x0FFF, "Aopen Inc." }, - { 0x1000, "Speed Tech Corp." }, - { 0x1001, "Ritronics Components (S) Pte. Ltd." }, - { 0x1002, "Spa Design Ltd." }, - { 0x1003, "SIGMA CORPORATION" }, - { 0x1004, "LG Electronics Inc." }, - { 0x1005, "Apacer Technology Inc." }, - { 0x1006, "Reign Com Ltd." }, - { 0x1007, "Samphone Electronic Co., Ltd." }, - { 0x1008, "Futaba Corporation" }, - { 0x1009, "Lumanate, Inc." }, - { 0x100A, "AVC Technology" }, - { 0x100B, "Chou Chin Industrial Co., Ltd." }, - { 0x100C, "eMachines, inc" }, - { 0x100D, "NETOPIA, INC." }, - { 0x100E, "North American Pacific Industries, Corp." }, - { 0x100F, "Trek Inc." }, - { 0x1010, "FUKUDA DENSHI CO., LTD." }, - { 0x1011, "Mobile Media Tech." }, - { 0x1012, "SDKM Fibres, Wires & Cables Berhad" }, - { 0x1013, "TST-Touchless Sensor Technology AG" }, - { 0x1014, "Densitron Technologies PLC" }, - { 0x1015, "Softronics Pty. Ltd." }, - { 0x1016, "Xiamen Hung's Enterprise Co., Ltd." }, - { 0x1017, "SPEEDY INDUSTRIAL SUPPLIES PTE. LTD." }, - { 0x1018, "Mindtell Inc." }, - { 0x1019, "Fostex Corporation" }, - { 0x101A, "Annecy Electronique" }, - { 0x101B, "Digital Innovations" }, - { 0x101C, "Teradyne Diagnostic Solutions Ltd." }, - { 0x101D, "Aerospace Information Corporation Limited" }, - { 0x101E, "Fronius International GmbH" }, - { 0x101F, "Pocketec" }, - { 0x1020, "Paten Wireless Technology Inc." }, - { 0x1021, "Time Management, Inc." }, - { 0x1022, "Shinko Shoji Co., Ltd." }, - { 0x1023, "CHRONIX Inc." }, - { 0x1024, "ASEC CO., LTD." }, - { 0x1025, "Technology Testing Lab" }, - { 0x1026, "Newly Corporation" }, - { 0x1027, "Time Domain" }, - { 0x1028, "Inovys Corporation" }, - { 0x1029, "Atlantic Coast Telesys" }, - { 0x102A, "RAMOS Technology Co., Ltd." }, - { 0x102B, "Infotronic America, Inc." }, - { 0x102C, "Etoms Electronics Corp." }, - { 0x102D, "Winic Corporation" }, - { 0x102E, "Binstead Systems Ltd." }, - { 0x102F, "WENZHOU YIHUA CONNECTOR CO.,LTD." }, - { 0x1030, "Asoka USA Corporation" }, - { 0x1031, "Comax Technology Inc." }, - { 0x1032, "C-One Technology Corp." }, - { 0x1033, "Nucam Corporation" }, - { 0x1034, "Teramecs Co., Ltd." }, - { 0x1035, "Cyber Solid Laboratory" }, - { 0x1036, "ELLAB A/S" }, - { 0x1037, "Red Lion Controls LP" }, - { 0x1038, "SteelSeries ApS" }, - { 0x1039, "devolo AG" }, - { 0x103A, "I+ME ACTIA GmbH" }, - { 0x103B, "Quatographic AG" }, - { 0x103C, "AMX Corp." }, - { 0x103D, "Stanton Magnetics, Inc." }, - { 0x103E, "Thurlby-Thandar Instruments Ltd." }, - { 0x103F, "Tectech inc." }, - { 0x1040, "Valiant Technology Ltd." }, - { 0x1041, "Kongsberg Defence Communications AS" }, - { 0x1042, "CARDIO SISTEMAS COML. INDL. LTDA." }, - { 0x1043, "iCreate Technologies Corporation" }, - { 0x1044, "Chu Yuen Enterprise Co., Ltd." }, - { 0x1045, "Transiciel Technologies" }, - { 0x1046, "Hitachi Asahi Electronics Co., Ltd." }, - { 0x1047, "HOYA CORPORATION Vision Care Company" }, - { 0x1048, "Targus International LLC" }, - { 0x1049, "Studio Technologies, Inc." }, - { 0x104A, "WACOH Corporation" }, - { 0x104B, "CSM GmbH" }, - { 0x104C, "AMCO TEC International Inc." }, - { 0x104D, "Newport Corporation" }, - { 0x104E, "Halliburton Energy Services" }, - { 0x104F, "W B Electronics" }, - { 0x1050, "Yubico AB" }, - { 0x1051, "Nippon Printer Engineering Inc." }, - { 0x1052, "U-Medica Inc." }, - { 0x1053, "Immanuel Electronics Co., Ltd." }, - { 0x1054, "BMS International Beheer N.V." }, - { 0x1055, "Complex Micro Interconnection Co., Ltd." }, - { 0x1056, "Hsin Chen Ent Co., Ltd." }, - { 0x1057, "ON Semiconductor" }, - { 0x1058, "Western Digital, Branded" }, - { 0x1059, "Giesecke & Devrient GmbH" }, - { 0x105A, "DDS, Inc." }, - { 0x105B, "TOKIWA WEST Co., Ltd." }, - { 0x105C, "Freeway Electronic Wire & Cable (Dongguan) Co., Ltd." }, - { 0x105D, "Delkin Devices, Inc." }, - { 0x105E, "Valence Semiconductor Design Limited" }, - { 0x105F, "Chin Shong Enterprise Co., Ltd." }, - { 0x1060, "Easthome Industrial Co., Ltd." }, - { 0x1061, "Cardinal Components Inc." }, - { 0x1062, "Sumitomo Electric Industries, Ltd." }, - { 0x1063, "LPKF Laser & Electronics AG" }, - { 0x1064, "INNOPLUS Co., Ltd." }, - { 0x1065, "ImageQuest Co., Ltd." }, - { 0x1066, "Eten Information Systems Co., Ltd." }, - { 0x1067, "L-3 Communications" }, - { 0x1068, "Micropi Elettronica" }, - { 0x1069, "Easy Digital Concept" }, - { 0x106A, "Loyal Legend Limited" }, - { 0x106B, "MED Associates Inc. , sue@med-associates.com" }, - { 0x106C, "Curitel Communications, Inc." }, - { 0x106D, "San Chieh Manufacturing Ltd." }, - { 0x106E, "ConectL" }, - { 0x106F, "Money Controls" }, - { 0x1070, "TAKAMISAWA CYBERNETICS CO., LTD." }, - { 0x1071, "Paxton Access Ltd." }, - { 0x1072, "FDI Matelec" }, - { 0x1073, "Lifetron Co., Ltd." }, - { 0x1074, "TECHNO SOFT SYSTEMNICS INC." }, - { 0x1075, "TOKYO KEIKI INC." }, - { 0x1076, "GCT Semiconductor, Inc." }, - { 0x1077, "VoiceBox Technologies Inc." }, - { 0x1078, "Maycom Co., Ltd." }, - { 0x1079, "Suisei Electronics System Co., Ltd." }, - { 0x107A, "Optionexist Limited" }, - { 0x107B, "X E Systems Inc." }, - { 0x107C, "Whelen Engineering Company Inc." }, - { 0x107D, "Arlec Australia Limited" }, - { 0x107E, "MIDORIYA ELECTRIC CO., LTD." }, - { 0x107F, "KidzMouse, Inc." }, - { 0x1080, "Musetel Co., Ltd." }, - { 0x1081, "VG Electracon, Inc." }, - { 0x1082, "Shin-Etsukaken Co., Ltd." }, - { 0x1083, "CANON ELECTRONICS INC." }, - { 0x1084, "PANTECH CO., LTD." }, - { 0x1085, "Datalaster" }, - { 0x1086, "Smart System Inc." }, - { 0x1087, "Shanghai Ewaytek Co., Ltd." }, - { 0x1088, "Archtek Telecom Co." }, - { 0x1089, "On Track Innovations Ltd." }, - { 0x108A, "Chloride Power Protection" }, - { 0x108B, "Grand-tek Technology Co., Ltd." }, - { 0x108C, "Robert Bosch GmbH" }, - { 0x108D, "Mitsui Zosen Systems Research Inc." }, - { 0x108E, "Lotes Co., Ltd." }, - { 0x108F, "HIOKI E.E. CORPORATION" }, - { 0x1090, "DSP Research Inc." }, - { 0x1091, "DR. JOHANNES HEIDENHAIN GmbH" }, - { 0x1092, "TOPDEK Semiconductor Inc." }, - { 0x1093, "SongPro, Inc." }, - { 0x1094, "NextEngine, Inc." }, - { 0x1095, "Good Work Systems" }, - { 0x1096, "NIO Corporation" }, - { 0x1097, "Computational Systems Incorporated" }, - { 0x1098, "Raytek Corp." }, - { 0x1099, "Surface Optics Corporation" }, - { 0x109A, "DATASOFT Systems GmbH" }, - { 0x109B, "Qingdao Hisense Communication Co., Ltd." }, - { 0x109C, "Electronic Trade Solutions Ltd." }, - { 0x109D, "NAVIUS CO., LTD." }, - { 0x109E, "Finger System Inc." }, - { 0x109F, "eSOL Co., Ltd." }, - { 0x10A0, "HIROTECH, INC." }, - { 0x10A1, "target-systemelectronic gmbh" }, - { 0x10A2, "HYUNDAI NETWORKS, INC." }, - { 0x10A3, "MITSUBISHI MATERIALS CORPORATION" }, - { 0x10A4, "Frontier Silicon Ltd." }, - { 0x10A5, "FINGERPRINT CARDS AB" }, - { 0x10A6, "SKYUP TECHNOLOGY CORPORATION" }, - { 0x10A7, "3i techs Development Corp" }, - { 0x10A8, "Imaging Devices, Inc." }, - { 0x10A9, "SK Teletech Co., Ltd." }, - { 0x10AA, "Cables To Go" }, - { 0x10AB, "Universal Global Scientific Industrial Co., Ltd." }, - { 0x10AC, "Honeywell, Inc." }, - { 0x10AD, "Impact Instrumentation Inc." }, - { 0x10AE, "Princeton Technology Corp." }, - { 0x10AF, "Liebert Corporation" }, - { 0x10B0, "IPmental Inc." }, - { 0x10B1, "Safe Valley Inc." }, - { 0x10B2, "Data East Corporation" }, - { 0x10B3, "Roke Manor Research Limited" }, - { 0x10B4, "Guardtec, Inc." }, - { 0x10B5, "Comodo" }, - { 0x10B6, "Dynojet Research, Inc." }, - { 0x10B7, "VSM Medtech Ltd." }, - { 0x10B8, "DIBCOM" }, - { 0x10B9, "Prime Electronics & Satellitics, Inc." }, - { 0x10BA, "Dong-Guan Sintai Optical Co., Ltd." }, - { 0x10BB, "TM Technology Inc." }, - { 0x10BC, "Dinging Technology Co., Ltd." }, - { 0x10BD, "TMT TECHNOLOGY, INC." }, - { 0x10BE, "KBM Electronic System Design" }, - { 0x10BF, "Smarthome" }, - { 0x10C0, "SougaSoft Co., Ltd." }, - { 0x10C1, "Kyokuto Electric Co., Ltd." }, - { 0x10C2, "Phasespace, Inc." }, - { 0x10C3, "Universal Laser Systems" }, - { 0x10C4, "Silicon Laboratories, Inc." }, - { 0x10C5, "Sanei Electric Inc." }, - { 0x10C6, "Intec, Inc." }, - { 0x10C7, "Touchstone Technology Co., Ltd." }, - { 0x10C8, "SIGMACOM CO., LTD." }, - { 0x10C9, "ZUKEN Inc." }, - { 0x10CA, "Xrosstech, Inc." }, - { 0x10CB, "eratech" }, - { 0x10CC, "GBM Connector Co., Ltd." }, - { 0x10CD, "Kycon Inc." }, - { 0x10CE, "Shinko Electric Co., Ltd." }, - { 0x10CF, "Velleman Components" }, - { 0x10D0, "Tokai University Educational System" }, - { 0x10D1, "HBM GmbH" }, - { 0x10D2, "Adams IT Services" }, - { 0x10D3, "Trimos SA" }, - { 0x10D4, "Man Boon Manufactory Ltd." }, - { 0x10D5, "Uni Class Technology Co., Ltd." }, - { 0x10D6, "Actions Semiconductor Co., Ltd." }, - { 0x10D7, "Array Corporation" }, - { 0x10D8, "ACTIKEY S.A." }, - { 0x10D9, "Tecnova Corporation" }, - { 0x10DA, "HOWTEL CO., LTD." }, - { 0x10DB, "Prior Scientific Instruments Ltd." }, - { 0x10DC, "Evolve Communications" }, - { 0x10DD, "VerNova, Inc." }, - { 0x10DE, "Authenex, Inc." }, - { 0x10DF, "In-Win Development Inc." }, - { 0x10E0, "Bella Corporation" }, - { 0x10E1, "CABLEPLUS LTD." }, - { 0x10E2, "Nada Electronics, Ltd." }, - { 0x10E3, "tec5 AG" }, - { 0x10E4, "Trans-Lux Corporation & Subsidiaries" }, - { 0x10E5, "MACTek" }, - { 0x10E6, "Altotec Hard- und Software GmbH" }, - { 0x10E7, "dSPACE GmbH" }, - { 0x10E8, "Kumahira Co., Ltd." }, - { 0x10E9, "XIA LLC" }, - { 0x10EA, "ELITRONIC s.r.o." }, - { 0x10EB, "FREEBOX SA" }, - { 0x10EC, "Vast Technologies Inc." }, - { 0x10ED, "KDS USA, Inc." }, - { 0x10EE, "Compuprint" }, - { 0x10EF, "Integrity Instruments Inc." }, - { 0x10F0, "Etronics Corp." }, - { 0x10F1, "Inventec Multimedia & Telecom Corp." }, - { 0x10F2, "Autonics Co., Ltd." }, - { 0x10F3, "Vercel Development Inc." }, - { 0x10F4, "INcoder Technology CO., Ltd." }, - { 0x10F5, "Voyetra Turtle Beach, Inc." }, - { 0x10F6, "IMAGENICS Co., Ltd." }, - { 0x10F7, "Hando Computer Co., Ltd" }, - { 0x10F8, "CESYS GmbH" }, - { 0x10F9, "NSD Corporation" }, - { 0x10FA, "CHINO Corporation" }, - { 0x10FB, "Pictos Technologies, Inc." }, - { 0x10FC, "MICRELEC" }, - { 0x10FD, "Animation Technologies Inc." }, - { 0x10FE, "Thrane & Thrane A/S" }, - { 0x10FF, "Bellwave" }, - { 0x1100, "VirTouch Ltd." }, - { 0x1101, "EASYPASS INDUSTRIAL CO., LTD." }, - { 0x1102, "Instrument Systems GmbH" }, - { 0x1103, "Brain Products GmbH" }, - { 0x1104, "TOA Corporation" }, - { 0x1105, "MAP Medizin-Technologie GmbH" }, - { 0x1106, "OrangeHouse Co., Ltd." }, - { 0x1107, "CreamWare GmbH" }, - { 0x1108, "BRIGHTCOM TECHNOLOGIES LTD." }, - { 0x1109, "LG Industrial Systems Co., Ltd." }, - { 0x110A, "Moxa Inc." }, - { 0x110B, "NAKI INTERNATIONAL" }, - { 0x110C, "Computer Network Technology" }, - { 0x110D, "Hitachi Car Engineering Co., Ltd." }, - { 0x110E, "Innotrac Diagnostics OY" }, - { 0x110F, "OneVision Corporation" }, - { 0x1110, "Analog Devices Canada Ltd." }, - { 0x1111, "Siemens Healthcare Diagnostics Inc." }, - { 0x1112, "Golden Bright (Sichuan) Electronic Technology Co Ltd" }, - { 0x1113, "Medion AG" }, - { 0x1114, "Psion Teklogix Inc." }, - { 0x1115, "Data Link Co., Ltd." }, - { 0x1116, "Compro Technology Inc." }, - { 0x1117, "11 WAVE TECHNOLOGY, INC." }, - { 0x1118, "MotoSAT" }, - { 0x1119, "GCS General Control Systems GmbH" }, - { 0x111A, "The Nippon Signal Co., Ltd." }, - { 0x111B, "Kyusyu Ten Ltd." }, - { 0x111C, "point electronic GmbH" }, - { 0x111D, "Centon Electronics" }, - { 0x111E, "VSO ELECTRONICS CO., LTD." }, - { 0x111F, "BANCOR S.R.L." }, - { 0x1120, "Voipac, s.r.o." }, - { 0x1121, "Kore Technology Limited" }, - { 0x1122, "Klein & Melgert Developments B.V." }, - { 0x1123, "Hi-Tech Instruments, Inc." }, - { 0x1124, "REnex Technology Limited" }, - { 0x1125, "Industrial Computing Ltd." }, - { 0x1126, "Protonic - Holland" }, - { 0x1127, "BANK25 Co., Ltd." }, - { 0x1128, "STEAG ETA-Optik GmbH" }, - { 0x1129, "Jung Myung Telecom Co., Ltd." }, - { 0x112A, "RedRat Ltd." }, - { 0x112B, "Stenograph L.L.C." }, - { 0x112C, "Ethics Organization of Computer Software" }, - { 0x112D, "SYSMEX CORPORATION" }, - { 0x112E, "Master Hill Electric Wire and Cable Co., Ltd." }, - { 0x112F, "Cellon International" }, - { 0x1130, "Tenx Technology, Inc." }, - { 0x1131, "Integrated System Solution Corp." }, - { 0x1132, "Visoduck discount GmbH" }, - { 0x1133, "Sanei Electric Co., Ltd." }, - { 0x1134, "Tri-L Data Systems, Inc." }, - { 0x1135, "imo-elektronik GmbH" }, - { 0x1136, "CTS ELECTRONICS" }, - { 0x1137, "Beyond LSI, Inc." }, - { 0x1138, "Greenwood Engineering A/S" }, - { 0x1139, "Wavetrend" }, - { 0x113B, "Hana Micron, Inc." }, - { 0x113C, "Arintech Co., Ltd." }, - { 0x113D, "Mapower Electronics Co. Ltd." }, - { 0x113E, "KDK Electric Wire (H.K.) Co., Ltd." }, - { 0x113F, "Integrated Biometrics" }, - { 0x1140, "Ultra-Scan Corporation" }, - { 0x1141, "V ONE MULTIMEDIA PTE LTD" }, - { 0x1142, "CYBERSCAN TECH. INC." }, - { 0x1143, "Wako Pure Chemical Industries, Ltd.." }, - { 0x1144, "MURATA MACHINERY, LTD." }, - { 0x1145, "Japan Radio Co., Ltd." }, - { 0x1146, "Shimane SANYO Electric Co., Ltd." }, - { 0x1147, "Ever Great Electric Wire and Cable Co., Ltd." }, - { 0x1148, "KGS Corporation" }, - { 0x1149, "TAMA TECH LAB CORP." }, - { 0x114A, "TANITA Corporation (1)" }, - { 0x114B, "Sphairon Technologies GmbH" }, - { 0x114C, "Tinius Olsen Testing Machine Co., Inc." }, - { 0x114D, "Alpha Imaging Technology Corp." }, - { 0x114E, "Digital Electronics Corporation" }, - { 0x114F, "WAVECOM" }, - { 0x1150, "Don Alan Pty. Ltd." }, - { 0x1151, "World Wide Licenses Limited" }, - { 0x1152, "Codonics, Inc." }, - { 0x1153, "Tritec Co., Ltd." }, - { 0x1154, "BEB Industrie-Elektronik AG" }, - { 0x1155, "DICESVA S.L." }, - { 0x1156, "Cybertech bv" }, - { 0x1157, "EKS Oy" }, - { 0x1158, "Syn-Tech Systems Inc." }, - { 0x1159, "Micro Application Laboratory Corp." }, - { 0x115A, "Extreme Speed" }, - { 0x115B, "Salix Technology Co., Ltd." }, - { 0x115C, "CORESMA" }, - { 0x115D, "ADTEK SYSTEM SCIENCE CO., LTD." }, - { 0x115E, "Group Sense Ltd." }, - { 0x115F, "Dataring Systems" }, - { 0x1160, "Invocon, Inc." }, - { 0x1161, "Port Denshi Co., Ltd." }, - { 0x1162, "Secugen Corporation" }, - { 0x1163, "DeLorme Publishing Inc." }, - { 0x1164, "YUAN High-Tech Development Co., Ltd." }, - { 0x1165, "Telson Electronics Co., Ltd." }, - { 0x1166, "Bantam Interactive Technologies" }, - { 0x1167, "Salient Systems Corporation" }, - { 0x1168, "BizConn International Corp." }, - { 0x1169, "Adirondack Optics" }, - { 0x116A, "JJL Technologies, LLC" }, - { 0x116B, "Pigeon Point Systems" }, - { 0x116C, "SecureEye, Inc." }, - { 0x116D, "Filmetrics, Inc." }, - { 0x116E, "Gigastorage Corp." }, - { 0x116F, "Silicon 10 Technology Corp." }, - { 0x1170, "Tadiran Com. Ltd." }, - { 0x1171, "CRE Technology Co., Ltd." }, - { 0x1172, "Telegate Co., Ltd." }, - { 0x1173, "Esko-Graphics" }, - { 0x1174, "Techno-One Co., Ltd." }, - { 0x1175, "Sheng Yih Technologies Co., Ltd." }, - { 0x1176, "Japan Touchscreen Distributions, Inc." }, - { 0x1177, "Hitachi Communication Technologies, Ltd." }, - { 0x1178, "Kamaya Electric Co., Ltd." }, - { 0x1179, "Bio-logic Systems Corp." }, - { 0x117A, "Ishikawa Seisakusho, Ltd." }, - { 0x117B, "Primetech Engineering Corporation" }, - { 0x117C, "SOFTIDEA s.r.o." }, - { 0x117D, "Santa Electronic Inc." }, - { 0x117E, "JNC, Inc." }, - { 0x117F, "Princeton Technology, Ltd." }, - { 0x1180, "Spectra-Physics" }, - { 0x1181, "USB NET" }, - { 0x1182, "Venture Corporation Limited" }, - { 0x1183, "Digital Dream Co. Europe Ltd." }, - { 0x1184, "Kyocera Elco Corporation" }, - { 0x1185, "Projectiondesign AS" }, - { 0x1186, "Scientec System" }, - { 0x1187, "Techno Valley Co., Ltd." }, - { 0x1188, "Bloomberg L.P." }, - { 0x1189, "Trisat IndTry Computer Co. LTD." }, - { 0x118A, "KEBA AG" }, - { 0x118B, "AXIOMTEK Co., Ltd." }, - { 0x118C, "INFINIT GmbH" }, - { 0x118D, "Gould Instrument Systems" }, - { 0x118E, "Hermstedt AG" }, - { 0x118F, "You Yang Technology Co., Ltd." }, - { 0x1190, "Tripace" }, - { 0x1191, "Loyalty Founder Enterprise Co., Ltd." }, - { 0x1192, "Matsusada Precision Inc." }, - { 0x1193, "H2I TECHNOLOGIES" }, - { 0x1194, "GLORY AZ System Co., Ltd." }, - { 0x1195, "ELECTROLINE" }, - { 0x1196, "Yankee Robotics, LLC" }, - { 0x1197, "Technoimagia Co., Ltd." }, - { 0x1198, "StarShine Technology Corp." }, - { 0x1199, "Sierra Wireless Inc." }, - { 0x119A, "DONG GUAN JALINK ELECTRONICES CO.,LTD" }, - { 0x119B, "ruwido austria GmbH" }, - { 0x119C, "SK MEDICAL ELECTRONICS CO.,LTD" }, - { 0x119D, "Saka-Techno Science Co., Ltd." }, - { 0x119E, "Engineered Audio, LLC." }, - { 0x119F, "TECNOS CO., LTD." }, - { 0x11A0, "Chipcon" }, - { 0x11A1, "Mikrap AG" }, - { 0x11A2, "SitecSoft Co., Ltd." }, - { 0x11A3, "Technovas Co., Ltd." }, - { 0x11A4, "THE FURUKAWA ELECTRIC CO., LTD." }, - { 0x11A5, "TOKYO RIKAKIKAI CO., LTD." }, - { 0x11A6, "VRmagic GmbH" }, - { 0x11A7, "SNAPSHIELD LTD." }, - { 0x11A8, "Hoeft & Wessel AG" }, - { 0x11A9, "Parker Hannifin" }, - { 0x11AA, "GlobalMedia Group, LLC" }, - { 0x11AB, "Exito Electronics Co., Ltd." }, - { 0x11AC, "Nike, Inc." }, - { 0x11AD, "SANWA ELECTRIC INSTRUMENT CO., LTD." }, - { 0x11AE, "Stoelting Co." }, - { 0x11AF, "Valence Semiconductor" }, - { 0x11B0, "ATECH FLASH TECHNOLOGY" }, - { 0x11B1, "New Motion Tec. Corp." }, - { 0x11B2, "Bizerba GmbH & Co. KG" }, - { 0x11B3, "MONYA Corporation" }, - { 0x11B4, "SPIELO" }, - { 0x11B5, "ADVANTECH EQUIPMENT CORP." }, - { 0x11B6, "Diskware Co., Ltd." }, - { 0x11B7, "Embla" }, - { 0x11B8, "CROSS S&T Inc." }, - { 0x11B9, "IST Electronics, Inc." }, - { 0x11BA, "Sasem Co., Ltd." }, - { 0x11BB, "YaMu Solutions" }, - { 0x11BC, "Taipei EELY-ECW Co., Ltd." }, - { 0x11BD, "UBINETICS LIMITED" }, - { 0x11BE, "Martin Professional A/S" }, - { 0x11BF, "SonoSite, Inc." }, - { 0x11C0, "Sanmos Microelectronics Corp." }, - { 0x11C1, "Wako Giken Kogyo Co., Ltd." }, - { 0x11C2, "EYESPYFX" }, - { 0x11C3, "Kaizen Frogpad, LLC" }, - { 0x11C4, "DALLANTBANK, INC." }, - { 0x11C5, "INMAX TECHNOLOGY CORP." }, - { 0x11C6, "Guzik Technical Enterprises" }, - { 0x11C7, "Reliance Electric Limited" }, - { 0x11C8, "Fullcom Technology Corp." }, - { 0x11C9, "Monster Cable Products, Inc." }, - { 0x11CA, "VeriFone" }, - { 0x11CB, "Magni Systems, Inc." }, - { 0x11CC, "AIM SRL" }, - { 0x11CD, "KTEK Co., Ltd." }, - { 0x11CE, "Argolis BV" }, - { 0x11CF, "Nemoto Kyorindo Co., Ltd." }, - { 0x11D0, "TOPCON CORPORATION, Opthalmic & Medical Instrument Dept" }, - { 0x11D1, "Far Touch Inc." }, - { 0x11D2, "BW Technologies Ltd." }, - { 0x11D3, "Elias Technology, Inc." }, - { 0x11D4, "Unitac Co., Ltd." }, - { 0x11D5, "Polyvision Corporation" }, - { 0x11D6, "FUJIFILM AXIA CO., LTD." }, - { 0x11D7, "Kokusai Electric Alpha Co., Ltd." }, - { 0x11D8, "Zybertek" }, - { 0x11D9, "Itronix Corporation" }, - { 0x11DA, "Tekscan, Inc." }, - { 0x11DB, "Topfield Co., Ltd." }, - { 0x11DC, "STELECTRIC A/S" }, - { 0x11DD, "DRAGONCHIP LTD." }, - { 0x11DE, "La Generale Multimedia" }, - { 0x11DF, "ROI Computer AG" }, - { 0x11E0, "SUNX Limited" }, - { 0x11E1, "Encentuate Pte. Ltd." }, - { 0x11E2, "SPECSOFT CONSULTING INC" }, - { 0x11E3, "GfS-Hofheim" }, - { 0x11E4, "STANDARD ELECTRONICS TELECOM INC." }, - { 0x11E5, "CHUFON Technology Co., Ltd." }, - { 0x11E6, "K.I. Technology Co. Ltd." }, - { 0x11E7, "Rockford Corporation" }, - { 0x11E8, "NAAT Technology Corp." }, - { 0x11E9, "Wincan Technology Co., Ltd." }, - { 0x11EA, "Panram International Corp." }, - { 0x11EB, "VTech Innovation L.P. dba Advanced American Telephones" }, - { 0x11EC, "Hitachi Computer Peripherals Co., Ltd." }, - { 0x11ED, "Shimizu Technology Inc." }, - { 0x11EE, "ASAHI ELECTRIC CO., LTD." }, - { 0x11EF, "Cableplus Industrial Co., Ltd." }, - { 0x11F0, "Matthew Ward Solutions" }, - { 0x11F1, "Cal-Comp Electronics (Thailand) Public Co., Ltd." }, - { 0x11F2, "Chain Tay Technology Co., Ltd." }, - { 0x11F3, "ROUND Co., Ltd." }, - { 0x11F4, "Kyoritsu Electric Corporation" }, - { 0x11F5, "Siemens Mobile Phones" }, - { 0x11F6, "NetIndex Inc." }, - { 0x11F7, "ALCATEL BUSINESS SYSTEMS" }, - { 0x11F8, "BodyMedia, Inc." }, - { 0x11F9, "Cryptocard Corporation" }, - { 0x11FA, "Code Corporation" }, - { 0x11FB, "HORIBA, Ltd." }, - { 0x11FC, "ANCOT CORPORATION" }, - { 0x11FD, "EKE-Electronics Ltd." }, - { 0x11FE, "SHENZHEN CHANGXUNXING ELECTRONIC CO., LTD." }, - { 0x11FF, "LITE STAR ELECTRONICS TECHNOLOGIES, CO. LTD." }, - { 0x1200, "Spellman High Voltage Electronics Corp." }, - { 0x1201, "Practical Automation, Inc." }, - { 0x1202, "KUK JE TONG SHIN CO., LTD." }, - { 0x1203, "Taiwan Semiconductor Co., Ltd." }, - { 0x1204, "SATEC" }, - { 0x1205, "NV ADB TTV TECHNOLOGIES SA" }, - { 0x1206, "Synnix Technology Co." }, - { 0x1207, "Cardinal Health UK 232 Ltd." }, - { 0x1208, "Seiko Epson Corp.- System Device" }, - { 0x120A, "Wintest Corp." }, - { 0x120B, "Dension Audio Systems Ltd." }, - { 0x120C, "ALF, Inc." }, - { 0x120D, "(AVL) DiTEST Fahrzeugdiagnose GmbH" }, - { 0x120E, "HUDSON SOFT CO., LTD." }, - { 0x120F, "Magellan Navigation, Inc." }, - { 0x1210, "Harman" }, - { 0x1211, "COSMED S.r.l." }, - { 0x1212, "D'Crypt Pte Ltd." }, - { 0x1213, "Fukko System Co., Ltd." }, - { 0x1214, "Dr. Bott KG" }, - { 0x1215, "Towa Engineering Corporation" }, - { 0x1216, "ProMinent Dosiertechnik GmbH" }, - { 0x1217, "Goyatek Technology Inc." }, - { 0x1218, "Geutebrueck GmbH" }, - { 0x1219, "COMPAL COMMUNICATIONS, INC." }, - { 0x121A, "TimeKeeping Systems, Inc." }, - { 0x121B, "FEC Inc." }, - { 0x121C, "Raysis Co., Ltd." }, - { 0x121D, "Intelligent Computer Solutions" }, - { 0x121E, "Jungsoft Co., Ltd." }, - { 0x121F, "Panini S.P.A." }, - { 0x1220, "TC Group A/S" }, - { 0x1221, "Averatec, Inc." }, - { 0x1222, "Tipro Keyboards D.O.O." }, - { 0x1223, "SKYCABLE ENTERPRISE CO., LTD." }, - { 0x1224, "SCATT, ZAO" }, - { 0x1225, "HI-P Tech Corporation" }, - { 0x1226, "Keihin Corporation" }, - { 0x1227, "T-RAC INTERNATIONAL, INC." }, - { 0x1228, "DATAPAQ" }, - { 0x1229, "EPO Science & Technology Inc." }, - { 0x122A, "WABCO GmbH & Co., OHG" }, - { 0x122B, "Midas Lab Inc." }, - { 0x122C, "Qbtech AB" }, - { 0x122D, "Hitachi Information & Control Solutions, Ltd." }, - { 0x122E, "IOLINE" }, - { 0x122F, "Takimaging" }, - { 0x1230, "MIPSABG Chipidea, Lda." }, - { 0x1231, "CHI MEI COMMUNICATION SYSTEMS, INC." }, - { 0x1232, "SolitonWave Co., Ltd." }, - { 0x1233, "Targa Systems Div. L-3 Communications" }, - { 0x1234, "Micro Science Co., Ltd." }, - { 0x1235, "Focusrite Audio Engineering Ltd" }, - { 0x1236, "Nozaki Insatsu Shigyo Co., Ltd." }, - { 0x1237, "Technowave Ltd." }, - { 0x1238, "Bridgekey Corp." }, - { 0x1239, "Antex Electronics" }, - { 0x123A, "Spectra Technologies Holdings Co., Ltd." }, - { 0x123B, "De La Rue Systems Automatizacao" }, - { 0x123C, "K-Won C & C Co., Ltd." }, - { 0x123D, "Microplex Printware AG" }, - { 0x123E, "A.T. WORKS, Inc." }, - { 0x123F, "DURAPOWER TECHNOLOGY LTD." }, - { 0x1240, "HUMUS MOG CO., LTD." }, - { 0x1241, "OTSUKA ELECTRONICS CO., LTD." }, - { 0x1242, "MAC SYSTEM CO., LTD." }, - { 0x1243, "Fujikura Ltd., Fiber Optic System Division" }, - { 0x1244, "DResearch Digital Media Systems GmbH" }, - { 0x1245, "R/D Tech Inc." }, - { 0x1246, "CTO S.p.A." }, - { 0x1247, "JAPAN PRECISION INSTRUMENTS, INC." }, - { 0x1248, "Vector Informatik GmbH" }, - { 0x1249, "TRACESPAN Communications Ltd." }, - { 0x124A, "AirVast Technology Inc." }, - { 0x124B, "NYKO Technologies, Inc." }, - { 0x124C, "MEMORY EXPERTS International Inc." }, - { 0x124D, "Just Rams PLC" }, - { 0x124E, "YEM Inc." }, - { 0x124F, "Beijing JingHuiJiaDe Tech. Co., Ltd." }, - { 0x1250, "TECMAG" }, - { 0x1251, "Iwaya Corporation" }, - { 0x1252, "Nextway Co., Ltd." }, - { 0x1253, "Erebus Limited" }, - { 0x1254, "Empirical Systems" }, - { 0x1255, "ASCII Solutions, Inc." }, - { 0x1256, "Spectronic Denmark A/S" }, - { 0x1257, "AudioScience" }, - { 0x1258, "Continental Automotive Trading UK Ltd." }, - { 0x1259, "Deutsche Montan Technologie GmbH" }, - { 0x125A, "Shintake Sangyo Co., Ltd." }, - { 0x125B, "VIDEX" }, - { 0x125C, "Apogee Instruments, Inc." }, - { 0x125D, "Advanced Technology (UK) PLC" }, - { 0x125E, "Bosch Automotive Service Solutions" }, - { 0x125F, "ADATA Technology Co., Ltd." }, - { 0x1260, "Cores Inc." }, - { 0x1261, "All Ring Tech Co., Ltd." }, - { 0x1262, "MICRO VISION CO., LTD." }, - { 0x1263, "Opti Japan Corporation" }, - { 0x1264, "Covidien Energy-based Devices" }, - { 0x1265, "Good Mind Industries Co., Ltd." }, - { 0x1266, "Pirelli Cavi e Sistemi Telecom S.p.A." }, - { 0x1267, "SILCOR" }, - { 0x1268, "icube Corp." }, - { 0x1269, "Sequoia Voting Systems Inc." }, - { 0x126A, "CHH Electronics Ltd." }, - { 0x126B, "Veridian Systems" }, - { 0x126C, "Aristocrat Technologies" }, - { 0x126D, "Bel Stewart" }, - { 0x126E, "Strobe Data, Inc." }, - { 0x126F, "TwinMOS Technologies ME FZE" }, - { 0x1270, "Procomp Informatics Ltd." }, - { 0x1271, "Foxda Technology Industrial (Shenzhen) Co., Ltd." }, - { 0x1272, "Linear Technology Corporation" }, - { 0x1273, "HANEX Co., Ltd." }, - { 0x1274, "Matin, Inc." }, - { 0x1275, "Xaxero Marine Software Engineering Ltd." }, - { 0x1276, "QVS" }, - { 0x1277, "Silicon Media Inc." }, - { 0x1278, "Starlight Xpress Ltd." }, - { 0x1279, "Cheesecote Mountain Camac" }, - { 0x127A, "Electrophysics Corp." }, - { 0x127B, "The Technology Partnership (TTP)" }, - { 0x127C, "Comarco Wireless" }, - { 0x127D, "RAiO Technology Inc." }, - { 0x127E, "Hugelent Telecommunication (SuZhou) Co., Ltd." }, - { 0x127F, "IPACS Hans-Borchers-Gruentjens GbR (IPACS)" }, - { 0x1280, "Animeta Systems Inc." }, - { 0x1281, "Gean Sen Electronic Co., Ltd." }, - { 0x1282, "Falco Electronics Mexico" }, - { 0x1283, "zebris Medizintechnik GmbH" }, - { 0x1284, "YEC Co., Ltd." }, - { 0x1285, "Schindler Aufzuge AG" }, - { 0x1286, "MARVELL SEMICONDUCTOR, INC." }, - { 0x1287, "Infomove Co., Ltd." }, - { 0x1288, "Micro Advantage Inc." }, - { 0x1289, "Nippon Telesoft Co., Ltd." }, - { 0x128A, "Asia Vital Components Co., Ltd." }, - { 0x128B, "Medicapture, Inc." }, - { 0x128C, "ITW Food Equipment Group, LLC dba Hobart Corporation" }, - { 0x128D, "Testo AG" }, - { 0x128E, "Stormblue Co., Ltd." }, - { 0x128F, "Guidant Corporation" }, - { 0x1290, "Musicus GmbH" }, - { 0x1291, "Flarion Technologies" }, - { 0x1292, "Fire International Ltd." }, - { 0x1293, "Mitsubishi Electric Engineering Co., Ltd." }, - { 0x1294, "RISO KAGAKU CORP." }, - { 0x1295, "A & G Souzioni Digitali" }, - { 0x1296, "RadioScape" }, - { 0x1297, "DEKTEC Digital Video B.V." }, - { 0x1298, "Genlyte Controls" }, - { 0x1299, "DGStation Co., Ltd." }, - { 0x129A, "PULSTEC INDUSTRIAL CO., LTD." }, - { 0x129B, "CyberTAN Technology Inc." }, - { 0x129C, "Min Aik Technology Co., Ltd." }, - { 0x129D, "Yueqing Longhua Electronics Factory" }, - { 0x129E, "Aceeca Limited" }, - { 0x129F, "Howtek Devices Corp." }, - { 0x12A0, "CDC Point S.p.A." }, - { 0x12A1, "Tohken Co., Ltd." }, - { 0x12A2, "E28 (Shanghai) Ltd." }, - { 0x12A3, "KENT WORLD CO., LTD." }, - { 0x12A4, "Guangdong Matsunichi Communications Technology Co., Ltd" }, - { 0x12A5, "Sola/Hevi-Duty" }, - { 0x12A6, "ULVAC-PHI, Inc." }, - { 0x12A7, "Trendchip Technologies Corp." }, - { 0x12A8, "Clovertech Inc." }, - { 0x12A9, "Sunwave Technology Corp." }, - { 0x12AA, "Bustec Production Ltd." }, - { 0x12AB, "Honey Bee (Hong Kong) Limited" }, - { 0x12AC, "Compact Light System Norway A/S" }, - { 0x12AD, "Asahi Seiko Co., Ltd." }, - { 0x12AE, "Matsunichi Communication Holdings Limited" }, - { 0x12AF, "Baldor UK Ltd." }, - { 0x12B0, "Axciton Systems, Inc." }, - { 0x12B1, "HIMECS CO., LTD." }, - { 0x12B2, "DICKSON Company" }, - { 0x12B3, "Megaforce Company Ltd." }, - { 0x12B4, "Hanchang System Corporation" }, - { 0x12B5, "World Touch Gaming , Inc." }, - { 0x12B6, "Naito Densei Machida Mfg. Co., Ltd." }, - { 0x12B7, "Genesis Microchip Inc." }, - { 0x12B8, "Zhejiang Xinya Electronic Technology Co., Ltd." }, - { 0x12B9, "Freehand Systems, Inc." }, - { 0x12BA, "Sony Computer Entertainment America" }, - { 0x12BB, "Paltronics, Inc." }, - { 0x12BC, "Hakusan Corporation" }, - { 0x12BD, "Sun Light Application Co., Ltd." }, - { 0x12BE, "Dynex Technologies" }, - { 0x12BF, "Matrix Multimedia Ltd." }, - { 0x12C0, "Sencore, Inc." }, - { 0x12C1, "ARTRAY CO., LTD." }, - { 0x12C2, "HHB Communications Ltd." }, - { 0x12C3, "Fiso Technologies, Inc." }, - { 0x12C4, "Autocue Ltd." }, - { 0x12C5, "XN Technologies, Inc." }, - { 0x12C6, "Bosch Security Systems" }, - { 0x12C7, "Hismartech Co., Ltd." }, - { 0x12C8, "XiMeta Inc." }, - { 0x12C9, "Newmen Technology Corp. Ltd." }, - { 0x12CA, "Cables To Go International Manufacturing Co., Ltd." }, - { 0x12CB, "Dallmeier electronic GmbH" }, - { 0x12CC, "Printherm" }, - { 0x12CD, "Cables Unlimited" }, - { 0x12CE, "Hakko Electronics Co., Ltd." }, - { 0x12CF, "Dexin Corporation" }, - { 0x12D0, "ITG Research & Development Center" }, - { 0x12D1, "Huawei Technologies Co., Ltd." }, - { 0x12D2, "LINE TECH INDUSTRIAL CO., LTD." }, - { 0x12D3, "Linak A/S" }, - { 0x12D4, "Infonics Pty. Limited" }, - { 0x12D5, "Strategic Vista Corp." }, - { 0x12D6, "EMS Dr. Thomas Wuensche" }, - { 0x12D7, "Better Holdings (HK) Limited" }, - { 0x12D8, "Araneus Information Systems Oy" }, - { 0x12D9, "DIGITFAB INTERNATIONAL CO., LTD." }, - { 0x12DA, "Simavionics, Inc." }, - { 0x12DB, "Planar Systems, Inc." }, - { 0x12DC, "MMGEAR Co., Ltd." }, - { 0x12DD, "JFE Advantech Co., Ltd." }, - { 0x12DE, "National Display Systems" }, - { 0x12DF, "Sumitomo 3M Limited" }, - { 0x12E0, "Electronica Mecanica Y Control S.A." }, - { 0x12E1, "FDK CORPORATION" }, - { 0x12E2, "Bonso Electronic Ltd." }, - { 0x12E3, "1417188 Ontario Ltd." }, - { 0x12E4, "Bruel & Kjaer Sound & Vibration Meas. A/S" }, - { 0x12E5, "Interactive Computer Products, Inc." }, - { 0x12E6, "Waldorf-Music AG" }, - { 0x12E7, "Sugiyama Electron Co., Ltd." }, - { 0x12E8, "ZAN Messgeraete" }, - { 0x12E9, "Mindspeed Technologies" }, - { 0x12EA, "Microlink Systems" }, - { 0x12EB, "MITSUI & CO., LTD." }, - { 0x12EC, "KYORITSU ELECTRICAL INSTRUMENTS WORKS, LTD. (R&D Center" }, - { 0x12ED, "Techno Kit Corporation" }, - { 0x12EE, "Avery Dennison Deutschland GmbH" }, - { 0x12EF, "Tapwave, Inc." }, - { 0x12F0, "KROHNE" }, - { 0x12F1, "OHIRA GIKEN, IND. CO., LTD." }, - { 0x12F2, "VIEWPLUS TECHNOLOGIES, INC." }, - { 0x12F3, "FORMOSA TELETEK CORPORATION" }, - { 0x12F4, "Glovic Electronics Corp." }, - { 0x12F5, "Dynamic System Electronics Corp." }, - { 0x12F6, "Aichi Tokei Denki Co., Ltd." }, - { 0x12F7, "Memorex Products, Inc." }, - { 0x12F8, "Evolution Technologies, Inc." }, - { 0x12F9, "RF-LINK SYSTEMS, INC." }, - { 0x12FA, "RF Micro Devices" }, - { 0x12FB, "SSD JAPAN CO., Ltd" }, - { 0x12FC, "eGenium S.r.l." }, - { 0x12FD, "AIN COMM. TECHNOLOGY CO., LTD." }, - { 0x12FE, "E.U CONNECTOR(M) SDN BHD." }, - { 0x12FF, "Fascinating Electronics, Inc." }, - { 0x1300, "Muscle Corporation" }, - { 0x1301, "Woehler Messgeraete Kehrgeraete GmbH" }, - { 0x1302, "Wildseed Ltd." }, - { 0x1303, "Lloyd Research (Projects) Ltd." }, - { 0x1304, "MEDIALINK-I, Inc." }, - { 0x1305, "ELSE Ltd." }, - { 0x1306, "Torcon Instruments Inc." }, - { 0x1307, "USBest Technology Inc." }, - { 0x1308, "Precision Photonics Corp." }, - { 0x1309, "Sabine, Inc." }, - { 0x130A, "SIBATA SCIENTIFIC TECHNOLOGY, LTD." }, - { 0x130B, "MPC Products" }, - { 0x130C, "Quest Technologies" }, - { 0x130D, "Loyal Technology Corporation" }, - { 0x130E, "Microlink Communications Inc." }, - { 0x130F, "AGFA NDT, Krautkramer Ultrasonic Systems" }, - { 0x1310, "Air2U Inc." }, - { 0x1311, "EDX Epi-Scan Corp" }, - { 0x1312, "ICS Electronics" }, - { 0x1313, "THORLABS, INC" }, - { 0x1314, "Ryoko Electric Co., Ltd." }, - { 0x1315, "Prairie Systems & Equip. Ltd. O/A Massload Technologies" }, - { 0x1316, "JUNGLE Inc" }, - { 0x1317, "PC-CRAFT Co., Ltd." }, - { 0x1318, "O'RITE TECHNOLOGY Co., Ltd." }, - { 0x1319, "Peekel Instruments B.V." }, - { 0x131A, "VERYWELL CO., LTD." }, - { 0x131B, "Rowley Associates Ltd." }, - { 0x131C, "Staples, Inc." }, - { 0x131D, "Natural Point" }, - { 0x131E, "Duerr Dental GmbH & Co., KG" }, - { 0x131F, "Ayuttha Technology Corp." }, - { 0x1320, "Jaguar International Corporation" }, - { 0x1321, "Lectrosonics, Inc." }, - { 0x1322, "Z/I Imaging" }, - { 0x1323, "Zeustech Company Limited" }, - { 0x1324, "H-Mod, Inc." }, - { 0x1325, "Austriamicrosystems AG" }, - { 0x1326, "Force Control Industries Inc." }, - { 0x1327, "Avtec, Inc." }, - { 0x1328, "Iris Power Engineering" }, - { 0x1329, "Appairent Technologies, Inc." }, - { 0x132A, "Envara" }, - { 0x132B, "Konica Minolta, Inc." }, - { 0x132C, "Le Prestique International (H.K.) Ltd." }, - { 0x132D, "GE Healthcare Life Sciences" }, - { 0x132E, "Kwang Jang Corporation" }, - { 0x132F, "ViALUX GmbH" }, - { 0x1330, "ALFANUCLEAR S.A." }, - { 0x1331, "Panic Inc." }, - { 0x1332, "Moral Follow System Co., Ltd." }, - { 0x1333, "Ultra Electronics Precision Air & Land Systems" }, - { 0x1334, "ADC Corporation" }, - { 0x1335, "PLUS Corporation" }, - { 0x1336, "IMM-Gruppe" }, - { 0x1337, "Radiant Networks Plc" }, - { 0x1338, "IT CONCEPTS LLC" }, - { 0x1339, "Akashi Corporation" }, - { 0x133A, "Vyyo Inc." }, - { 0x133B, "FLASH SUPPORT GROUP, INC." }, - { 0x133C, "G-Design Technology" }, - { 0x133D, "Jasco Products Company" }, - { 0x133E, "Kemper Digital GmbH" }, - { 0x133F, "Hwayoung RF Solution Inc." }, - { 0x1340, "Escherlogic Inc." }, - { 0x1341, "Lavry Engineering" }, - { 0x1342, "Sutter Instrument Company" }, - { 0x1343, "Heiwa Tokei Mfg. Co., Ltd" }, - { 0x1344, "TCI, Inc. d/b/a TCI Medical" }, - { 0x1345, "Sino Lite Technology Corp." }, - { 0x1346, "Mediatek Corp." }, - { 0x1347, "Moravian Instruments, Inc." }, - { 0x1348, "Katsuragawa Electric Co., Ltd." }, - { 0x1349, "Esaote/Pie Medical Equipment" }, - { 0x134A, "iX Group" }, - { 0x134B, "El Pusk Co., Ltd." }, - { 0x134C, "Panjit International Inc." }, - { 0x134D, "Danfoss Drives A/S" }, - { 0x134E, "Digby's Bitpile, Inc. D.B.A. D Bit" }, - { 0x134F, "Addvalue Communications Pte Ltd." }, - { 0x1350, "UniqueICs, LLC" }, - { 0x1351, "Crossware Associates" }, - { 0x1352, "Km2Net" }, - { 0x1353, "Shenzhen Coship Software Co., Ltd." }, - { 0x1354, "FACTS Engineering LLC" }, - { 0x1355, "Ethicon Endo-Surgery, Inc." }, - { 0x1356, "Techpoint Electric Wire & Cable Co., Ltd." }, - { 0x1357, "P & E Microcomputer Systems, Inc." }, - { 0x1358, "SKYLIGHT DIGITAL INC." }, - { 0x1359, "RKC INSTRUMENT INC." }, - { 0x135A, "URMET TLC S.p.A. - Servizio Amministrativo" }, - { 0x135B, "M-System Co., Ltd." }, - { 0x135C, "Real-Time Essentials, Inc." }, - { 0x135D, "ALGOTEX SRL" }, - { 0x135E, "Insta Elektro GmbH" }, - { 0x135F, "Control Development, Inc." }, - { 0x1360, "FREETRON COM LTD." }, - { 0x1361, "Thinktel Korea Co., Ltd." }, - { 0x1362, "IMAGICA Corp." }, - { 0x1363, "Axsun Technologies, Inc." }, - { 0x1364, "SHARP TAKAYA ELECTRONICS INDUSTRY CO., LTD." }, - { 0x1365, "TOYO JIKI INDUSTRY CO., LTD." }, - { 0x1366, "SEGGER Microcontroller Systems GmbH" }, - { 0x1367, "The Soundbeam Project" }, - { 0x1368, "TelePaq Technology Inc." }, - { 0x1369, "FASL LLC." }, - { 0x136A, "Pelco" }, - { 0x136B, "STEC" }, - { 0x136C, "Datastor Technology Co., Ltd." }, - { 0x136D, "Brainchild" }, - { 0x136E, "Andor Technology" }, - { 0x136F, "Nielsen Media Research" }, - { 0x1370, "Swissbit AG" }, - { 0x1371, "Micro Technology Co., Ltd." }, - { 0x1372, "AMAC Tek Co., Ltd." }, - { 0x1373, "Radical Research, Inc." }, - { 0x1374, "American Anko Co." }, - { 0x1375, "TCL MOBILE COMMUNICATION CO., LTD." }, - { 0x1376, "Vimtron Electronics Co., Ltd." }, - { 0x1377, "Sennheiser Electronic" }, - { 0x1378, "HIRATA Corporation" }, - { 0x1379, "Inprocomm, Inc." }, - { 0x137A, "Weldon Technologies, Inc." }, - { 0x137B, "SCAPS GmbH" }, - { 0x137C, "Yaskawa Electric Corporation" }, - { 0x137D, "Diodes Incorporated" }, - { 0x137E, "XL Microwave, Inc." }, - { 0x137F, "Sata Hi Tech Services" }, - { 0x1380, "Staveley Instruments" }, - { 0x1381, "N-LINE SYSTEM CO., LTD." }, - { 0x1382, "Systemware Inc." }, - { 0x1383, "Application Corporation" }, - { 0x1384, "Device Drivers Limited" }, - { 0x1385, "Variscite Ltd." }, - { 0x1386, "SCD Tech Inc." }, - { 0x1387, "Advanced Technical Group" }, - { 0x1388, "Southern Vision Systems, Inc." }, - { 0x1389, "Coolnection Technology Co., Ltd." }, - { 0x138A, "Validity Inc." }, - { 0x138B, "AMS Limited, Integrated Systems" }, - { 0x138C, "Fortemedia, Inc." }, - { 0x138D, "CPI GmbH" }, - { 0x138E, "RAISONANCE" }, - { 0x138F, "Saia-Burgess Controls Ltd." }, - { 0x1390, "TomTom International B.V." }, - { 0x1391, "IdealTEK" }, - { 0x1392, "SAGE INSTRUMENTS" }, - { 0x1393, "ELNEC s.r.o." }, - { 0x1394, "Gemini 2000 Ltd." }, - { 0x1395, "Sennheiser Communications A/S" }, - { 0x1396, "Greenliant Systems, Inc." }, - { 0x1397, "Behringer Spezielle Studiotechnik GmbH" }, - { 0x1398, "Nintendo of America" }, - { 0x1399, "Thai Wonderful Wire Cable Co., Ltd." }, - { 0x139A, "Infinitec Co., Ltd." }, - { 0x139B, "Thomas Enterprises, Inc." }, - { 0x139C, "Deltronics" }, - { 0x139D, "Digisafe Pte. Ltd." }, - { 0x139E, "Valueplus Inc." }, - { 0x139F, "Audio Technology Switzerland SA" }, - { 0x13A0, "Essilor International" }, - { 0x13A1, "Canas Co., Ltd." }, - { 0x13A2, "Pesa Switching Systems, Inc." }, - { 0x13A3, "Dynon Instruments" }, - { 0x13A4, "Equipment Systems & Devices" }, - { 0x13A5, "Sammy Corporation" }, - { 0x13A6, "Jeppesen Sanderson Inc." }, - { 0x13A7, "Circuit Design, Inc." }, - { 0x13A8, "Grandtec Electronic Corp" }, - { 0x13A9, "YAMAMOTO-MS CO., LTD." }, - { 0x13AA, "Sinar Electronics Limited" }, - { 0x13AB, "MicroMade Galka i Drozdz sp.j" }, - { 0x13AC, "DAQ Systems" }, - { 0x13AD, "Baltech AG" }, - { 0x13AE, "CIM-USA Inc." }, - { 0x13AF, "Handheld Entertainment" }, - { 0x13B0, "PerkinElmer Optoelectronics" }, - { 0x13B1, "Cisco-Linksys, LLC" }, - { 0x13B2, "ALESIS" }, - { 0x13B3, "Nippon Dics Co., Ltd." }, - { 0x13B4, "Dolch Computer Systems" }, - { 0x13B5, "INVENTECH, INC." }, - { 0x13B6, "ISABELLENHUETTE Heusler GmbH KG" }, - { 0x13B7, "Keymark Technology Co., Ltd." }, - { 0x13B8, "PDM Electronic Co., Ltd." }, - { 0x13B9, "Cimcore" }, - { 0x13BA, "Yung Ray Technology Co., Ltd." }, - { 0x13BB, "Covidien Respiratory and Monitoring Solutions" }, - { 0x13BC, "Imaging Supersonic Laboratories Co., Ltd." }, - { 0x13BD, "Remote Technologies, Inc." }, - { 0x13BE, "Ricoh Printing Systems, Ltd." }, - { 0x13BF, "Accusys, Inc." }, - { 0x13C0, "Stream Labs" }, - { 0x13C1, "Vivitar Corporation" }, - { 0x13C2, "SATO KEIRYOKI MFG. CO., LTD." }, - { 0x13C3, "SCT Performance, LLC" }, - { 0x13C4, "StationZ Inc." }, - { 0x13C5, "MELFAS, INC." }, - { 0x13C6, "Hasointech Co., Ltd." }, - { 0x13C7, "ANDO ELECTRIC CO., LTD." }, - { 0x13C8, "Togami Electric Mfg. Co., Ltd." }, - { 0x13C9, "LinearX Systems Inc." }, - { 0x13CA, "JyeTai Precision Industrial Co., Ltd." }, - { 0x13CB, "JTEK Technology Corporation" }, - { 0x13CC, "Cellvic Corporation" }, - { 0x13CD, "ABCD Aging Biorhythms and Computer Diagnostics GmbH" }, - { 0x13CE, "Cypherix (Pty) Ltd." }, - { 0x13CF, "Wisair Ltd." }, - { 0x13D0, "Swedect AB" }, - { 0x13D1, "A-Max Technology Macao Commercial Offshore Co. Ltd." }, - { 0x13D2, "Intelligraphics, Inc." }, - { 0x13D3, "AzureWave Technologies, Inc." }, - { 0x13D4, "IWATSU TEST INSTRUMENTS CORPORATION" }, - { 0x13D5, "International Electronics Inc." }, - { 0x13D6, "Appside" }, - { 0x13D7, "Tableau, LLC" }, - { 0x13D8, "University of Stirling" }, - { 0x13D9, "Blazepoint Limited" }, - { 0x13DA, "OPTEX CO., LTD." }, - { 0x13DB, "Zastron Electronic (Shenzhen) Co. Ltd." }, - { 0x13DC, "ALEREON, INC." }, - { 0x13DD, "i.Tech Dynamic Limited" }, - { 0x13DE, "LANKOM ELECTRONICS CO., LTD." }, - { 0x13DF, "Good Fancy Enterprise Co., Ltd." }, - { 0x13E0, "Taiwan Silicon Electronics Corp." }, - { 0x13E1, "Kaibo Wire & Cable (Shenzhen) Co., Ltd." }, - { 0x13E2, "Parallax, Inc." }, - { 0x13E3, "SoniqCast, LLC" }, - { 0x13E4, "Audio Precision" }, - { 0x13E5, "Sigma Audio Research Ltd." }, - { 0x13E6, "TechnoScope Co., Ltd." }, - { 0x13E7, "Gantner Pigeon Systems GmbH" }, - { 0x13E8, "PalmSource Inc." }, - { 0x13E9, "Ununpentium, LLC" }, - { 0x13EA, "I/F - COM A/S" }, - { 0x13EB, "PILZ GMBH & CO. KG" }, - { 0x13EC, "Chyau Yuan Technology Co., Ltd." }, - { 0x13ED, "Wooju Communications Co., Ltd." }, - { 0x13EE, "ATLab Inc." }, - { 0x13EF, "Turner Technology" }, - { 0x13F0, "DIGENT CO., Ltd." }, - { 0x13F1, "AP Instruments" }, - { 0x13F2, "Tech Micro Corporation" }, - { 0x13F3, "Amulet Hotkey" }, - { 0x13F4, "Verisity Design Inc." }, - { 0x13F5, "X-TEL Communications, Inc." }, - { 0x13F6, "Aspen Touch Solutions, Inc." }, - { 0x13F7, "Corevalley Co., Ltd." }, - { 0x13F8, "EZPnP Technologies Corp." }, - { 0x13F9, "Impsys Digital Security AB" }, - { 0x13FA, "Radiantech, Inc." }, - { 0x13FB, "Noritsu Koki Co., Ltd." }, - { 0x13FC, "Compucat Research Pty Limited" }, - { 0x13FD, "Initio (HK) Corporation Limited" }, - { 0x13FE, "Phison Electronics Corp." }, - { 0x13FF, "VIEWCON ELECTRONIC LTD." }, - { 0x1400, "Axxion Group Corp." }, - { 0x1401, "Fulhua Microelectronics Corp." }, - { 0x1402, "Bowe Bell & Howell" }, - { 0x1403, "Sitronix Technology Corp." }, - { 0x1404, "Fundamental Software Incorporated" }, - { 0x1405, "Cooper Security Ltd." }, - { 0x1406, "Systemneeds, Inc." }, - { 0x1407, "Coin Mechanisms Inc." }, - { 0x1408, "Comark Ltd." }, - { 0x1409, "IDS Imaging Development Systems GmbH" }, - { 0x140A, "Koyo Electronics Industries Co., Ltd." }, - { 0x140B, "Vertex Standard Co., Ltd." }, - { 0x140C, "MITS Electronics" }, - { 0x140D, "Japan Novel Corporation" }, - { 0x140E, "Telechips, Inc." }, - { 0x140F, "i-WAVER" }, - { 0x1410, "Novatel Wireless, Inc." }, - { 0x1411, "SKIDATA AG" }, - { 0x1412, "IMADA CO., LTD." }, - { 0x1413, "Telsey S.p.A." }, - { 0x1415, "Sony Computer Entertainment Europe" }, - { 0x1416, "Axeon Limited" }, - { 0x1417, "Butterfly Media" }, - { 0x1418, "MediaPower Technology Corporation" }, - { 0x1419, "ABILITY ENTERPRISE CO., LTD." }, - { 0x141A, "Realm Systems Inc." }, - { 0x141B, "METRAWARE" }, - { 0x141C, "Leviton Manufacturing" }, - { 0x141D, "J.FIT Co., Ltd." }, - { 0x141E, "Ikegami Tsushinki Co., Ltd." }, - { 0x141F, "SHIMADZU CORPORATION" }, - { 0x1420, "Lyrtech Inc." }, - { 0x1421, "Sentech Co., Ltd." }, - { 0x1422, "Bird Electronic Corporation" }, - { 0x1423, "ANCA Pty. Ltd." }, - { 0x1424, "Posnet Polska S.A." }, - { 0x1425, "IBEX Technology Co., Ltd." }, - { 0x1426, "NADEX Co., Ltd." }, - { 0x1427, "Global Display Solutions S.P.A." }, - { 0x1428, "Improvision Ltd." }, - { 0x1429, "Vega Technologies Industrial (Austria) Co." }, - { 0x142A, "Thales-e-Transactions" }, - { 0x142B, "Arbiter Systems, Inc." }, - { 0x142C, "SOMA OPTICS, LTD." }, - { 0x142D, "Sanblaze Technology, Inc." }, - { 0x142E, "TAMS Inc." }, - { 0x142F, "IO Display Systems" }, - { 0x1430, "Activision" }, - { 0x1431, "Pertech Resources, Inc." }, - { 0x1432, "Beijing Watertek Information Technology Co., Ltd." }, - { 0x1433, "TRANWO TECHNOLOGY CORP." }, - { 0x1434, "Comart System Co., Ltd." }, - { 0x1435, "Wistron NeWeb Corp." }, - { 0x1436, "Denali Software, Inc." }, - { 0x1437, "Carl Zeiss" }, - { 0x1438, "My3ia (Beijing) Technology Ltd." }, - { 0x1439, "Wind River Systems Inc." }, - { 0x143A, "CP Technologies" }, - { 0x143B, "RHESCA Company Limited" }, - { 0x143C, "Altek Corporation" }, - { 0x143D, "FUKOKU INDUSTRY CO., LTD." }, - { 0x143E, "IAV GmbH" }, - { 0x143F, "IDEC IZUMI CORPORATION" }, - { 0x1440, "Jaalaa, Inc." }, - { 0x1441, "MARIAN GbR" }, - { 0x1442, "Canadian Bank Note Company, Limited" }, - { 0x1443, "Digilent Inc." }, - { 0x1444, "H & S Instruments Inc." }, - { 0x1445, "JUSTER CO., LTD." }, - { 0x1446, "X.J. Group Ltd." }, - { 0x1447, "Cognex Corporation" }, - { 0x1448, "Biosystems LLC" }, - { 0x1449, "SHIMADEN CO., LTD." }, - { 0x144A, "Megger" }, - { 0x144B, "MADENTEC LTD." }, - { 0x144C, "Always On UPS Systems Inc." }, - { 0x144D, "K-SUN Corporation" }, - { 0x144E, "Westar Corporation" }, - { 0x144F, "K-jump Health Co., Ltd." }, - { 0x1450, "Melec Inc." }, - { 0x1451, "Force Dimension LLC" }, - { 0x1452, "DAI NIPPON PRINTING CO., LTD." }, - { 0x1453, "Epilog Corporation" }, - { 0x1454, "China IWNCOMM Co., Ltd." }, - { 0x1455, "Georgia Technology Corp." }, - { 0x1456, "Extending Wire & Cable Co., Ltd." }, - { 0x1457, "DAE-A Mediatech Co., Ltd." }, - { 0x1458, "Rauland-Borg Corporation" }, - { 0x1459, "Shanghai Simax Micro-electronics Co., Ltd." }, - { 0x145A, "All-Systems Electronics Pty. Ltd." }, - { 0x145B, "Lead-Type Precision Electronics Co., Ltd." }, - { 0x145C, "Busch-Jaeger-Elektro GmbH" }, - { 0x145D, "Sopac Ltd." }, - { 0x145E, "Forschungszentrum Karlsruhe GmbH" }, - { 0x145F, "Trust International BV" }, - { 0x1460, "TATUNG Company" }, - { 0x1461, "Staccato Communications" }, - { 0x1462, "Bright Computech Co., Ltd." }, - { 0x1463, "BBWM Corp." }, - { 0x1464, "Asiamajor Inc." }, - { 0x1465, "Michilin Prosperity Co., Ltd." }, - { 0x1466, "H2 Developer Group" }, - { 0x1467, "Clearly Superior Technologies" }, - { 0x1468, "CSE Co., Ltd." }, - { 0x1469, "ELECTRIM CORPORATION" }, - { 0x146A, "Knobloch GmbH" }, - { 0x146B, "BigBen Interactive Limited" }, - { 0x146C, "HETEC Datensysteme GmbH" }, - { 0x146D, "Progeny Inc." }, - { 0x146E, "ClearOne Communications" }, - { 0x146F, "Unity Electrical Ind. Ltd." }, - { 0x1470, "STARRIVER TECHNOLOGY CO., LTD." }, - { 0x1471, "Open Labs, Inc." }, - { 0x1472, "Hangzhou H3C Technologies Co., Ltd." }, - { 0x1473, "Dingo Incorporated" }, - { 0x1474, "Lamp Express USA, Inc." }, - { 0x1475, "NAC Image Technology Incorporated" }, - { 0x1476, "Westech Korea Inc." }, - { 0x1477, "XIROKU INC." }, - { 0x1478, "Link World Electric Inc." }, - { 0x1479, "Datalux Corporation" }, - { 0x147A, "Formosa21 Inc." }, - { 0x147B, "ABB STOTZ-KONTAKT GmbH" }, - { 0x147C, "KeyGhost Ltd." }, - { 0x147D, "Tosoh Corporation" }, - { 0x147E, "UPEK Inc." }, - { 0x147F, "Hama GmbH & Co., KG" }, - { 0x1480, "SITEK S.p.a." }, - { 0x1481, "MHT S.p.A." }, - { 0x1482, "Vaillant GmbH" }, - { 0x1483, "Shenzhen MingWah Aohan High Technology Co., Ltd." }, - { 0x1484, "Triad Semiconductor, Inc." }, - { 0x1485, "OrangeWare Corp." }, - { 0x1486, "SCM PC-CARD GmbH" }, - { 0x1487, "DSP Group, Ltd." }, - { 0x1488, "Orion Technology Corp." }, - { 0x1489, "Sakura Finetek USA, Inc." }, - { 0x148A, "MICROVISION" }, - { 0x148B, "HandEra, Inc." }, - { 0x148C, "Colortrac Ltd." }, - { 0x148D, "DESMA Co., Ltd." }, - { 0x148E, "EVATRONIX SA" }, - { 0x148F, "Ralink Technology, Corp." }, - { 0x1490, "Digitek Spa" }, - { 0x1491, "Futronic Technology Co., Ltd." }, - { 0x1492, "Farsharp Imaging Technology Corp." }, - { 0x1493, "Suunto" }, - { 0x1495, "Elprotronic Inc." }, - { 0x1496, "Tunturi Oy Ltd." }, - { 0x1497, "Panstrong Company Ltd." }, - { 0x1498, "ULi Electronics Inc." }, - { 0x1499, "G-STAR Communications, Ltd." }, - { 0x149A, "Imagination Technologies" }, - { 0x149B, "Ivoclar Vivadent AG" }, - { 0x149C, "TonerHead.com" }, - { 0x149D, "QMotions Inc." }, - { 0x149E, "Amkor Technology" }, - { 0x149F, "Wits Technologies Pte. Ltd." }, - { 0x14A0, "WAVE Corporation" }, - { 0x14A1, "Sunhayato Corp." }, - { 0x14A2, "Big Dutchman (Skandinavien) A/S" }, - { 0x14A3, "Wipotec GmbH" }, - { 0x14A4, "Kyerim Industrial Co." }, - { 0x14A5, "I-ROCKS TECHNOLOGY CO., LTD." }, - { 0x14A6, "Interface Masters, Inc." }, - { 0x14A7, "LanReady Technologies, Inc." }, - { 0x14A8, "1C Company" }, - { 0x14A9, "Smar Research Corp." }, - { 0x14AA, "WideView Technology Inc." }, - { 0x14AB, "Technisches Buero Koenig" }, - { 0x14AC, "Coolstf.com" }, - { 0x14AD, "CTK Corporation" }, - { 0x14AE, "Printronix Inc." }, - { 0x14AF, "ATP Electronics Inc." }, - { 0x14B0, "StarTech.com Ltd." }, - { 0x14B1, "I.E. Gesellschaft fuer Industrieelektronik mbH" }, - { 0x14B2, "Alpha Networks Inc." }, - { 0x14B3, "CHUO ELECTRIC WORKS CO., LTD." }, - { 0x14B4, "Appliances Corp." }, - { 0x14B5, "NTS Telecom" }, - { 0x14B6, "Mimic Technologies Inc." }, - { 0x14B7, "In2Games Limited" }, - { 0x14B8, "UNITEK TECHNOLOGY CORPORATION" }, - { 0x14B9, "BP Microsystems" }, - { 0x14BA, "FLOVEL CO., LTD." }, - { 0x14BB, "Assembly Tech. Co., Ltd." }, - { 0x14BC, "NordNav Technologies AB" }, - { 0x14BD, "Eintech Co., Ltd." }, - { 0x14BE, "Crestron Electronics, Inc." }, - { 0x14BF, "Everbee Networks" }, - { 0x14C0, "Rockwell Automation, Inc." }, - { 0x14C1, "SOHYA TECHNOLOGY CO., LTD." }, - { 0x14C2, "Gemlight Computer Ltd." }, - { 0x14C3, "VOXELLE LTD." }, - { 0x14C4, "CLOVER Electronics Co., Ltd." }, - { 0x14C5, "AudioControl" }, - { 0x14C6, "Trigon Components, Inc." }, - { 0x14C7, "Hartmann GmbH" }, - { 0x14C8, "Zytronic Displays Limited" }, - { 0x14C9, "IXOS Ltd. Bvi" }, - { 0x14CA, "Technol Seven Co., Ltd." }, - { 0x14CB, "Dynapoint, Inc." }, - { 0x14CC, "WIN TONG ELECTRONICS CO., LTD." }, - { 0x14CD, "MOAI ELECTRONICS CORPORATION" }, - { 0x14CE, "Spectra, Inc." }, - { 0x14CF, "Measurement Systems Inc." }, - { 0x14D0, "Dentrix Dental Systems, Inc." }, - { 0x14D1, "Maximo Products LLC" }, - { 0x14D2, "BITS CO., LTD." }, - { 0x14D3, "Y2 Corporation" }, - { 0x14D4, "Telequip Corporation" }, - { 0x14D5, "Electronic Theatre Controls" }, - { 0x14D6, "Beijing Zhijiu Technology Co., Ltd." }, - { 0x14D7, "Toppan Printing Co., Ltd." }, - { 0x14D8, "JAMER INDUSTRIES CO., LTD." }, - { 0x14D9, "Advanced Flash Memory Card Technology Ltd." }, - { 0x14DA, "Horng Technical Enterprise Co., Ltd." }, - { 0x14DB, "TOA Musendenki Co., Ltd." }, - { 0x14DC, "Ftech Co., Ltd." }, - { 0x14DD, "Raritan Computer, Inc." }, - { 0x14DE, "Jetway Information Co., Ltd." }, - { 0x14DF, "COMPRION GmbH" }, - { 0x14E0, "Winradio Communications" }, - { 0x14E1, "Imagination Broadway Ltd" }, - { 0x14E2, "Avistar Communications Corporation" }, - { 0x14E3, "Medmont Pty Ltd." }, - { 0x14E4, "S.CAM Co., Ltd." }, - { 0x14E5, "Zinitix Co., Ltd" }, - { 0x14E6, "Micromed Biotecnologia Ltda." }, - { 0x14E7, "ISS Incorporated" }, - { 0x14E8, "Animated Lighting LC" }, - { 0x14E9, "Lifetouch, Inc." }, - { 0x14EA, "Kosaka Laboratory Ltd." }, - { 0x14EB, "Pendulum Instruments AB" }, - { 0x14EC, "Vansco Electronics Ltd." }, - { 0x14ED, "Shure Inc." }, - { 0x14EE, "INFORAD Ltd." }, - { 0x14EF, "AVICLink Corporation" }, - { 0x14F0, "GE" }, - { 0x14F1, "America Hears, LLC." }, - { 0x14F2, "Axess AG" }, - { 0x14F3, "BAP IMAGE SYSTEMS" }, - { 0x14F4, "Accell Corporation" }, - { 0x14F5, "SourceQuest, Inc." }, - { 0x14F6, "Symbium Corporation" }, - { 0x14F7, "TechniSat Digital GmbH" }, - { 0x14F8, "Chenrol Electric Wire & Cable Co., Ltd." }, - { 0x14F9, "Full Conductor Electric Appliance Manufacturer" }, - { 0x14FA, "The Wild Divine Project" }, - { 0x14FB, "JAI" }, - { 0x14FC, "Signami LLC" }, - { 0x14FD, "IPC Information Systems" }, - { 0x14FE, "Madrics Media GmbH Europe" }, - { 0x14FF, "Twinhead International Corp." }, - { 0x1500, "Ellisys" }, - { 0x1501, "Pine-Tum Enterprise Co., Ltd." }, - { 0x1502, "Peavey Electronics" }, - { 0x1503, "Stretch Inc." }, - { 0x1504, "Bixolon Co., Ltd." }, - { 0x1505, "Extraordinary Technologies Pty. Ltd.-Trading as Halcro" }, - { 0x1506, "T.D. Technecon Ltd." }, - { 0x1507, "APIM INFORMATIQUE" }, - { 0x1508, "MAATEL" }, - { 0x1509, "LI-COR Biosciences, Inc." }, - { 0x150A, "TiVo Inc." }, - { 0x150B, "COLLEX COMMUNICATION CORP." }, - { 0x150C, "Brightwell Dispenses Ltd." }, - { 0x150D, "PR Electronics A/S" }, - { 0x150E, "Ono Sokki Co., Ltd." }, - { 0x150F, "Nidec Nemicon Corporation" }, - { 0x1510, "RACEWOOD TELECOM CO., LTD." }, - { 0x1511, "BridgeCo, AG" }, - { 0x1512, "Software Technologies Group, Inc." }, - { 0x1513, "Hypercom" }, - { 0x1514, "Microsemi, SOC Products Group" }, - { 0x1515, "Hexon Media Pte Ltd" }, - { 0x1516, "Skymedi Corporation" }, - { 0x1517, "Precisa Instruments AG" }, - { 0x1518, "Cheshire Engineering Corporation" }, - { 0x1519, "Comneon GmbH Co., Ohg." }, - { 0x151A, "RoyalTek Company Ltd." }, - { 0x151B, "HOSTNET CO." }, - { 0x151C, "VeriSilicon Holdings Co., Ltd." }, - { 0x151D, "P W Allen & Co." }, - { 0x151E, "Circad Design Ltd." }, - { 0x151F, "Opal Kelly Incorporated" }, - { 0x1520, "Bitwire Corp." }, - { 0x1521, "S++ Simulation Services" }, - { 0x1522, "Educational Insights" }, - { 0x1523, "Hitachi High-Tech Science Corporation" }, - { 0x1524, "SCIENTEX Inc." }, - { 0x1525, "Newson Engineering NV" }, - { 0x1526, "ARDUC Co., Ltd." }, - { 0x1527, "iQue Ltd." }, - { 0x1528, "HighAndes Limited" }, - { 0x1529, "UBIQUAM CO., LTD." }, - { 0x152A, "Thesycon Systemsoftware & Consulting GmbH" }, - { 0x152B, "MIR-Medical International Research" }, - { 0x152C, "titel++" }, - { 0x152D, "JMicron Technology Corp." }, - { 0x152E, "HLDS (Hitachi-LG Data Storage, Inc.)" }, - { 0x152F, "PRO-MECH CORPORATION" }, - { 0x1530, "Martsoft Corp." }, - { 0x1531, "MICRODIA Ltd." }, - { 0x1532, "Razer (Asia-Pacific) Pte Ltd." }, - { 0x1533, "AEPTEC Microsystems, Inc." }, - { 0x1534, "Advanced Research Corporation" }, - { 0x1535, "Practical Engineering Incorporated" }, - { 0x1536, "Neonode Technologies AB" }, - { 0x1537, "Power Up Manufacturing" }, - { 0x1538, "IES Elektronikentwicklung" }, - { 0x1539, "AFG-Engineering GmbH" }, - { 0x153A, "WMS Gaming Inc." }, - { 0x153B, "ERCO Leuchten GmbH" }, - { 0x153C, "Guger Technologies OEG" }, - { 0x153D, "Adam Tech" }, - { 0x153E, "abKey ptd ltd." }, - { 0x153F, "UNIBRAIN S.A." }, - { 0x1540, "Phihong Technology Co., Ltd." }, - { 0x1541, "Better Light, Inc." }, - { 0x1542, "Gemini Industries, Inc." }, - { 0x1543, "Buxco Research Systems" }, - { 0x1544, "Alphamosaic Ltd." }, - { 0x1545, "Kistler Instrumente AG" }, - { 0x1546, "u-blox AG" }, - { 0x1547, "S. Goers IT-Solutions" }, - { 0x1548, "Centrepoint Technologies" }, - { 0x1549, "Beamex Oy Ab" }, - { 0x154A, "ID Innovations Incorporated" }, - { 0x154B, "PNY Technologies Inc." }, - { 0x154C, "AutoXray Inc." }, - { 0x154D, "Rapid Conn, Connect County Holdings Bhd" }, - { 0x154E, "D & M Holdings, Inc." }, - { 0x154F, "Shandong New Beiyang Information Technology Co., Ltd." }, - { 0x1550, "Cardinal Health, Inc." }, - { 0x1551, "SAIC/IISBU" }, - { 0x1552, "DALLAB (M) SDN BHD (587734-A)" }, - { 0x1553, "Raytheon Commercial Infrared" }, - { 0x1554, "Prolink Microsystems Corporation" }, - { 0x1555, "OWEN Ltd." }, - { 0x1556, "CERN" }, - { 0x1557, "OQO" }, - { 0x1558, "Microbus Designs Ltd." }, - { 0x1559, "The Toro Company" }, - { 0x155A, "ELDAT GmbH" }, - { 0x155B, "Shanghai Huahong Integrated Circuit Co., Ltd." }, - { 0x155C, "Meyers Technology" }, - { 0x155D, "National Rejectors, Inc. GmbH" }, - { 0x155E, "DUPLO SEIKO CORPORATION" }, - { 0x155F, "Cobra Electronics Corporation" }, - { 0x1560, "Supra, A UTC Fire & Security Company" }, - { 0x1561, "LaunchPadOffice Inc." }, - { 0x1562, "Infowize Technologies Corporation" }, - { 0x1563, "Micronet Corporation" }, - { 0x1564, "Gizmondo Europe Ltd." }, - { 0x1565, "Advance Modules" }, - { 0x1566, "WIN ACCORD LTD." }, - { 0x1567, "MUTOH Industries Ltd." }, - { 0x1568, "Sunf Pu Technology (Dong-Guan) Co., Ltd." }, - { 0x1569, "Mad City Labs, Inc." }, - { 0x156A, "Logical Solutions, Inc." }, - { 0x156B, "Cairn Research Ltd." }, - { 0x156C, "Meade Instruments Corp." }, - { 0x156D, "OMICRON electronics GmbH" }, - { 0x156E, "MVox Electronics" }, - { 0x156F, "Quantum Corporation" }, - { 0x1570, "ALLTOP TECHNOLOGY CO., LTD." }, - { 0x1571, "NIKON-TRIMBLE CO., LTD." }, - { 0x1572, "Ricreations, Inc." }, - { 0x1573, "Gradiente Eletronica S.A." }, - { 0x1574, "HKW-Elektronik GmbH" }, - { 0x1575, "Video Associates Labs, Inc." }, - { 0x1576, "Maretron" }, - { 0x1577, "MIYUKI ELEX CO., LTD." }, - { 0x1578, "Beijing Huaqi Information Digital Technology Co., Ltd." }, - { 0x1579, "Reputed Industrial Company Limited" }, - { 0x157A, "Lowrance Electronics, Inc." }, - { 0x157B, "Ketron SRL" }, - { 0x157C, "Eurosoft (UK) Ltd." }, - { 0x157D, "Tokyo Sokuteikizai Co., Ltd." }, - { 0x157E, "U-MEDIA Communications, Inc." }, - { 0x157F, "Levon Limited" }, - { 0x1580, "Real Time Logic, Inc." }, - { 0x1581, "IGB Communication Co., Ltd." }, - { 0x1582, "Asia Pacifc Microsystems, Inc." }, - { 0x1583, "EUCHNER GmbH & Co. KG" }, - { 0x1584, "Prueftechnik AG" }, - { 0x1585, "IKeyInfinity Inc." }, - { 0x1586, "Palconn Technology Co., Ltd." }, - { 0x1587, "SMA Solar Technology AG" }, - { 0x1588, "Fine Instruments Corporation" }, - { 0x1589, "Arcus Technology Inc." }, - { 0x158A, "BOBE Industrie-Elektronik" }, - { 0x158B, "Righttag Inc." }, - { 0x158C, "LINFOS CO., LTD." }, - { 0x158D, "Oakley Inc." }, - { 0x158E, "Acterna Germany GmbH" }, - { 0x158F, "Tai Yip Electrical Co., Ltd." }, - { 0x1590, "Onsu Data Telecommunication Technology (Shenzhen) Fty." }, - { 0x1591, "Advanced Product Design & Mfg. Inc." }, - { 0x1592, "Tokyo Drawing Ltd." }, - { 0x1593, "Vector International bvba" }, - { 0x1594, "Lockheed Martin Missiles & Fire Control" }, - { 0x1595, "Flexiworld Technologies, Inc." }, - { 0x1596, "Kilodyne LLC" }, - { 0x1597, "KCodes Corporation" }, - { 0x1598, "Kunshan Guoji Electronics Co., Ltd." }, - { 0x1599, "ANRITSU METER CO., LTD." }, - { 0x159A, "SkuTek Instrumentation" }, - { 0x159B, "Zitte Corporation" }, - { 0x159C, "Binary Acoustic Technology" }, - { 0x159D, "Boone Cable Works & Electronics" }, - { 0x159E, "SmartSwing, Inc." }, - { 0x159F, "Beijer Electronics AB" }, - { 0x15A0, "Zarlink Semiconductor" }, - { 0x15A1, "Nicety Technologies Inc." }, - { 0x15A2, "Freescale Semiconductor, Inc." }, - { 0x15A3, "Larson Davis, Inc." }, - { 0x15A4, "Afa Technologies, Inc." }, - { 0x15A5, "CIT Engineering NV" }, - { 0x15A6, "Unicos Corporation" }, - { 0x15A7, "APPSware Wireless LLC dba Apriva" }, - { 0x15A8, "Shen Zhen Teamspower Electronics Co., Ltd." }, - { 0x15A9, "Gemtek Technology Co., Ltd." }, - { 0x15AA, "GuangDong Ya Lian Technology Co., Ltd" }, - { 0x15AB, "Virgin HealthMiles, Inc." }, - { 0x15AC, "Smartware" }, - { 0x15AD, "Bleile Datentechnik GmbH" }, - { 0x15AE, "KAYSER-THREDE GMBH" }, - { 0x15AF, "Jenaer Antriebstechnik GmbH" }, - { 0x15B0, "Pacific Instruments, Inc." }, - { 0x15B1, "MiTAC Technology Corporation" }, - { 0x15B2, "Audio Dev AB" }, - { 0x15B3, "GL Sciences Inc." }, - { 0x15B4, "Orient Power Multimedia Ltd." }, - { 0x15B5, "ANUBIS ELECTRONIC GmbH" }, - { 0x15B6, "Dialog Semiconductor GmbH" }, - { 0x15B7, "Hyper Stimulator International Pty Ltd." }, - { 0x15B8, "Serome Electronics, Inc." }, - { 0x15B9, "USD Corporation" }, - { 0x15BA, "Olimex Ltd." }, - { 0x15BB, "CopyPro , Inc." }, - { 0x15BC, "Daktronics Inc." }, - { 0x15BD, "Sigmaelectronics Co., Ltd." }, - { 0x15BE, "EssNet Interactive AB" }, - { 0x15BF, "ESA, Inc." }, - { 0x15C0, "CJM" }, - { 0x15C1, "Amirix Systems Inc." }, - { 0x15C2, "SoundGraph, Inc." }, - { 0x15C3, "m.u.t - GmbH" }, - { 0x15C4, "Global Marketing Alliance, Inc." }, - { 0x15C5, "Pressure Profile Systems, Inc." }, - { 0x15C6, "Laboratoires MXM" }, - { 0x15C7, "IRI-Ubiteq, Inc." }, - { 0x15C8, "KTF Technologies" }, - { 0x15C9, "D-Box Technologies" }, - { 0x15CA, "TEXTECH INTERNATIONAL LTD." }, - { 0x15CB, "Activis Polska" }, - { 0x15CC, "GL Communications Inc." }, - { 0x15CD, "DeFelsko Corporation" }, - { 0x15CE, "Oriental R&D Co., Ltd." }, - { 0x15CF, "AVTOR Ltd.." }, - { 0x15D0, "AIRSTAR Inc." }, - { 0x15D1, "Hokuyo Automatic Co., Ltd." }, - { 0x15D2, "REA Elektronik GmbH" }, - { 0x15D3, "Symmetric Research" }, - { 0x15D4, "Opinionmeter International, Ltd." }, - { 0x15D5, "Coulomb Electronics Ltd." }, - { 0x15D6, "Fitness Expert" }, - { 0x15D7, "amaxa GmbH" }, - { 0x15D8, "Grundig Business Systems GmbH" }, - { 0x15D9, "Apexone Microelectronics Inc." }, - { 0x15DA, "Cooper - Atkins Corporation" }, - { 0x15DB, "Philip Harris Education" }, - { 0x15DC, "Hynix Semiconductor Inc." }, - { 0x15DD, "Axona Limited" }, - { 0x15DE, "Spatial Freedom, Inc." }, - { 0x15DF, "Helmut Fischer GmbH + Co. KG" }, - { 0x15E0, "Seong Ji Industrial Co., Ltd." }, - { 0x15E1, "RSA Security Inc." }, - { 0x15E2, "Bionopoly LLC" }, - { 0x15E3, "NEURICAM SPA" }, - { 0x15E4, "Numark Industries" }, - { 0x15E5, "Micro Systems Inc." }, - { 0x15E6, "Turnkey Ltd." }, - { 0x15E7, "Media Systems Ltd." }, - { 0x15E8, "Micro Tools Inc." }, - { 0x15E9, "Pacific Digital Corp." }, - { 0x15EA, "C-guys Inc." }, - { 0x15EB, "VIA Telecom" }, - { 0x15EC, "Belcarra Technologies Corp." }, - { 0x15ED, "UCA Technology Inc." }, - { 0x15EE, "Quorum Communications, Inc." }, - { 0x15EF, "MSilicon Electronics, Inc." }, - { 0x15F0, "Technex Lab Co., Ltd." }, - { 0x15F1, "Mortara Instrument, Inc." }, - { 0x15F2, "Chyron Corp." }, - { 0x15F3, "AquaCube Inc." }, - { 0x15F4, "Computer & Entertainment, Inc." }, - { 0x15F5, "Mobitek Communication Corp." }, - { 0x15F6, "ASICS World Services Ltd." }, - { 0x15F7, "HANTEL CO., LTD." }, - { 0x15F8, "Vianet, Inc." }, - { 0x15F9, "SunCorp Industrial Limited" }, - { 0x15FA, "Department of Defense" }, - { 0x15FB, "R-Quest Technologies , LLC" }, - { 0x15FC, "Humen Xintai Electrical Wires Factory" }, - { 0x15FD, "XEMAX Co., Ltd." }, - { 0x15FE, "Bio-Rad Laboratories Deeside" }, - { 0x15FF, "Heartsine Technologies Ltd." }, - { 0x1600, "Monisys Limited" }, - { 0x1601, "Avenues in Leather" }, - { 0x1602, "CompUSA Inc." }, - { 0x1603, "ERGODEX Corp." }, - { 0x1604, "Kyokko Seiko Co., Ltd." }, - { 0x1605, "Acces I/O Products, Inc." }, - { 0x1606, "UMAX Data Systems Inc." }, - { 0x1607, "ESE Corporate" }, - { 0x1608, "Inside Out Networks, a division of Digi International" }, - { 0x1609, "K-byte (ACI Group)" }, - { 0x160A, "VIA Networking Technologies, Inc." }, - { 0x160B, "CSI Wireless Inc." }, - { 0x160C, "Shanghai Tiananxin Information & Tech., Co., Ltd." }, - { 0x160D, "Samtec" }, - { 0x160E, "INRO Consultants Inc." }, - { 0x160F, "Strand Lighting Limited" }, - { 0x1610, "Q-Sense AB" }, - { 0x1611, "Vita-Mix Corporation" }, - { 0x1612, "Soft DB Inc." }, - { 0x1613, "Airconnect Solutions (Asia) Ltd." }, - { 0x1614, "Amoi Electronics Co., Ltd." }, - { 0x1615, "Rock Data Services Ltd." }, - { 0x1616, "Cute Mobile Corp." }, - { 0x1617, "Navman" }, - { 0x1618, "Redpine Signals, Inc." }, - { 0x1619, "L & K Precision Technology Co., Ltd." }, - { 0x161A, "Celeraise Investments Ltd." }, - { 0x161B, "MYCOM, INC." }, - { 0x161C, "DigiTech Systems Co., Ltd." }, - { 0x161D, "Delfin Technologies Ltd." }, - { 0x161E, "Aerotech Inc." }, - { 0x161F, "Prosisa International LLC" }, - { 0x1620, "Accesstek Inc." }, - { 0x1621, "Wionics Research" }, - { 0x1622, "California Instruments" }, - { 0x1623, "Mindtech Limited" }, - { 0x1624, "AIOI Systems, USA Corp." }, - { 0x1625, "ViaSat UK" }, - { 0x1626, "Advance Data Technology Corporation" }, - { 0x1627, "IPextreme, Inc." }, - { 0x1628, "Stonestreet One, Inc." }, - { 0x1629, "Erae Electronics" }, - { 0x162A, "Airgo Networks Inc." }, - { 0x162B, "Acksys" }, - { 0x162C, "Ecler Laboratorio de Electroacustica S.A." }, - { 0x162D, "Control Instruments Development (Pty) Ltd." }, - { 0x162E, "Joytech Europe Ltd." }, - { 0x162F, "WiQuest Communications, Inc." }, - { 0x1630, "QformX" }, - { 0x1631, "Focus Enhancements" }, - { 0x1632, "Data Ray Inc." }, - { 0x1633, "AIM GmbH" }, - { 0x1634, "ABB Switzerland Ltd." }, - { 0x1635, "Doble Engineering Co." }, - { 0x1636, "Kobe-Addtech Co., Ltd." }, - { 0x1637, "LZAE LUMEL SA" }, - { 0x1638, "Skyworks Solutions" }, - { 0x1639, "BeRiver Electronics Co., Ltd." }, - { 0x163A, "Traficon N.V." }, - { 0x163B, "Controlled Speed Engineering Ltd." }, - { 0x163C, "Watchdata System Co., Ltd." }, - { 0x163D, "Million Tech Dev. Ltd." }, - { 0x163E, "Dezhou HongJu Communication Technology Co., Ltd." }, - { 0x163F, "AVEX Technologies, Inc." }, - { 0x1640, "M3 Electronics, Inc." }, - { 0x1641, "eMagin Corporation" }, - { 0x1642, "AquaSensors LLC" }, - { 0x1643, "Sanwa Newtec Co., Ltd." }, - { 0x1644, "Active Technologies SRL" }, - { 0x1645, "Smiths Heimann Biometrics GmbH" }, - { 0x1646, "Altronic, Inc." }, - { 0x1647, "Horizon Navigation, Inc." }, - { 0x1648, "Wood Head Software & Electronics" }, - { 0x1649, "Softec Microsystems" }, - { 0x164A, "ChipX" }, - { 0x164B, "Lytech Technology Inc." }, - { 0x164C, "Matrix Vision GmbH" }, - { 0x164D, "DASAN Networks, Inc." }, - { 0x164E, "Picotest Corp." }, - { 0x164F, "Kinkei System Co., Ltd." }, - { 0x1650, "Remopro Technology Inc." }, - { 0x1651, "PACOMP" }, - { 0x1652, "EFull Tech. Corp. Ltd." }, - { 0x1653, "Nissho Electronics Co., Ltd." }, - { 0x1654, "Stamer Musikanlagen GmbH" }, - { 0x1655, "Dtron Co., Ltd." }, - { 0x1656, "QSC Audio Products, Inc." }, - { 0x1657, "Struck Innovative Systeme GmbH" }, - { 0x1658, "Grayhill Inc." }, - { 0x1659, "Lathem Time Corp." }, - { 0x165A, "E.D.P. SRL" }, - { 0x165B, "Frontier Design Group" }, - { 0x165C, "Kondo Kagaku Co., Ltd." }, - { 0x165D, "Orange Tree Technologies Ltd." }, - { 0x165E, "Pangolin" }, - { 0x165F, "Ansync Inc." }, - { 0x1660, "Creatix Polymedia GmbH" }, - { 0x1661, "DVS Korea Co., Ltd." }, - { 0x1662, "Positivo Informatica LTDA" }, - { 0x1663, "Sercel, Inc." }, - { 0x1664, "ARGOX INFORMATION CO., LTD." }, - { 0x1665, "General Dynamics Canada" }, - { 0x1666, "Vanguard Instruments Co., Inc." }, - { 0x1667, "GIGA-TMS, INC." }, - { 0x1668, "Actiontec Electronics, Inc." }, - { 0x1669, "PiKRON s.r.o." }, - { 0x166A, "Clipsal Integrated Systems" }, - { 0x166B, "PedalPax Corporation" }, - { 0x166C, "Technology Driven Solutions Ltd" }, - { 0x166D, "MCS Logic Inc." }, - { 0x166E, "SerComm Corporation" }, - { 0x166F, "Idetech Europe S.A." }, - { 0x1670, "Hach Company" }, - { 0x1671, "Telular Corporation" }, - { 0x1672, "MBS GmbH" }, - { 0x1673, "ROBOTIKER" }, - { 0x1674, "Pantone, Inc." }, - { 0x1675, "SE-IR Corporation" }, - { 0x1676, "I-Ware Laboratory Co., Ltd." }, - { 0x1677, "China Integrated Circuit Design Corp., Ltd." }, - { 0x1678, "Matsunichi Information Technology (Shenzhen) Co., Ltd." }, - { 0x1679, "Total Phase" }, - { 0x167A, "USBWARE" }, - { 0x167B, "Pure Digital Technologies" }, - { 0x167C, "Vionics" }, - { 0x167D, "SIM Security & Electronic System GmbH" }, - { 0x167E, "Videa Technology Inc." }, - { 0x167F, "Actigraph, LLC" }, - { 0x1680, "KaVo Dental GmbH" }, - { 0x1681, "Prevo Technologies, Inc." }, - { 0x1682, "Maxwise Production Enterprise Ltd." }, - { 0x1683, "DualCor Technologies, Inc." }, - { 0x1684, "Godspeed Computer Corp." }, - { 0x1685, "Tanic Electroics Ltd." }, - { 0x1686, "ZOOM Corporation" }, - { 0x1687, "Kingmax Digital Inc." }, - { 0x1688, "AerotechTelub AB" }, - { 0x1689, "Griffin International Companies, Inc." }, - { 0x168A, "Veeco Instruments" }, - { 0x168B, "BTC Secu Co., Ltd." }, - { 0x168C, "Tabor Electroics Ltd." }, - { 0x168D, "YSI, Inc." }, - { 0x168E, "iMetrikus Inc." }, - { 0x168F, "ETA S.A. Manufacture Horlogere Suisse" }, - { 0x1690, "Simple Solutions" }, - { 0x1691, "Landers Instruments" }, - { 0x1692, "Weatherford" }, - { 0x1693, "Zultys Technologies" }, - { 0x1694, "Cassidian Communications" }, - { 0x1695, "FATAR, S.r.l." }, - { 0x1696, "Hitachi Advanced Digital, Inc." }, - { 0x1697, "VTEC TEST, INC." }, - { 0x1698, "Eurosmart" }, - { 0x1699, "United RadioTek Inc." }, - { 0x169A, "Ten X Technology Inc." }, - { 0x169B, "aitronic GmbH" }, - { 0x169C, "DMS" }, - { 0x169E, "Groupics.com, Inc." }, - { 0x169F, "Monolith Inc." }, - { 0x16A0, "Real Thoughts GmbH" }, - { 0x16A1, "Trilithic, Inc." }, - { 0x16A2, "Sypris Test and Measurement (FW Bell)" }, - { 0x16A3, "B & W Tek Inc." }, - { 0x16A4, "Sagutech Microsystems" }, - { 0x16A5, "Shenzhen Zhengerya Technology Co., Ltd." }, - { 0x16A6, "UNIGRAF OY" }, - { 0x16A7, "Sauer-Danfoss" }, - { 0x16A8, "Nice Systems" }, - { 0x16A9, "Worth-Pfaff Innovations, Inc." }, - { 0x16AA, "Symtx Inc." }, - { 0x16AB, "InnoWireless Co. Ltd." }, - { 0x16AC, "Dongguan ChingLung Wire & Cable Co., Ltd." }, - { 0x16AD, "Siemens VDO Trading GmbH" }, - { 0x16AE, "ELSA Japan Inc." }, - { 0x16AF, "Intelligent Mechatronic Systems" }, - { 0x16B0, "Infosight Corp." }, - { 0x16B1, "Cami Research Inc." }, - { 0x16B2, "Bruxton Corporation" }, - { 0x16B3, "Eizoken Inc." }, - { 0x16B4, "Digital Cube" }, - { 0x16B5, "PerSen Technologies, Inc." }, - { 0x16B6, "Nexus Technology Inc." }, - { 0x16B7, "Pulsafeeder Inc." }, - { 0x16B8, "Honeywell Life Safety" }, - { 0x16B9, "Origin Technologies Limited" }, - { 0x16BA, "SmarTec" }, - { 0x16BB, "Tomra Systems ASA" }, - { 0x16BC, "JOBO AG" }, - { 0x16BD, "Leica Geosystems AG" }, - { 0x16BE, "RyuSyo Industrial Co., Ltd." }, - { 0x16BF, "CAST, INC." }, - { 0x16C0, "Van Ooijen Technische Informatica" }, - { 0x16C1, "Lucas-Nuelle GmbH" }, - { 0x16C2, "Amphenol-Data Telecom" }, - { 0x16C3, "Nihon Kaiheiki Ind. Co., Ltd." }, - { 0x16C4, "SavaJe Technologies, Inc." }, - { 0x16C5, "Cryptek Inc." }, - { 0x16C6, "NDS Surgical Imaging, LLC" }, - { 0x16C7, "Crystal Technology, Inc." }, - { 0x16C8, "Technische Universiteit Eindhoven" }, - { 0x16C9, "OCT Co., Ltd." }, - { 0x16CA, "Wireless Cables Inc." }, - { 0x16CB, "Highwater Designs Limited" }, - { 0x16CC, "silex technology, Inc." }, - { 0x16CD, "Brian Moore Guitars, Inc." }, - { 0x16CE, "IPFlex Inc." }, - { 0x16CF, "YAZAKI PARTS CO., LTD." }, - { 0x16D1, "SUPREMA, INC." }, - { 0x16D2, "TOMEY" }, - { 0x16D3, "Frontline Test Equipment, Inc." }, - { 0x16D4, "SRTechnologies" }, - { 0x16D5, "AnyDATA Corporation" }, - { 0x16D6, "Jablotron" }, - { 0x16D7, "Aprilis, Inc." }, - { 0x16D8, "CMOTECH CO., LTD." }, - { 0x16D9, "A7 Engineering, Inc." }, - { 0x16DA, "Linkam Scientific Instruments Ltd." }, - { 0x16DB, "Eridon Corporation" }, - { 0x16DC, "W-IE-NE-R, Plein & Baus GmbH" }, - { 0x16DD, "YOSHIDA SEIKI CO., LTD." }, - { 0x16DE, "Schneider Electric" }, - { 0x16DF, "King Billion Electronics Co., Ltd." }, - { 0x16E0, "Lumex Ltd." }, - { 0x16E1, "Bed Check Corporation" }, - { 0x16E2, "Hitachi I E Systems Co., Ltd." }, - { 0x16E3, "ITM Inc." }, - { 0x16E4, "Franklin Electric Co., Inc." }, - { 0x16E5, "TOKYO KEIKI RAIL TECHNO INC." }, - { 0x16E6, "Diginfo Technology Corporation" }, - { 0x16E7, "United Keys, Inc." }, - { 0x16E8, "Frontier Information Enterprise, Inc." }, - { 0x16E9, "Dr. Gal Ben-David" }, - { 0x16EA, "Avionica, Inc." }, - { 0x16EB, "Helvar" }, - { 0x16EC, "ASAHI GLASS CO., LTD." }, - { 0x16ED, "Parker Vision Inc." }, - { 0x16EE, "Ryvor Corp." }, - { 0x16EF, "Global Safety & Security Solutions OY" }, - { 0x16F0, "GN ReSound" }, - { 0x16F1, "Versus Technology, Inc." }, - { 0x16F2, "St. Jude Medical AB" }, - { 0x16F3, "Hammer Storage/Bell Microproducts" }, - { 0x16F4, "Lineeye Co., Ltd." }, - { 0x16F5, "Futurelogic Inc." }, - { 0x16F6, "Shin Tek Inc." }, - { 0x16F7, "Japan Gals Co., Ltd." }, - { 0x16F8, "Ever Bright Wire Factory" }, - { 0x16F9, "Astrosys International Limited" }, - { 0x16FA, "Shachihata Inc." }, - { 0x16FB, "MICRONIX CORPORATION" }, - { 0x16FC, "TRICOM TECHNOLOGIES, INC." }, - { 0x16FD, "Reakin Technology Corporation" }, - { 0x16FE, "Su Zhou Song Qing Electronical Co., Ltd." }, - { 0x16FF, "Ultimate Technology Corp." }, - { 0x1700, "Hunt Engineering (UK) Ltd." }, - { 0x1701, "Peyroutet Telecom" }, - { 0x1702, "Softcare Ltd." }, - { 0x1703, "NormSoft, Inc." }, - { 0x1704, "ANIMATICS CORP." }, - { 0x1705, "Aerosonic Corporation" }, - { 0x1706, "BlueView Technologies, Inc." }, - { 0x1707, "ARTIMI" }, - { 0x1708, "Mibudenki Industrial Co., Ltd." }, - { 0x1709, "Sanmina-SCI" }, - { 0x170A, "MAXTEK, INC." }, - { 0x170B, "Phonic Corp." }, - { 0x170C, "BlueTree Wireless Data" }, - { 0x170D, "Avnera" }, - { 0x170E, "Iris Corporation Berhad" }, - { 0x170F, "UbiBro Technolgies Inc." }, - { 0x1710, "AZIO Corporation" }, - { 0x1711, "Leica Microsystems CMS GmbH" }, - { 0x1712, "Fujitsu LSI Technology Ltd." }, - { 0x1713, "Enter Tech Co., Ltd" }, - { 0x1714, "iCRco" }, - { 0x1715, "NL Technology" }, - { 0x1716, "LHR Technologies" }, - { 0x1717, "Formats Unlimited, Inc." }, - { 0x1718, "Mobile Doctor Co., Ltd." }, - { 0x1719, "American Technology Corp." }, - { 0x171A, "PSi Printer Systems international GmbH" }, - { 0x171B, "NT Ware Systemprogrammierung GmbH" }, - { 0x171C, "IER" }, - { 0x171E, "PACIFIC CORPORATION" }, - { 0x171F, "CHIPNUTS TECHNOLOGY INC." }, - { 0x1720, "Innova Electronics Corp." }, - { 0x1721, "ELAD SRL" }, - { 0x1722, "Axicon Auto ID LTD" }, - { 0x1723, "Datatronics Technology, Inc" }, - { 0x1724, "Lumenera Corporation" }, - { 0x1725, "HI-TECH Software" }, - { 0x1726, "Axesstel, Inc." }, - { 0x1727, "RiCHIP Incorporated" }, - { 0x1728, "BYTE TOOLS INC." }, - { 0x1729, "CONSULTRONICS EUROPE LTD." }, - { 0x172A, "wenglor sensoric gmbh" }, - { 0x172B, "CompuSoft A/S" }, - { 0x172C, "Silicon Optix" }, - { 0x172D, "AccFast Technology Corp." }, - { 0x172E, "ELECTION SYSTEMS & Software" }, - { 0x172F, "WALTOP International Corporation" }, - { 0x1730, "MERCURY" }, - { 0x1731, "DATA DISPLAY AG" }, - { 0x1732, "NETENRICH INC." }, - { 0x1733, "NUBYTECH INC." }, - { 0x1734, "IPdrum AB" }, - { 0x1735, "Satloc LLC (CSI Wireless)" }, - { 0x1736, "CANON IMAGING SYSTEMS INC." }, - { 0x1737, "Hong Kong Applied Science and Technology Research Inst." }, - { 0x1738, "Asicen Technology Corp." }, - { 0x1739, "Radiant Technologies Inc." }, - { 0x173A, "F. Hoffmann-La Roche AG" }, - { 0x173B, "Cadillac Jack Inc." }, - { 0x173C, "Signalcraft Technologies Inc." }, - { 0x173D, "Great Pleasure Electronics Co. LTD." }, - { 0x173E, "Devlin Electronics Ltd." }, - { 0x173F, "Peyer Engineering" }, - { 0x1740, "Senao International Co., Ltd." }, - { 0x1741, "Techino Science Co., Ltd." }, - { 0x1742, "Nippon Chemi-Con Corp." }, - { 0x1743, "General Atomics" }, - { 0x1744, "Sanwa Electronic Instrument Co. Ltd." }, - { 0x1745, "Video Simplex, Inc." }, - { 0x1746, "Edge Products" }, - { 0x1747, "CML MICROCIRCUITS (UK) LTD" }, - { 0x1748, "MQP Electronics Ltd." }, - { 0x1749, "MAGO MOBILE LTD" }, - { 0x174A, "Endress + Hauser" }, - { 0x174B, "BARACODA" }, - { 0x174C, "ASMedia Technology Inc." }, - { 0x174D, "Broadcast System & Design ApS" }, - { 0x174E, "Xi'an Tongshi Data Co., Ltd." }, - { 0x174F, "D-MAX Technology Co., Ltd." }, - { 0x1750, "Hirschmann Automation and Control GmbH" }, - { 0x1751, "EMPIRISOFT CORPORATION" }, - { 0x1752, "Liyitec Incorporated" }, - { 0x1753, "Tecvan Informatica LTDA" }, - { 0x1754, "GERSTEL GmbH & Co. KG" }, - { 0x1755, "Electronics and Telecommunication Research Institute" }, - { 0x1756, "ENENSYS Technologies" }, - { 0x1757, "ST-MICHAEL STRATEGIES" }, - { 0x1758, "FUTURECOM SYSTEMS GROUP INC." }, - { 0x1759, "LucidPort Technology, Inc." }, - { 0x175A, "Lantronix" }, - { 0x175B, "Dongguan Init Technology Co., Ltd." }, - { 0x175C, "Isolcell Italia SpA" }, - { 0x175D, "Caterpillar Inc." }, - { 0x175E, "AT KidSystems Inc." }, - { 0x175F, "I-BIT Corporation" }, - { 0x1760, "RAYLASE AG" }, - { 0x1761, "RC GROUP (Holdings) Limited" }, - { 0x1763, "USAF" }, - { 0x1764, "KANOMAX JAPAN INC." }, - { 0x1765, "VK Corporation" }, - { 0x1766, "Hip Interactive Inc." }, - { 0x1767, "KIS Photo Mc Group" }, - { 0x1769, "ARTEK Inc." }, - { 0x176A, "GLOBALSAT TECHNOLOGY CORPORATION" }, - { 0x176B, "ATOP ELECTRONICS CO., LTD." }, - { 0x176C, "Advanced Electronic Designs" }, - { 0x176D, "Mbridge Systems, Inc." }, - { 0x176E, "UD electronic corp." }, - { 0x176F, "Astralink Technology Pte Ltd" }, - { 0x1770, "precisionWave Corporation" }, - { 0x1771, "Shenzhen Alex Connector Co., Ltd." }, - { 0x1772, "System Level Solutions, Inc." }, - { 0x1773, "InSync Speech Technologies, Inc." }, - { 0x1774, "Strawberry Linux Co., Ltd." }, - { 0x1775, "RADAR-TRONIC KFT." }, - { 0x1776, "HYPERLABS, Inc." }, - { 0x1777, "Microscan Systems, Inc." }, - { 0x1778, "PChome Online Inc." }, - { 0x1779, "Optek Electronics Co., Ltd." }, - { 0x177A, "Explore Semiconductor, Inc." }, - { 0x177B, "Cetus Engineering" }, - { 0x177C, "AD Information & Communications Co., Ltd" }, - { 0x177D, "Delta Industrie Service" }, - { 0x177E, "mils electronic GmbH & Co Kg" }, - { 0x177F, "Sweex Europe B.V." }, - { 0x1780, "TENDYRON CORPORATION" }, - { 0x1781, "MECANIQUE" }, - { 0x1782, "Spreadtrum Hong Kong Limited" }, - { 0x1783, "Foster Flight, Inc." }, - { 0x1784, "TopSeed Technology Corp." }, - { 0x1785, "CARALLON LIMITED" }, - { 0x1786, "Xeltek Inc." }, - { 0x1787, "TRIDENT SYSTEMS, INC." }, - { 0x1788, "ShenZhen Litkconn Technology Co., Ltd." }, - { 0x1789, "Ascom (Schweiz) AG" }, - { 0x178A, "Prentke Romich Company" }, - { 0x178B, "Panduit Corp." }, - { 0x178C, "URTEK TECHNOLOGIES INC." }, - { 0x178D, "CEIVA Logic, Inc." }, - { 0x178E, "Movimento Group AB" }, - { 0x1790, "Ueda Japan Radio Co., Ltd." }, - { 0x1791, "SYNTHETIC PLANNING INDUSTRY CO., LTD." }, - { 0x1792, "LINK GmbH" }, - { 0x1793, "Heim Systems GmbH" }, - { 0x1794, "MA'AGALIM COMPUTER SYSTEMS Ltd." }, - { 0x1795, "INTEGRATION ASSOCIATES INCORPORATED" }, - { 0x1796, "Printrex, Inc." }, - { 0x1797, "JALCO CO., LTD." }, - { 0x1798, "TYPE TECHNOLOGY INC." }, - { 0x1799, "Thales Norway AS" }, - { 0x179A, "Conrad Electronic GmbH" }, - { 0x179B, "HANDSFULL TECHNOLOGY CORP." }, - { 0x179C, "Net-2Com Corporation" }, - { 0x179D, "Ricavision International Inc." }, - { 0x179E, "Silicon Engines" }, - { 0x179F, "CLIQ LIMITED" }, - { 0x17A0, "Samson Technologies Corp." }, - { 0x17A1, "Taiwan Advanced Sensors Corporation" }, - { 0x17A2, "Vantage Controls, Inc." }, - { 0x17A3, "OnTime tek Inc." }, - { 0x17A4, "Concept 2" }, - { 0x17A5, "Advanced Connection Technology Inc." }, - { 0x17A6, "Astron Clinica Ltd." }, - { 0x17A7, "MICOMSOFT CO., LTD." }, - { 0x17A8, "Kamstrup A/S" }, - { 0x17A9, "MULTIMEDIA GAMES, INC." }, - { 0x17AA, "SETEK Elektronik AB" }, - { 0x17AB, "i-Bulldog Co., Ltd." }, - { 0x17AC, "Dengen Automation Co., Ltd." }, - { 0x17AD, "TRIOC AB" }, - { 0x17AE, "NAD Electronics International/A Div. of Lenbrook Ind." }, - { 0x17AF, "GIGABYTE Communications Inc." }, - { 0x17B0, "Weinmann Geraete fuer Medizen GmbH+Co. KG" }, - { 0x17B1, "ViaSat, Inc." }, - { 0x17B2, "Metec GmbH" }, - { 0x17B3, "Grey Innovation Pty., Ltd." }, - { 0x17B4, "Apres Health & Fitness" }, - { 0x17B5, "Lunatone Industrielle Elektronik GmbH" }, - { 0x17B6, "Hydronix Limited" }, - { 0x17B7, "Sinter Information Corp." }, - { 0x17B8, "Trojan Technologies Private Limited" }, - { 0x17B9, "Green Bit S.p.A." }, - { 0x17BA, "Sauris GmbH" }, - { 0x17BB, "Weihai Dongxing Electronics Co., Ltd." }, - { 0x17BC, "Advanced Peripherals Technologies, Inc." }, - { 0x17BD, "Citron Electronic Co., Ltd." }, - { 0x17BE, "Dongguan Yangming Precision of Plastic Metal Elec Co Lt" }, - { 0x17BF, "Ampere Inc." }, - { 0x17C0, "ED Co., Ltd." }, - { 0x17C1, "Sirius XM Radio" }, - { 0x17C2, "Ingenient Technologies" }, - { 0x17C3, "SGB Group Ltd." }, - { 0x17C4, "VISIOWAVE SA" }, - { 0x17C5, "Hantle System Co., Ltd." }, - { 0x17C6, "Magnetox" }, - { 0x17C7, "AIM Infrarot-Module GmbH" }, - { 0x17C8, "Ringway Tech (JiangSu) Co., Ltd." }, - { 0x17C9, "Andros Incorporated" }, - { 0x17CA, "CyberPak Co." }, - { 0x17CB, "CHINA HUAXU GOLDEN CARD CO., LTD." }, - { 0x17CC, "Native Instruments Software Synthesis GmbH" }, - { 0x17CD, "Basler Electric" }, - { 0x17CE, "Keymile AG" }, - { 0x17CF, "Hip Hing Cable & Plug Mfy. Ltd." }, - { 0x17D0, "Sanford L.P." }, - { 0x17D1, "ViDisys GmbH" }, - { 0x17D2, "Radiometer Medical ApS" }, - { 0x17D3, "Korea Techtron Co., Ltd." }, - { 0x17D4, "Kenetics Innovations Pte. Ltd., Singapore" }, - { 0x17D5, "ImageMap Inc." }, - { 0x17D6, "Samsung Electronics Research Institute" }, - { 0x17D7, "Copley Controls Corp." }, - { 0x17D8, "Rapattoni Corporation" }, - { 0x17D9, "Rasteme Systems Co., Ltd." }, - { 0x17DA, "GEMIT GmbH" }, - { 0x17DB, "CYNOVE" }, - { 0x17DC, "Thermoteknix Systems Ltd." }, - { 0x17DD, "Simply Automated, Incorporated" }, - { 0x17DE, "Grant Instruments" }, - { 0x17DF, "SOUTHWING" }, - { 0x17E0, "Big Sky Laser" }, - { 0x17E1, "ORTHOFIX" }, - { 0x17E2, "PIKAONE" }, - { 0x17E3, "Beck IPC GmbH" }, - { 0x17E4, "OKB SAPR" }, - { 0x17E5, "Memcorp Inc." }, - { 0x17E6, "Quantel Medical" }, - { 0x17E7, "Sirah Laser-und Plasmatechnik GmbH" }, - { 0x17E8, "Visionee S.R.L." }, - { 0x17E9, "DisplayLink (UK) Ltd." }, - { 0x17EA, "Web Technology Corp" }, - { 0x17EB, "Cornice, Inc." }, - { 0x17EC, "Telsource" }, - { 0x17ED, "Sumita Optical Glass, Inc." }, - { 0x17EE, "Personal Media Corporation" }, - { 0x17EF, "Lenovo" }, - { 0x17F0, "Bestronic Industry Co., Ltd." }, - { 0x17F1, "Microjet Technology Co., Ltd." }, - { 0x17F2, "Xmultiple Technologies Inc." }, - { 0x17F3, "Terascala, Inc." }, - { 0x17F4, "AgaMatrix, Inc." }, - { 0x17F5, "K.K. Rocky" }, - { 0x17F6, "Unicomp, Inc" }, - { 0x17F7, "Metroptic Technologies Ltd." }, - { 0x17F8, "Enustech, Inc." }, - { 0x17F9, "GIE Sesam-Vitale" }, - { 0x17FA, "DOSHISHA CORPORATION" }, - { 0x17FB, "Emutec Inc." }, - { 0x17FC, "Vitesse Semiconductor Corp." }, - { 0x17FD, "Formac GmbH" }, - { 0x17FE, "NIPPON PULSE MOTOR CO., LTD." }, - { 0x17FF, "Unication Co., Ltd" }, - { 0x1800, "Shandong Yuanda Net & Multimedia Co., Ltd." }, - { 0x1801, "Southern Data Comm, Inc." }, - { 0x1802, "SYN-TEK Technologies Inc." }, - { 0x1803, "Secutronix" }, - { 0x1804, "Clemens GmbH" }, - { 0x1805, "Digital Peripheral Solutions Inc." }, - { 0x1806, "New Index AS" }, - { 0x1807, "Par-Tech Inc." }, - { 0x1808, "Multiplex Engineering Inc." }, - { 0x1809, "Advantech Co., Ltd." }, - { 0x180A, "Technosystem Co., Ltd." }, - { 0x180B, "Photo Research, Inc." }, - { 0x180C, "Power Digital Card Co., Ltd." }, - { 0x180D, "U3, LLC" }, - { 0x180E, "Audisoft Technologies" }, - { 0x180F, "Phonak Communications AG" }, - { 0x1810, "Wanshih Electronic Co., Ltd." }, - { 0x1811, "Blackspot Interactive Ltd." }, - { 0x1812, "GEWI GmbH" }, - { 0x1813, "HAGIWARA ELECTRIC Co., Ltd." }, - { 0x1814, "Fashionow Co. Ltd." }, - { 0x1815, "Horizon Semiconductors Ltd." }, - { 0x1816, "Directed Electronics" }, - { 0x1817, "Digital Authentication Technologies, Inc." }, - { 0x1818, "Osteosys Co., Ltd." }, - { 0x1819, "Quality Vision International, Inc." }, - { 0x181A, "Fotonation" }, - { 0x181B, "Current Designs, Inc." }, - { 0x181C, "Rensselaer Polytechnic Institute" }, - { 0x181D, "Axon Systems Inc." }, - { 0x181E, "Advanced Tracking Technologies, Inc." }, - { 0x181F, "NAKAJIMA ALL Co., Ltd." }, - { 0x1820, "DSM - Messtechnik GmbH" }, - { 0x1821, "INwireless Co., Ltd" }, - { 0x1822, "DIGIBIO TECHNOLOGY CORP." }, - { 0x1823, "CelleBrite Mobile Synchronization" }, - { 0x1824, "Aval Nagasaki Corp." }, - { 0x1825, "Star-Dundee Ltd." }, - { 0x1826, "Xitron Inc." }, - { 0x1827, "Sanko Electronics Co., Ltd." }, - { 0x1828, "TSR Silicon Resources, Inc." }, - { 0x1829, "Dongguan YuQiu Electronics Co., Ltd." }, - { 0x182A, "Signalion GmbH" }, - { 0x182B, "Chest M.I., Incorporated" }, - { 0x182C, "Caliper LifeSciences" }, - { 0x182D, "Accutron Limited" }, - { 0x182E, "System Instruments Co., Ltd." }, - { 0x182F, "Worldwide Productions Inc." }, - { 0x1830, "I CAP Technologies, Inc." }, - { 0x1831, "Gwo Jinn Industries Co., Ltd." }, - { 0x1832, "Huizhou Shenghua Industrial Co., Ltd." }, - { 0x1833, "Genuine Technologies Co., Ltd." }, - { 0x1834, "SONEL S.A." }, - { 0x1835, "Lust Drivetronics GmbH" }, - { 0x1836, "ePoint Technology" }, - { 0x1837, "Hokuto Denko Corporation" }, - { 0x1838, "Real Networks, Inc." }, - { 0x1839, "AnexTEK Global Inc." }, - { 0x183A, "Mediafour Corporation" }, - { 0x183B, "SIDACON Systemtechnik GmbH" }, - { 0x183C, "Saab AB" }, - { 0x183D, "F3 Inc." }, - { 0x183E, "Robonik India Pvt. Ltd." }, - { 0x183F, "i-BEAD Co., Ltd." }, - { 0x1840, "Cognitive Solutions, Inc." }, - { 0x1841, "SEIKO TIME SYSTEM INC." }, - { 0x1842, "Keen High Technologies (HK) Ltd." }, - { 0x1843, "Vaisala" }, - { 0x1844, "Radiotechnika Marketing Sp.zo.o" }, - { 0x1845, "Cion Technology Corporation" }, - { 0x1846, "microEngineering Labs, Inc." }, - { 0x1847, "Global Payment Technologies, Inc." }, - { 0x1848, "Eurochannels Holding B.V." }, - { 0x1849, "Centurion Systems (Pty) Ltd." }, - { 0x184A, "EB Neuro SPA" }, - { 0x184B, "ARION Technology Inc." }, - { 0x184C, "Centice" }, - { 0x184D, "Dansk Automat Expert A/S" }, - { 0x184E, "SyGade Solutions (Pty) Ltd." }, - { 0x184F, "K2L GmbH" }, - { 0x1850, "Andigilog, Inc." }, - { 0x1851, "ULTRASONIC ENGINEERING CO., LTD." }, - { 0x1852, "Galaxy Far East Corp" }, - { 0x1853, "MITSUBISHI PRECISION CO., LTD." }, - { 0x1854, "Memory Devices Ltd." }, - { 0x1855, "Redpay Secure Payments" }, - { 0x1856, "Imaginova" }, - { 0x1857, "Picosecond Pulse Labs" }, - { 0x1858, "CELLSYSTEM CO., LTD" }, - { 0x1859, "Speech Technology Center, Ltd." }, - { 0x185A, "WinProbe Corporation" }, - { 0x185B, "IG-Development" }, - { 0x185C, "Omnisec AG" }, - { 0x185D, "Origgio Limited" }, - { 0x185E, "Meritech Co., Ltd." }, - { 0x185F, "Stinger Systems Inc." }, - { 0x1860, "HYUPJIN I & C CO, LTD." }, - { 0x1861, "Tech Technology Industrial Company" }, - { 0x1862, "Teridian Semiconductor Corp." }, - { 0x1863, "Wave Technology Co., Ltd." }, - { 0x1864, "Digital Art System" }, - { 0x1865, "Europlex Technologies" }, - { 0x1866, "Union Community Co., Ltd." }, - { 0x1867, "Control Microsystems" }, - { 0x1868, "Index Braille AB" }, - { 0x1869, "RTS Automation GmbH" }, - { 0x186A, "Pivot International, Inc." }, - { 0x186B, "Holophase Incorporated" }, - { 0x186C, "Miyachi Corporation" }, - { 0x186D, "Evermore Innovations" }, - { 0x186E, "Reel Stream LLC" }, - { 0x186F, "Motion Lingo, LLC" }, - { 0x1870, "Nexio Co., Ltd." }, - { 0x1871, "Aveo Technology Corp." }, - { 0x1872, "Cobalt Technologies Co., Ltd." }, - { 0x1873, "Etrovision Technology" }, - { 0x1874, "Nexilion Inc." }, - { 0x1875, "Humo Laboratory, Ltd." }, - { 0x1876, "MG Industrieelektronik GmbH" }, - { 0x1877, "SANEI HYTECHS Co., Ltd." }, - { 0x1878, "Sumitomo Heavy Industries, Ltd." }, - { 0x1879, "Spin Semiconductor Inc." }, - { 0x187A, "Mediachorus Inc." }, - { 0x187B, "Dent Instruments, Inc." }, - { 0x187C, "Alienware Corporation" }, - { 0x187D, "Ardware Ltd." }, - { 0x187E, "Sentelic Corporation" }, - { 0x187F, "Siano Mobile Silicon Ltd." }, - { 0x1880, "Vericon Co., Ltd./Jinn Shyang Precision Industrial Co.," }, - { 0x1881, "Interactive Learning Technologies" }, - { 0x1882, "TransChip Israel Ltd." }, - { 0x1883, "Tanaka S/S Ltd." }, - { 0x1884, "Liyuh Technology Ltd." }, - { 0x1885, "Ascalade Communications Inc." }, - { 0x1886, "Metalink Ltd." }, - { 0x1887, "Fishcamp Engineering" }, - { 0x1888, "Livingston Products, Inc." }, - { 0x1889, "DME Corporation" }, - { 0x188A, "Moeller" }, - { 0x188B, "Showa Electric Laboratory Co., Ltd." }, - { 0x188C, "Epos Development Ltd." }, - { 0x188D, "Across Techno, Inc." }, - { 0x188E, "Neopost Technologies" }, - { 0x188F, "Zefatek Co., Ltd." }, - { 0x1890, "MEDIAN Inc." }, - { 0x1891, "XSENSOR Technology Corp." }, - { 0x1892, "Accuri Instruments, Inc." }, - { 0x1893, "Ginga Software, Inc." }, - { 0x1894, "SyntheSys Research, Inc." }, - { 0x1895, "tesa scribos GmbH" }, - { 0x1896, "Legacy Electronics, Inc." }, - { 0x1897, "Evertop Wire Cable Co." }, - { 0x1898, "Summit Microelectronics" }, - { 0x1899, "Linkiss Co., Ltd." }, - { 0x189A, "Earth Computer Technologies, Inc." }, - { 0x189B, "Trimax Electronics Co., Ltd." }, - { 0x189C, "Walletex Microelectronics Ltd." }, - { 0x189D, "Navionics Inc." }, - { 0x189E, "Net Insight AB" }, - { 0x189F, "3Shape A/S" }, - { 0x18A0, "Kongsberg Maritime AS" }, - { 0x18A1, "Ionwerks, Inc." }, - { 0x18A2, "PSIA Corp." }, - { 0x18A3, "DIGIFRIENDS CO., LTD." }, - { 0x18A4, "CSSN, Inc. dba Card Scanning Solutions" }, - { 0x18A5, "Verbatim Americas LLC" }, - { 0x18A6, "Peripheral Dynamics Inc." }, - { 0x18A7, "Omniprint Inc." }, - { 0x18A8, "Smiths Medical MD" }, - { 0x18A9, "Veri-Tek International" }, - { 0x18AA, "MedRx Inc." }, - { 0x18AB, "Applied Data Systems, Inc." }, - { 0x18AC, "STRATEC Biomedical Systems AG" }, - { 0x18AD, "Invisible Technologies, Inc." }, - { 0x18AE, "MTT Corporation" }, - { 0x18AF, "LN Systems Limited" }, - { 0x18B0, "Mikrodidakt AB" }, - { 0x18B1, "Elmak Ltd." }, - { 0x18B2, "CINTEL FRANCE" }, - { 0x18B3, "RAYDON Corporation" }, - { 0x18B4, "e3C Inc." }, - { 0x18B5, "Klipsch Audio" }, - { 0x18B6, "Mikkon Technology Limited" }, - { 0x18B7, "Zotek Electronic Co., Ltd." }, - { 0x18B8, "Securewave SA" }, - { 0x18B9, "Clixxun GmbH" }, - { 0x18BA, "Bell Fruit Games" }, - { 0x18BB, "G7 Productivity Systems" }, - { 0x18BC, "Muro Co., Ltd" }, - { 0x18BD, "MNBT Co., Ltd." }, - { 0x18BE, "Kingfisher International" }, - { 0x18BF, "Ensyc Technologies" }, - { 0x18C0, "Gatekeeper Systems Inc." }, - { 0x18C1, "Shenzhen SDMC Microelectronics Co., Ltd." }, - { 0x18C2, "AccuSport International, Inc." }, - { 0x18C3, "Elite Semiconductor Memory Technology Inc. (ESMT)" }, - { 0x18C4, "ServerEngines LLC" }, - { 0x18C5, "Corega Taiwan, Inc." }, - { 0x18C6, "Aurora Photonics" }, - { 0x18C7, "Nagano Tectron Co., Ltd" }, - { 0x18C8, "Computerprox Corp." }, - { 0x18C9, "Exfo Electro-Optical Engineering Inc." }, - { 0x18CA, "Canon Korea Business Solutions Inc." }, - { 0x18CB, "Fr. Sauter AG" }, - { 0x18CC, "Osaki Electric Co., Ltd." }, - { 0x18CD, "Pico Instruments LLC" }, - { 0x18CE, "DTC Communications, Inc" }, - { 0x18CF, "Tung Shu Mei Industrial Co., Ltd." }, - { 0x18D0, "Uniform Industrial Corp." }, - { 0x18D1, "Google Inc." }, - { 0x18D2, "Raptor Gaming Technology GmbH" }, - { 0x18D3, "L&V Design" }, - { 0x18D4, "ABI Electronics Ltd." }, - { 0x18D5, "Starline International Group Limited" }, - { 0x18D6, "Ruetz Technologies" }, - { 0x18D7, "New Scale Technologies" }, - { 0x18D8, "Individual Computers" }, - { 0x18D9, "Kaba" }, - { 0x18DA, "Phonol Inc." }, - { 0x18DB, "Compix Incorporated" }, - { 0x18DC, "LKC Technologies, Inc." }, - { 0x18DD, "Docuport WC" }, - { 0x18DE, "Cyto Pulse Sciences, Inc" }, - { 0x18DF, "Cinea Inc." }, - { 0x18E0, "Source Technologies, LLC" }, - { 0x18E1, "Drew Technologies Inc." }, - { 0x18E2, "S.J. Electronics Co., Ltd" }, - { 0x18E3, "Fitilink Integrated Technology, Inc." }, - { 0x18E4, "SB Solutions, Inc" }, - { 0x18E5, "Ablaze Systems LLC" }, - { 0x18E6, "Gobex AS" }, - { 0x18E7, "Truscott Designs" }, - { 0x18E8, "Mondo Systems" }, - { 0x18E9, "Numsite Corporation" }, - { 0x18EA, "Matrox Electronic Systems" }, - { 0x18EB, "nDezign, Inc." }, - { 0x18EC, "Arkmicro Technologies Inc." }, - { 0x18ED, "Tyco Safety Products" }, - { 0x18EE, "Holm Acoustics" }, - { 0x18EF, "ELV Elektronik AG" }, - { 0x18F0, "AVAL DATA CORPORATION" }, - { 0x18F1, "AL Tech, Inc." }, - { 0x18F2, "Rasotto S.N.C." }, - { 0x18F3, "Miglia Technology Ltd." }, - { 0x18F4, "Vtech Engineering Corporation" }, - { 0x18F5, "Esterline Mason" }, - { 0x18F6, "Zermatt Systems Inc" }, - { 0x18F7, "ImageStream Internet Solutions Inc.." }, - { 0x18F8, "Teitsu Denshi Kenkyusho Co., Ltd." }, - { 0x18F9, "EX COMPANY LIMITED" }, - { 0x18FA, "Kuang Ying Computer Equipment Co., Ltd." }, - { 0x18FB, "Scriptel Corporation" }, - { 0x18FC, "Kinyo Co., Ltd." }, - { 0x18FD, "FineArch Inc." }, - { 0x18FE, "SecuriMetrics, Inc." }, - { 0x18FF, "HYUNDAI Digital Technology Co., Ltd." }, - { 0x1900, "Future Wave, Inc." }, - { 0x1901, "GE Healthcare" }, - { 0x1902, "CSIRO Marine & Atmospheric Research" }, - { 0x1903, "ANEX SYSTEM LTD." }, - { 0x1904, "LVI Low Vision International AB" }, - { 0x1905, "EGEMEN Bilgisayar Muh ve San LTD STI" }, - { 0x1906, "Seoro Tech Co., Ltd." }, - { 0x1907, "Elcoteq Design Center Oy" }, - { 0x1908, "APPOTECH LIMITED" }, - { 0x1909, "ABB Inc. Totalflow Division" }, - { 0x190A, "Freewide Inc." }, - { 0x190B, "Metasoft S.C." }, - { 0x190C, "ierise Inc." }, - { 0x190D, "Motorola GSG" }, - { 0x190E, "YAMASA Tokei-Keiki Co, Ltd" }, - { 0x190F, "YA HORNG ELECTRONIC CO., LTD." }, - { 0x1910, "Seriprint-Ziprip UK Limited" }, - { 0x1911, "Nihon Dengyo Kosaku Co., Ltd." }, - { 0x1912, "Yukyung Technologies Co, Ltd" }, - { 0x1913, "Atomynet, Inc." }, - { 0x1914, "Alco Digital Devices Limited" }, - { 0x1915, "Nordic Semiconductor ASA" }, - { 0x1916, "Juniper Systems, Inc." }, - { 0x1917, "Imagetech Corporation" }, - { 0x1918, "NanoSystem Solutions, Inc." }, - { 0x1919, "Pixelworks" }, - { 0x191A, "PATLITE Corporation" }, - { 0x191B, "PICOCEL Co., Ltd." }, - { 0x191C, "Innovative Technology Limited" }, - { 0x191D, "Midtronics, Inc." }, - { 0x191E, "Monsoon Multimedia Inc." }, - { 0x191F, "Venetex Co., Ltd." }, - { 0x1920, "U.S. Digital Television, LLC" }, - { 0x1921, "Interson Corporation" }, - { 0x1922, "Power 7 Technologies Corp." }, - { 0x1923, "FitSense Technology, Inc." }, - { 0x1924, "QnAp iT" }, - { 0x1925, "InnoFaith beauty sciences B.V." }, - { 0x1926, "NextWindow Limited" }, - { 0x1927, "Vulcan Portals Inc." }, - { 0x1928, "PROCEQ SA" }, - { 0x1929, "Wagner Owen Corporation" }, - { 0x192A, "Intek" }, - { 0x192B, "KVH Industries, Inc." }, - { 0x192C, "Twig Com Oy" }, - { 0x192D, "AgileTV" }, - { 0x192E, "Bioanalytical Systems" }, - { 0x192F, "Avago Technologies, Pte." }, - { 0x1930, "Shenzhen Xianhe Technology Co., Ltd." }, - { 0x1931, "Ningbo Broad Telecommunication Co., Ltd." }, - { 0x1932, "Daniels Electronics Ltd." }, - { 0x1933, "TASER INTERNATIONAL INC." }, - { 0x1934, "SAKAI Medical Co., Ltd." }, - { 0x1935, "Elektron Music Machines AB" }, - { 0x1936, "Asaka Riken Co., Ltd" }, - { 0x1937, "Dynjab Technologies Pty. Ltd." }, - { 0x1938, "Meinberg Funkuhren GmbH & Co. KG" }, - { 0x1939, "Hilscher GmbH" }, - { 0x193A, "Lipman Electronic Engineering Ltd." }, - { 0x193B, "Power Monitors, Inc." }, - { 0x193C, "COGELEC" }, - { 0x193D, "MAXIAN Co., Ltd." }, - { 0x193E, "Chestnut Hill Sound Inc." }, - { 0x193F, "OPDICOM PTY LTD" }, - { 0x1940, "U.S. Music Corporation" }, - { 0x1941, "Top Eight Industrial Corp." }, - { 0x1942, "GAMING PARTNERS INTERNATIONAL" }, - { 0x1943, "Sensoray" }, - { 0x1944, "Wegener Communications" }, - { 0x1945, "O-Pen" }, - { 0x1946, "Irisguard UK Ltd" }, - { 0x1947, "Harris Corporation" }, - { 0x1948, "Darlitech International Co., Ltd." }, - { 0x1949, "Lab126" }, - { 0x194A, "Secure Design Institute Co., Ltd." }, - { 0x194B, "Yanago Design Inc." }, - { 0x194C, "Scanivalve Corp." }, - { 0x194D, "Kern AG" }, - { 0x194E, "acam-messelectronic GmbH" }, - { 0x194F, "PreSonus Audio Electronics" }, - { 0x1950, "FUJINON CORPORATION" }, - { 0x1951, "Hyperstone GmbH" }, - { 0x1952, "X-TEMPO DESIGNS LLC" }, - { 0x1953, "Ironkey Inc." }, - { 0x1954, "Radiient Technologies" }, - { 0x1955, "4G Systems GmbH" }, - { 0x1956, "The SmartPill Corporation" }, - { 0x1957, "BIOS Corporation" }, - { 0x1958, "Office Depot, Inc." }, - { 0x1959, "DRS Signal Solutions Inc." }, - { 0x195A, "Technology Link Corporation" }, - { 0x195B, "Huge China Industrial Ltd." }, - { 0x195C, "NewSight" }, - { 0x195D, "Itron Technology Inc." }, - { 0x195E, "Datakey Electronics" }, - { 0x195F, "GODEX INTERNATIONAL CO., LTD." }, - { 0x1960, "Brains Corporation" }, - { 0x1961, "Grupo CD World S.L." }, - { 0x1962, "Vstone Corp." }, - { 0x1963, "IK MULTIMEDIA PRODUCTION srl" }, - { 0x1964, "ID Technica Sales Co., Ltd." }, - { 0x1965, "Uniden Corporation" }, - { 0x1966, "ELESTA GmbH" }, - { 0x1967, "CASIO HITACHI Mobile Communications Co., Ltd." }, - { 0x1968, "Global Silicon Ltd." }, - { 0x1969, "TM-Research, Inc." }, - { 0x196A, "SmartCom" }, - { 0x196B, "Wispro Technology Inc." }, - { 0x196C, "EMKA Technologies" }, - { 0x196D, "InnoDisk Corporation" }, - { 0x196E, "SEI" }, - { 0x196F, "Otoichi Corporation" }, - { 0x1970, "Dane-Elec Corp. USA" }, - { 0x1971, "Real ID Technology Co., Ltd." }, - { 0x1972, "Diagnostic Instruments, Inc." }, - { 0x1973, "SpectraLink Corporation" }, - { 0x1974, "LOSTEAKA, Inc." }, - { 0x1975, "Dongguan Guneetal Wire & Cable Co., Ltd." }, - { 0x1976, "Chipsbrand Microelectronics (HK) Co., Ltd." }, - { 0x1977, "Thales" }, - { 0x1978, "Lismore Instruments Limited" }, - { 0x1979, "Suga Digital Technology Limited" }, - { 0x197A, "Kellendonk Elektronik GmbH" }, - { 0x197B, "Way Systems Inc." }, - { 0x197C, "JSC Videofon MV" }, - { 0x197D, "Leuze electronic GmbH & Co. KG" }, - { 0x197E, "scemtec Transponder Technology GmbH" }, - { 0x197F, "Triton" }, - { 0x1980, "Storage Appliance Corp." }, - { 0x1981, "Matrix Audio Designs Inc." }, - { 0x1982, "Hitel Italia S.P.A." }, - { 0x1983, "Icera Inc." }, - { 0x1984, "Targetti Sankey S.P.A." }, - { 0x1985, "Elmos Co., Ltd." }, - { 0x1986, "Excelitas Technologies Corporation" }, - { 0x1987, "Camille Bauer AG" }, - { 0x1988, "Novar Controls" }, - { 0x1989, "Nuconn Technology Corp." }, - { 0x198A, "MODMEN Co., Ltd." }, - { 0x198B, "Fluid Imaging Technologies, Inc" }, - { 0x198C, "c-scape" }, - { 0x198D, "Fairchild Imaging" }, - { 0x198E, "Ingrid, Inc." }, - { 0x198F, "Beceem Communications Inc." }, - { 0x1990, "Acron Precision Industrial Co., Ltd." }, - { 0x1991, "AAI Corporation" }, - { 0x1992, "Avantes B.V." }, - { 0x1993, "Bluetop Technology Co., Ltd." }, - { 0x1994, "ZMM Ltd." }, - { 0x1995, "Trillium Technology PTY LTD." }, - { 0x1996, "PixeLINK" }, - { 0x1997, "CEFLA S.C.R.L." }, - { 0x1998, "JENOPTIK Laser, Optik, Systeme GmbH" }, - { 0x1999, "iba AG" }, - { 0x199A, "DNA-Technology" }, - { 0x199B, "MicroStrain, Inc." }, - { 0x199C, "Richnex Microelectronics Corporation" }, - { 0x199D, "Dexxon Groupe" }, - { 0x199E, "The Imaging Source Europe GmbH" }, - { 0x199F, "Benica Corporation" }, - { 0x19A0, "Krautkramer Japan Co., Ltd." }, - { 0x19A1, "Zeecraft Tech." }, - { 0x19A2, "SICK AG" }, - { 0x19A3, "ASmobile Communication Inc." }, - { 0x19A4, "Unique Medical Co., Ltd." }, - { 0x19A5, "Harris RF Communication" }, - { 0x19A6, "UBISYS TECHNOLOGIES" }, - { 0x19A7, "SuperTop International Corp." }, - { 0x19A8, "Biforst Technology Inc." }, - { 0x19A9, "Musashi Co., Ltd." }, - { 0x19AA, "musicobo" }, - { 0x19AB, "Bodelin Technologies" }, - { 0x19AC, "Hardworks, Inc." }, - { 0x19AD, "RiTTO GmbH & Co. KG" }, - { 0x19AE, "KeeLog" }, - { 0x19AF, "Innomax Technology Ltd." }, - { 0x19B0, "Sobal Corporation" }, - { 0x19B1, "Kyoritsu Radio Co., Ltd." }, - { 0x19B2, "Batronix Elektronik" }, - { 0x19B3, "SPOTWAVE WIRELESS" }, - { 0x19B4, "CELESTRON" }, - { 0x19B5, "B & W Group" }, - { 0x19B6, "Infotech Logistic, LLC" }, - { 0x19B7, "SK-Electronics Co. Ltd." }, - { 0x19B8, "Control Technology Inc." }, - { 0x19B9, "Drobo, Inc." }, - { 0x19BA, "ebro Electronic GmbH & Co. KG" }, - { 0x19BB, "Informtest" }, - { 0x19BC, "ioLab Systems Inc." }, - { 0x19BD, "Celluon, Inc." }, - { 0x19BE, "Guidance Software, Inc." }, - { 0x19BF, "HASHIMOTO Electronic Industry Co., Ltd." }, - { 0x19C0, "TeraTron GmbH" }, - { 0x19C1, "Digital Info Technology Pte. Ltd." }, - { 0x19C2, "TARGA GmbH" }, - { 0x19C3, "Riskema Informatica e Automacao Ltda." }, - { 0x19C4, "Control Gaging, Inc." }, - { 0x19C5, "Danaher Sensors and Controls" }, - { 0x19C6, "Harmony Microelectronic Inc." }, - { 0x19C7, "WEG Equipamentos Elétricos S.A. - Automação" }, - { 0x19C8, "Secure Key LLC" }, - { 0x19C9, "Electronic Sports" }, - { 0x19CA, "Sandio Technology Corp." }, - { 0x19CB, "EMS (European) LTD." }, - { 0x19CC, "SCIEN Co." }, - { 0x19CD, "D. O. Tel Co., Ltd." }, - { 0x19CE, "SINUS Messtechnik GmbH" }, - { 0x19CF, "Parrot SA" }, - { 0x19D0, "Pan Pacific Enterprise Co., Inc." }, - { 0x19D1, "Channaa" }, - { 0x19D2, "ZTE Corporation" }, - { 0x19D3, "Zucchetti Centro Sistemi SPA" }, - { 0x19D4, "I Bee, K.K." }, - { 0x19D5, "CNB Technology Inc." }, - { 0x19D6, "WIDE Corporation" }, - { 0x19D7, "Unitop New Technology Co., Ltd." }, - { 0x19D8, "Smart Point SA" }, - { 0x19D9, "Fujitsu Ten Limited" }, - { 0x19DA, "MUSE Inc." }, - { 0x19DB, "GeBE Elektronik und Feinwerktechnik GmbH" }, - { 0x19DC, "Communications & Power Industries" }, - { 0x19DD, "NEXVU TECHNOLOGIES, Inc." }, - { 0x19DE, "MITEQ Inc." }, - { 0x19DF, "AlpnaCom" }, - { 0x19E0, "Micro-Nits Co., Ltd." }, - { 0x19E1, "WeiDuan Electronic Accessory (S.Z.) Co., Ltd." }, - { 0x19E2, "Solomon Systech Limited" }, - { 0x19E3, "Bae Systems IEWS" }, - { 0x19E4, "In-Situ Inc." }, - { 0x19E5, "Jetmobile" }, - { 0x19E6, "Apex Digital Inc." }, - { 0x19E7, "Charismathics GmbH" }, - { 0x19E8, "Industrial Technology Research Institute" }, - { 0x19E9, "Bartec Auto ID Ltd." }, - { 0x19EA, "Lung Hwa Electronics Co., Ltd." }, - { 0x19EB, "ACE Antenna, Advanced Technology R&D Team." }, - { 0x19EC, "Forth Dimension Displays Ltd." }, - { 0x19ED, "Plastic Logic Ltd." }, - { 0x19EE, "Modern Marketing Concepts Inc." }, - { 0x19EF, "Pak Heng Technology (Shenzhen) Co., Ltd." }, - { 0x19F0, "Jyh Woei Industrial Co., Ltd." }, - { 0x19F1, "SindoRicoh Co., LTD." }, - { 0x19F2, "INFOMARK Co., Ltd." }, - { 0x19F3, "JAPAN Kyastem Co., Ltd." }, - { 0x19F4, "Malvern Instruments Ltd" }, - { 0x19F5, "Nationz Technologies Inc." }, - { 0x19F6, "J. A. Woollam Co. Inc." }, - { 0x19F7, "Rode Microphones" }, - { 0x19F8, "RoboTech srl" }, - { 0x19F9, "Megadata (Europe) PLC" }, - { 0x19FA, "SHENZHEN GAMEWARE ELECTRONIC CO., LTD." }, - { 0x19FB, "VLSI Solution Oy" }, - { 0x19FC, "BioControl A/S" }, - { 0x19FD, "MTI Instruments" }, - { 0x19FE, "Micromap Corporation" }, - { 0x19FF, "Best Buy China Ltd." }, - { 0x1A00, "Polymax Precision Industry Co., Ltd." }, - { 0x1A01, "Siemens Power Transmission & Dist. Energy Automation" }, - { 0x1A02, "DLoG GmbH" }, - { 0x1A03, "HORIBA ITECH Co., Ltd." }, - { 0x1A04, "ASTRO MACHINE CORP." }, - { 0x1A05, "Media Lab., Inc" }, - { 0x1A06, "Beijing Deng Hong Technology Co., Ltd." }, - { 0x1A07, "HID" }, - { 0x1A08, "Bellwood International, Inc." }, - { 0x1A09, "DILANO GmbH" }, - { 0x1A0B, "Teleste OYJ" }, - { 0x1A0C, "Sunkorea Electronics Co., Ltd." }, - { 0x1A0D, "Ladybug Technologies LLC" }, - { 0x1A0E, "Sasse Elektronik GmbH" }, - { 0x1A0F, "HT-ITALIA" }, - { 0x1A10, "KWANG SUNG ELECTRONICS H.K. Co., Ltd." }, - { 0x1A11, "eMDee Technology, Inc." }, - { 0x1A12, "KES Co., Ltd." }, - { 0x1A13, "Plasmon" }, - { 0x1A14, "Brainvision Inc." }, - { 0x1A15, "Amphenol-Tuchel Electronics GmbH" }, - { 0x1A16, "General Dynamics" }, - { 0x1A17, "Oticon A/S" }, - { 0x1A18, "Quadzilla Performance Technologies, Inc." }, - { 0x1A19, "DDTIC Corporation Ltd." }, - { 0x1A1A, "ASIACORP INTERNATIONAL LTD." }, - { 0x1A1B, "Fischer-Zoth GmbH" }, - { 0x1A1C, "Mercury Computer Systems AG" }, - { 0x1A1D, "Syncomm Technology Corp." }, - { 0x1A1E, "Dekart s.r.l." }, - { 0x1A1F, "Ikanos Communications Inc." }, - { 0x1A20, "Mind Logic Co., Ltd." }, - { 0x1A21, "ASITEQ Co., Ltd." }, - { 0x1A22, "Kenwin Industrial (HK) Ltd." }, - { 0x1A23, "Hangzhou YiHeng Technologies Co., Ltd." }, - { 0x1A24, "Beyondwiz Co., Ltd." }, - { 0x1A25, "Amphenol East Asia Ltd." }, - { 0x1A26, "APSI (Asia Pacific Satellite Industry)" }, - { 0x1A27, "Senior Technologies" }, - { 0x1A28, "NOVITUS SA" }, - { 0x1A29, "ABOV Semiconductor Co., Ltd." }, - { 0x1A2A, "Seagate Branded Solutions" }, - { 0x1A2B, "NTI Corporation" }, - { 0x1A2C, "Wuxi China Resources Semico Co., Ltd." }, - { 0x1A2D, "WEBSYNC Co., Ltd." }, - { 0x1A2E, "Lanner Electronics Inc." }, - { 0x1A2F, "Tetradyne Software Inc." }, - { 0x1A30, "New Media Life" }, - { 0x1A31, "SPEX SamplePrep, LLC" }, - { 0x1A32, "Verint Video Technology GmbH" }, - { 0x1A33, "Schmid & Partner Engineering AG" }, - { 0x1A34, "King Chuang Tech & Electronic Co., Ltd." }, - { 0x1A35, "Artesyn Technologies Inc." }, - { 0x1A36, "Topdisk Technology Limited" }, - { 0x1A37, "Stayhealthy Inc." }, - { 0x1A38, "Nemo-Q International AB" }, - { 0x1A39, "GBC Scientific Equipment" }, - { 0x1A3A, "Laerdal Medical AS" }, - { 0x1A3B, "South Mountain Technologies, Ltd." }, - { 0x1A3C, "New Image Co., Ltd." }, - { 0x1A3D, "ELGA LabWater (VWS UK LTD)" }, - { 0x1A3E, "INTEVAC" }, - { 0x1A3F, "Hokkei Industries Co., Ltd." }, - { 0x1A40, "TERMINUS TECHNOLOGY INC." }, - { 0x1A41, "Action Electronics Co., Ltd." }, - { 0x1A42, "CROSSLINK GmbH" }, - { 0x1A43, "JTEKT CORPORATION" }, - { 0x1A44, "VASCO Data Security NV" }, - { 0x1A45, "Wavelength Electronics Inc." }, - { 0x1A46, "JAVAD GNSS, Inc." }, - { 0x1A47, "iQBio, Inc." }, - { 0x1A48, "KYOHRITSU ELECTRONIC INDUSTRY Co., Ltd." }, - { 0x1A49, "TOKYO SEIMITSU CO., LTD." }, - { 0x1A4A, "Silicon Image" }, - { 0x1A4B, "SafeBoot International B.V." }, - { 0x1A4C, "PMC" }, - { 0x1A4D, "N-CRYPT, Inc." }, - { 0x1A4E, "SIMS Corp." }, - { 0x1A4F, "Haliplex PTY Ltd." }, - { 0x1A50, "Mechatro Inc." }, - { 0x1A51, "FRWD Technologies Ltd." }, - { 0x1A52, "MediaPhy Corporation" }, - { 0x1A53, "SANDBOX Co., Ltd" }, - { 0x1A54, "Oestling Markiersysteme GmbH" }, - { 0x1A55, "Raytheon Systems Limited" }, - { 0x1A56, "East Port Technology Co., Ltd." }, - { 0x1A57, "ARESIS d.o.o." }, - { 0x1A58, "Miranda Technologies Inc." }, - { 0x1A59, "HAAG-STREIT AG" }, - { 0x1A5A, "Tandberg Data" }, - { 0x1A5B, "Entner Electronics KEG" }, - { 0x1A5C, "Arkino Corporation Limited" }, - { 0x1A5D, "Daikin Denshi Kogyo Co., Ltd." }, - { 0x1A5E, "Edixia" }, - { 0x1A5F, "Sonatest Limited" }, - { 0x1A60, "Joytoto Co., Ltd." }, - { 0x1A61, "Abbott Diabetes Care" }, - { 0x1A62, "DAT H.K. LIMITED" }, - { 0x1A63, "Canfield Scientific, Inc." }, - { 0x1A64, "MASTERVOLT INTERNATIONAL" }, - { 0x1A65, "ELEKTRINA d.o.o., podjetje za razvoj elektronike" }, - { 0x1A66, "Andatek Technology, Ltd." }, - { 0x1A67, "Privaris" }, - { 0x1A68, "Double Top Technology Ltd." }, - { 0x1A69, "Kalon Semiconductor, Inc." }, - { 0x1A6A, "Cypress Semiconductor GmbH" }, - { 0x1A6B, "Taiwin Electronics Co., Ltd." }, - { 0x1A6C, "Hivion Co., Ltd." }, - { 0x1A6D, "SamYoung Electronics Co., Ltd" }, - { 0x1A6E, "Global Unichip Corp." }, - { 0x1A6F, "Sagem Orga GmbH" }, - { 0x1A70, "Items Technology Co., Ltd." }, - { 0x1A71, "SEIDEL Elektronik GmbH Nfg. KG" }, - { 0x1A72, "Physik Instrumente (PI) GmbH & Co. KG" }, - { 0x1A73, "Huntron Inc." }, - { 0x1A74, "Oberthur Technologies" }, - { 0x1A75, "Nautilus Hyosung" }, - { 0x1A76, "JADAK Technologies, Inc." }, - { 0x1A77, "American Master Import 26, Inc." }, - { 0x1A78, "AirLink Communications, Inc." }, - { 0x1A79, "Ascensia Diabetes Care" }, - { 0x1A7A, "Softron Co., Ltd." }, - { 0x1A7B, "Lumberg Connect GmbH" }, - { 0x1A7C, "Evoluent LLC" }, - { 0x1A7D, "Systex Corporation" }, - { 0x1A7E, "MELTEC Systementwicklung" }, - { 0x1A7F, "SSD COMPANY LIMITED" }, - { 0x1A80, "Zhong Ming Wire Cable Technology (Xiamen) Co., Ltd." }, - { 0x1A81, "G.Tech Technology Ltd." }, - { 0x1A82, "Proconn Technology Co., Ltd." }, - { 0x1A83, "Socle Technology Corp." }, - { 0x1A84, "COBB Tuning, Inc." }, - { 0x1A85, "Southwest Research Institute" }, - { 0x1A86, "Nanjing Qinherg Electronics Co., Ltd." }, - { 0x1A87, "TechLab 2000 Ltd. Co., Sp Zo.o." }, - { 0x1A88, "WowWee Limited" }, - { 0x1A89, "Dynalith Systems Co., Ltd." }, - { 0x1A8A, "Simula Technology Inc." }, - { 0x1A8B, "SGS Taiwan Ltd." }, - { 0x1A8C, "MagicEyes Digital Co., Ltd" }, - { 0x1A8D, "BandRich Inc." }, - { 0x1A8E, "XiTRON Technologies" }, - { 0x1A8F, "Harman Becker Automotive Systems, GmbH" }, - { 0x1A90, "Resource Data Management" }, - { 0x1A91, "GEOMC Co., Ltd." }, - { 0x1A92, "Berkash Enterprise" }, - { 0x1A93, "Promotional Technologies International Corp." }, - { 0x1A94, "STWTECH Co., Ltd." }, - { 0x1A95, "Sextant Labs, Inc." }, - { 0x1A96, "Harman Becker Automotive Systems, Inc." }, - { 0x1A97, "XM Satellite Radio Inc." }, - { 0x1A98, "Leica Camera AG" }, - { 0x1A99, "Asia Tai Technology (Dongguan) Co., Ltd." }, - { 0x1A9A, "Verari Systems, Inc." }, - { 0x1A9B, "Balboa Instruments" }, - { 0x1A9C, "Inomed Medizintechnik GmbH" }, - { 0x1A9D, "TrafficSim Co., Ltd." }, - { 0x1A9E, "Epicenter, Inc." }, - { 0x1A9F, "Hysitron Incorporated" }, - { 0x1AA0, "Auto Enginuity, L.L.C." }, - { 0x1AA1, "Vestax Corporation" }, - { 0x1AA2, "ORIENTAL MOTOR CO., LTD." }, - { 0x1AA3, "ZOLL Medical Corporation" }, - { 0x1AA4, "Data Drive Thru, Inc." }, - { 0x1AA5, "UBeacon Technologies, Inc." }, - { 0x1AA6, "eFortune Technology Corp." }, - { 0x1AA7, "SiliconSystems, Inc." }, - { 0x1AA8, "Waves Audio Ltd." }, - { 0x1AA9, "Home Phone Tunes Inc." }, - { 0x1AAA, "Taylor Associates/Communications, Inc." }, - { 0x1AAB, "SilverCreations Software AG" }, - { 0x1AAC, "Witschi Electronic AG" }, - { 0x1AAD, "KeeTouch Electronic Co., Ltd." }, - { 0x1AAE, "Johnson Component & Equipments Co., Ltd." }, - { 0x1AAF, "Intellectual Property Library Company" }, - { 0x1AB0, "DAEWOO ELECTRONIC COMPONENTS CO., LTD." }, - { 0x1AB1, "Rigol Technologies, Inc." }, - { 0x1AB2, "Allied Vision Technologies GmbH" }, - { 0x1AB3, "M and C System" }, - { 0x1AB4, "Japan Remote Control Co., Ltd." }, - { 0x1AB5, "Hamamatsu TOA Electronics, Inc." }, - { 0x1AB6, "Integrated Technology Corp." }, - { 0x1AB7, "GLOBAL VR, Inc." }, - { 0x1AB8, "Pen Laboratory Inc." }, - { 0x1AB9, "Nomadio Inc." }, - { 0x1ABA, "Kenton Electronics Limited" }, - { 0x1ABB, "Airo Wireless Media Inc." }, - { 0x1ABC, "Fuji Photo Film USA" }, - { 0x1ABD, "PERTO S.A." }, - { 0x1ABE, "MP3Car.com Inc" }, - { 0x1ABF, "ANIMA Corporation" }, - { 0x1AC0, "SOKKIA Co., Ltd." }, - { 0x1AC1, "LIANHE TECHNOLOGIES, INC." }, - { 0x1AC2, "DESKO GmbH" }, - { 0x1AC3, "DISK KING Technology Co., Ltd." }, - { 0x1AC4, "CAO Group, Inc." }, - { 0x1AC5, "Electronic Engineering Solutions S.L." }, - { 0x1AC6, "JAPAN ADE LTD." }, - { 0x1AC7, "Modular Communication Systems, Inc." }, - { 0x1AC8, "Toyota Industries Corporation" }, - { 0x1AC9, "Broadxent Pte. Ltd." }, - { 0x1ACA, "Bluebird Soft Inc." }, - { 0x1ACB, "Salcomp Plc" }, - { 0x1ACC, "Ta Horng Musical Instrument Co., Ltd." }, - { 0x1ACD, "MKS Instruments" }, - { 0x1ACE, "Temento Systems" }, - { 0x1ACF, "International Manufacturing & Engineering Services Co." }, - { 0x1AD0, "Cygnetron, Inc." }, - { 0x1AD1, "Desan Wire Co., Ltd." }, - { 0x1AD2, "Mesa Imaging AG" }, - { 0x1AD3, "Advanced Technetix, Inc." }, - { 0x1AD4, "Advanced Printing Systems" }, - { 0x1AD5, "Gentec-EO" }, - { 0x1AD6, "General Dynamics SATCOM Technologies, State College Fac" }, - { 0x1AD7, "A.B.O. Co., Ltd." }, - { 0x1AD8, "Motion Control i Västerås AB" }, - { 0x1AD9, "Rocket Gaming Systems" }, - { 0x1ADA, "VEGA Grieshaber KG" }, - { 0x1ADB, "Schweitzer Engineering Laboratories" }, - { 0x1ADC, "Turbolinux, Inc." }, - { 0x1ADD, "Marshall Electronics, Inc." }, - { 0x1ADE, "SpinMaster Ltd." }, - { 0x1ADF, "digital design GmbH" }, - { 0x1AE0, "Axiomatic Technologies Corp." }, - { 0x1AE1, "Hoffman Engineering" }, - { 0x1AE2, "A-JET Technology Co., LTD." }, - { 0x1AE3, "Chung Young Digital Corp., Ltd." }, - { 0x1AE4, "ic-design Reinhard Gottinger GmbH" }, - { 0x1AE5, "Jianduan Technology (Shenzhen) Co., Ltd" }, - { 0x1AE6, "JOA Telecom Co., Ltd." }, - { 0x1AE7, "Joellenbeck GmbH" }, - { 0x1AE8, "Myway Labs Co., Ltd." }, - { 0x1AE9, "arnotec GmbH" }, - { 0x1AEA, "Mobilygen Corporation" }, - { 0x1AEB, "NIHON UNICA CORPORATION" }, - { 0x1AEC, "PORTEK TECHNOLOGY CORPORATION" }, - { 0x1AED, "High Top Precision Electronic Co., Ltd." }, - { 0x1AEE, "SHEN ZHEN REX TECHNOLOGY CO., LTD." }, - { 0x1AEF, "Octekconn Incorporation" }, - { 0x1AF0, "SuperPix Micro Technology Limited" }, - { 0x1AF1, "Connect One, Ltd." }, - { 0x1AF2, "AXSionics AG" }, - { 0x1AF3, "Smarthome Technology Limited" }, - { 0x1AF4, "NCS Pearson, Inc." }, - { 0x1AF5, "Arima Communications Corp." }, - { 0x1AF6, "SL International Ltd." }, - { 0x1AF7, "GRAPHIN CO., LTD." }, - { 0x1AF8, "JS-ROBOTICS" }, - { 0x1AF9, "Alvarion Ltd." }, - { 0x1AFA, "Mobinnova Corp." }, - { 0x1AFB, "Kirche Jesu Christi der Heiligen der Letzten Tage" }, - { 0x1AFC, "Blue Orb" }, - { 0x1AFD, "FarSite Communications Limited" }, - { 0x1AFE, "A. Eberle GmbH & Co. KG" }, - { 0x1AFF, "Defibtech, LLC" }, - { 0x1B00, "Uster Technologies, Inc." }, - { 0x1B01, "ETA Chips, Co." }, - { 0x1B02, "MEN Mikro Elektronik GmbH" }, - { 0x1B03, "Moog Japan Ltd." }, - { 0x1B04, "MEILHAUS Electronic GmbH" }, - { 0x1B05, "Cracol Developments Ltd." }, - { 0x1B06, "OPGAL" }, - { 0x1B07, "WEY Technology AG" }, - { 0x1B08, "Actimo Inc." }, - { 0x1B09, "MISUZU INDUSTRIES CORPORATION" }, - { 0x1B0A, "Sense Technology Inc." }, - { 0x1B0B, "Lambda Systems Inc." }, - { 0x1B0C, "MYTECS Co., Ltd." }, - { 0x1B0D, "SmarDTV" }, - { 0x1B0E, "BLUTRONICS S.R.L." }, - { 0x1B0F, "EKS-ELEKTRONIKSERVICE GmbH" }, - { 0x1B10, "KAGA COMPONENTS CO., LTD." }, - { 0x1B11, "OneClick Technologies Ltd." }, - { 0x1B12, "Eventide, Inc." }, - { 0x1B13, "Neuf Cegetel" }, - { 0x1B14, "Ergotron, Inc." }, - { 0x1B15, "i3micro technology ab" }, - { 0x1B16, "LinTech GmbH Berlin" }, - { 0x1B17, "SHENZHEN e-loam Technology Co., Ltd." }, - { 0x1B18, "Mikrolab Entwicklungsgesellschaft fur Elektroniksysteme" }, - { 0x1B19, "RADA Electronic Industries Ltd." }, - { 0x1B1A, "Tianjin China-Silicon Microelectronics Co., Ltd." }, - { 0x1B1B, "Shenzhen MD Electric Co., Ltd." }, - { 0x1B1C, "CORSAIR MEMORY INC." }, - { 0x1B1D, "Torian Wireless Ltd." }, - { 0x1B1E, "General Imaging Company" }, - { 0x1B1F, "eQ-3 Entwicklung GmbH" }, - { 0x1B20, "MStar Semiconductor, Inc." }, - { 0x1B21, "XenICs nv" }, - { 0x1B22, "WiLinx Corp." }, - { 0x1B23, "Skyray Instrument Co., Ltd." }, - { 0x1B24, "Telegent Systems Inc." }, - { 0x1B25, "ALE" }, - { 0x1B26, "Plug Power" }, - { 0x1B27, "Current Electronics Inc." }, - { 0x1B28, "NAVIsis Inc." }, - { 0x1B29, "Industrie Dial Face S.p.A." }, - { 0x1B2A, "MICRO EMISSION CO., LTD." }, - { 0x1B2B, "Neural Image Co., Ltd." }, - { 0x1B2C, "Advanced Thermal Solutions, Inc." }, - { 0x1B2D, "Photon Inc." }, - { 0x1B2E, "ETANI ELECTRONICS CO., LTD." }, - { 0x1B2F, "Ihara Electronic Industries Co.,Ltd." }, - { 0x1B30, "STZ QSBV Ilmenau" }, - { 0x1B31, "Renu Electronics Pvt. Ltd." }, - { 0x1B32, "Ugobe, Inc." }, - { 0x1B33, "3DV Systems Ltd." }, - { 0x1B34, "EyeTalk Systems, Inc." }, - { 0x1B35, "Paradigm Electronics Inc." }, - { 0x1B36, "ViXS Systems, Inc." }, - { 0x1B37, "Savant Systems, LLC" }, - { 0x1B38, "ALBAHITH TECHNOLOGIES" }, - { 0x1B39, "ViaMichelin SAS" }, - { 0x1B3A, "JUMO GmbH & Co. KG" }, - { 0x1B3B, "iPassion Technology Inc." }, - { 0x1B3C, "DEVI A/S" }, - { 0x1B3D, "Matrix Orbital" }, - { 0x1B3E, "STIL SA" }, - { 0x1B3F, "Generalplus Technology Inc." }, - { 0x1B40, "AISIN SEIKI CO., LTD." }, - { 0x1B41, "Fujitsu Australia Limited" }, - { 0x1B42, "Cardinal Scale Manufacturing Company" }, - { 0x1B43, "Extron Design Services" }, - { 0x1B44, "Elite Co., Ltd." }, - { 0x1B45, "Cyan Technology Ltd." }, - { 0x1B46, "Holylite Microelectronics Corp." }, - { 0x1B47, "Energizer Holdings, Inc." }, - { 0x1B48, "Plastron Precision Co., Ltd." }, - { 0x1B49, "Applied Printed Electronics Research, LLC" }, - { 0x1B4A, "Gem-Med, S.L." }, - { 0x1B4B, "Watson Marlow Ltd." }, - { 0x1B4C, "Unitron Group" }, - { 0x1B4D, "Objet Geometries Ltd." }, - { 0x1B4E, "ELPRO-BUCHS AG" }, - { 0x1B4F, "Spark Fun Electronics" }, - { 0x1B50, "DictaNet Software AG" }, - { 0x1B51, "Kundisch GmbH & Co. KG" }, - { 0x1B52, "A.R. Hungary, Inc." }, - { 0x1B53, "DANI Instruments S.p.A." }, - { 0x1B54, "COMMIT Incorporated" }, - { 0x1B55, "ZKSoftware Inc." }, - { 0x1B56, "V.I.O., Inc." }, - { 0x1B57, "ATREE Inc." }, - { 0x1B58, "Sumitomo Elec Ind Ltd. Lightwave Network Products Div." }, - { 0x1B59, "K.S. Terminals Inc." }, - { 0x1B5A, "Chao Zhou Kai Yuan Electric Co., Ltd." }, - { 0x1B5B, "Homoth Medizinelektronik" }, - { 0x1B5C, "ICP DAS Co., Ltd." }, - { 0x1B5D, "MV Circuit Design, Inc." }, - { 0x1B5E, "General Engine Management Systems Ltd." }, - { 0x1B5F, "Wayne Dalton Corp." }, - { 0x1B60, "NanoDrop Technologies, Inc." }, - { 0x1B61, "n-Trance Security Ltd." }, - { 0x1B62, "Shenzhen Aoni Electronic Industry Co., Ltd." }, - { 0x1B63, "Seedsware Corporation" }, - { 0x1B64, "C.G. Development Ltd." }, - { 0x1B65, "The Hong Kong Standards and Testing Centre Ltd." }, - { 0x1B66, "Bontempi-Farfisa Sigma S.p.A." }, - { 0x1B67, "Toradex AG" }, - { 0x1B68, "ZAFENA AB" }, - { 0x1B69, "KLA-Tencor" }, - { 0x1B6A, "HIKARI Co., Ltd." }, - { 0x1B6B, "Modiotek Co., Ltd." }, - { 0x1B6C, "Techno Veins Co., Ltd." }, - { 0x1B6D, "IDpendant GmbH" }, - { 0x1B6E, "HS Automatic ApS" }, - { 0x1B6F, "Federal Signal Vama S.A." }, - { 0x1B70, "Minicom Advanced Systems" }, - { 0x1B71, "Huizhou 10Moons Technology Development Co., Ltd." }, - { 0x1B72, "ATERGI TECHNOLOGY CO., LTD." }, - { 0x1B73, "Vehicle Camera Systems Ltd" }, - { 0x1B74, "MODAFUN, Inc." }, - { 0x1B75, "OvisLink Corp." }, - { 0x1B76, "Legend Silicon Corp." }, - { 0x1B77, "Protec, Inc." }, - { 0x1B78, "LOGICPACK CO., LTD." }, - { 0x1B79, "WingsTek, Inc." }, - { 0x1B7A, "Electrox" }, - { 0x1B7B, "Ingersoll Rand Co." }, - { 0x1B7C, "io Corporation" }, - { 0x1B7D, "SUNGIL TELECOM" }, - { 0x1B7E, "Lutron Electronics Inc." }, - { 0x1B7F, "EMC Corporation" }, - { 0x1B80, "KWorld Computer Co., Ltd." }, - { 0x1B81, "Kratos Analytical Ltd." }, - { 0x1B82, "Mcube Technology Co., Ltd." }, - { 0x1B83, "Megatone systems and Technologies LTD." }, - { 0x1B84, "WALTHER Data GmbH Scan-Solutions" }, - { 0x1B85, "INNOVA S.A." }, - { 0x1B86, "Dongguan Guanshang Electronics Co., Ltd." }, - { 0x1B87, "Davis Instruments" }, - { 0x1B88, "ShenMing Electron (Dong Guan) Co., Ltd." }, - { 0x1B89, "iCache, Incorporated" }, - { 0x1B8A, "Quellan, Inc." }, - { 0x1B8B, "PROCES-DATA A/S" }, - { 0x1B8C, "Altium Limited" }, - { 0x1B8D, "e-MOVE Technology Co., Ltd." }, - { 0x1B8E, "Amlogic, Inc." }, - { 0x1B8F, "Super Talent Technology, Inc." }, - { 0x1B90, "Deep Sea Electronics Plc" }, - { 0x1B91, "Zicplay SA" }, - { 0x1B92, "Trysys Co., Ltd." }, - { 0x1B93, "Phoenix Contact GmbH & Co. KG" }, - { 0x1B94, "Yoggie Security Systems" }, - { 0x1B95, "EVC electronic GmbH" }, - { 0x1B96, "N-Trig" }, - { 0x1B97, "Metronix GmbH" }, - { 0x1B98, "YMax Communications Corp." }, - { 0x1B99, "Shenzhen Yuanchuan Electronic" }, - { 0x1B9A, "Applied Vision Systems Corporation" }, - { 0x1B9B, "Microtrac, Inc." }, - { 0x1B9C, "Maki Manufacturing Co., Ltd." }, - { 0x1B9D, "Sigma Instruments, Inc." }, - { 0x1B9E, "ARCoptix S.A" }, - { 0x1B9F, "GHI Electronics, LLC" }, - { 0x1BA0, "Jiangmen Kong Yue Jolimark Information Technology Ltd." }, - { 0x1BA1, "JINQ CHERN ENTERPRISE CO., LTD." }, - { 0x1BA2, "Lite Metals & Plastic (Shenzhen) Co., Ltd." }, - { 0x1BA3, "EmbeddedFusion Ltd." }, - { 0x1BA4, "Ember Corporation" }, - { 0x1BA5, "Futiro" }, - { 0x1BA6, "Abilis Systems" }, - { 0x1BA7, "Xantech Corporation" }, - { 0x1BA8, "China Telecommunication Technology Labs" }, - { 0x1BA9, "Renau Electronic Laboratories" }, - { 0x1BAA, "Transcell Technology, Inc." }, - { 0x1BAB, "MATT R.P.Traczynscy Sp.J." }, - { 0x1BAC, "Bernecker + Rainer Industrie-Elektronik Ges.m.b.H." }, - { 0x1BAD, "Harmonix Music Systems, Inc." }, - { 0x1BAE, "Vuzix Corporation" }, - { 0x1BAF, "NIIGATA SEIMITSU CO., LTD." }, - { 0x1BB0, "LBS PLUS Co., Ltd." }, - { 0x1BB1, "Commodore International Corporation" }, - { 0x1BB2, "G.T. trading Srl" }, - { 0x1BB3, "Holzworth Instrumentation LLC" }, - { 0x1BB4, "Satmap Systems Ltd." }, - { 0x1BB5, "SEF Roboter GmbH" }, - { 0x1BB6, "PdMA Corporation" }, - { 0x1BB7, "DGT Sp. z o.o." }, - { 0x1BB8, "MIZOUE PROJECT JAPAN Corporation" }, - { 0x1BB9, "Qpixel Technology, Inc." }, - { 0x1BBA, "Medicomp, Inc." }, - { 0x1BBB, "TCL Communication Ltd" }, - { 0x1BBC, "KATHREIN-Werke KG" }, - { 0x1BBD, "Videology Imaging Solutions, Inc." }, - { 0x1BBE, "CE+T s.a." }, - { 0x1BBF, "Littfinski DatenTechnik (LDT)" }, - { 0x1BC0, "Senselock Software Technology Co.,Ltd" }, - { 0x1BC1, "ACE ELECTRONIQUE" }, - { 0x1BC2, "SEW-EURODRIVE GmbH & Co. KG" }, - { 0x1BC3, "Fujian START Computer Equipment Co., Ltd." }, - { 0x1BC4, "Ford Motor Co." }, - { 0x1BC5, "AVIXE Technology (China) Ltd." }, - { 0x1BC6, "Yurex, Inc." }, - { 0x1BC7, "Telit Wireless Solutions" }, - { 0x1BC8, "MDS Technology Co., Ltd." }, - { 0x1BC9, "Alti-2 Inc." }, - { 0x1BCA, "Ishii Hyoki Co., Ltd." }, - { 0x1BCB, "Cubic Defence NZ Limited" }, - { 0x1BCC, "TopScan Ltd." }, - { 0x1BCD, "AZKOYEN" }, - { 0x1BCE, "Contac Cable Industrial Limited" }, - { 0x1BCF, "Sunplus Innovation Technology Inc." }, - { 0x1BD0, "Hangzhou Riyue Electronics Co., Ltd." }, - { 0x1BD1, "Companion Worlds, Inc." }, - { 0x1BD2, "Beijing G & D Card Systems Co., Ltd." }, - { 0x1BD3, "3layer Engineering" }, - { 0x1BD4, "FastVDO Inc." }, - { 0x1BD5, "BG Systems, Inc." }, - { 0x1BD6, "Lodam electronics" }, - { 0x1BD7, "TouchNetworks, Inc." }, - { 0x1BD8, "Image Computer Systems Limited" }, - { 0x1BD9, "Emerson" }, - { 0x1BDA, "University of Southampton" }, - { 0x1BDB, "Spectral Applied Research" }, - { 0x1BDC, "Slacker" }, - { 0x1BDD, "QiGO Inc" }, - { 0x1BDE, "P-TWO INDUSTRIES, INC." }, - { 0x1BDF, "Electrone Americas Ltd., Co." }, - { 0x1BE0, "Analog Devices, Inc. - Test Technology Group" }, - { 0x1BE1, "LG-Ericsson Co., Ltd" }, - { 0x1BE2, "Shenzhen Fametech Electronic Co., Ltd." }, - { 0x1BE3, "WAGO Kontakttechnik GmbH & Co. KG" }, - { 0x1BE4, "Integrated Digital Technologies, Inc. (IDTI)" }, - { 0x1BE5, "NetLogic Microsystems" }, - { 0x1BE6, "NAVENTO TECHNOLOGIES" }, - { 0x1BE7, "CPR Tools, Inc." }, - { 0x1BE8, "MEDAV GmbH" }, - { 0x1BE9, "CONCH ELECTRONIC CO., LTD." }, - { 0x1BEA, "ATTO Corporation" }, - { 0x1BEB, "HOYA CANDEO OPTRONICS CORPORATION" }, - { 0x1BEC, "isMedia Co., Ltd." }, - { 0x1BED, "OPT Corporation" }, - { 0x1BEE, "KCI Medical Products (UK) Ltd." }, - { 0x1BEF, "Shenzhen Tongyuan Network-Communication Cables Co., Ltd" }, - { 0x1BF0, "RealVision Inc." }, - { 0x1BF1, "HENGSTLER" }, - { 0x1BF2, "Newport Media, Inc." }, - { 0x1BF3, "WAVES SYSTEM / SONAMIX" }, - { 0x1BF4, "ABB / Drives" }, - { 0x1BF5, "Extranet Systems Inc." }, - { 0x1BF6, "Orient Semiconductor Electronics, Ltd." }, - { 0x1BF7, "Axiotron, Inc." }, - { 0x1BF8, "Game Mechanisms LLC" }, - { 0x1BF9, "TRACTEL SAS" }, - { 0x1BFA, "METROLAB TECHNOLOGY SA" }, - { 0x1BFB, "ALLIED PANELS" }, - { 0x1BFC, "Guidance Interactive Healthcare" }, - { 0x1BFD, "RISINTECH INC." }, - { 0x1BFE, "SEOHWA TELECOM Co., LTD." }, - { 0x1BFF, "IonOptix Corp." }, - { 0x1C00, "prodaSafe GmbH" }, - { 0x1C01, "No Climb Products Ltd." }, - { 0x1C02, "Kreton Corporation" }, - { 0x1C03, "DDL CO., LTD." }, - { 0x1C04, "QNAP System Inc." }, - { 0x1C05, "Rockwell Collins" }, - { 0x1C06, "SeekTech, Inc." }, - { 0x1C07, "CEntrance, Inc." }, - { 0x1C08, "Arcus-EDS GmbH" }, - { 0x1C09, "RAMTEX Engineering ApS" }, - { 0x1C0A, "MaxRise Inc." }, - { 0x1C0B, "Kato Tech Co., Ltd." }, - { 0x1C0C, "Ionics EMS Inc." }, - { 0x1C0D, "Relm Wireless" }, - { 0x1C0E, "Qstik plc" }, - { 0x1C0F, "NEOTECHKNO" }, - { 0x1C10, "Lanterra Industrial Co., Ltd." }, - { 0x1C11, "UNIMTEC Co., Ltd." }, - { 0x1C12, "CONITEC DATENSYSTEME GmbH" }, - { 0x1C13, "ALECTRONIC LIMITED" }, - { 0x1C14, "SENSITIVE OBJECT" }, - { 0x1C15, "TeleWell Oy" }, - { 0x1C16, "Afit Corporation" }, - { 0x1C17, "LAB REHAB PTE LTD." }, - { 0x1C18, "Apria Technology" }, - { 0x1C19, "Charder Electronic Co., Ltd." }, - { 0x1C1A, "Datel Electronics Ltd." }, - { 0x1C1B, "Volkswagen of America, Inc." }, - { 0x1C1C, "Schmartz Inc." }, - { 0x1C1D, "GASTEC CORPORATION" }, - { 0x1C1E, "Focused Test, Inc." }, - { 0x1C1F, "Goldvish S.A." }, - { 0x1C20, "Fuji Electric Device Technology Co., Ltd." }, - { 0x1C21, "ADDMM LLC" }, - { 0x1C22, "ZHONGSHAN CHIANG YU ELECTRIC CO., LTD." }, - { 0x1C23, "Enzytek Technology Inc." }, - { 0x1C24, "DIGITAL IMAGING SYSTEMS GmbH" }, - { 0x1C25, "Sunwell Electronics Ltd." }, - { 0x1C26, "Shanghai Haiying Electronics Co., Ltd." }, - { 0x1C27, "SHENZHEN DNS INDUSTRIES CO., LTD." }, - { 0x1C28, "PMDTechnologies" }, - { 0x1C29, "Elster Group" }, - { 0x1C2A, "NAVIGON AG" }, - { 0x1C2B, "SIEB & MEYER AG" }, - { 0x1C2C, "QUANTEL LTD." }, - { 0x1C2D, "Barloworld Scientific Limited" }, - { 0x1C2E, "LiveWire Test Labs, Inc." }, - { 0x1C2F, "Wessex Advanced Switching Products Ltd." }, - { 0x1C30, "Li Creative Technologies, Inc." }, - { 0x1C31, "LS Mtron Ltd." }, - { 0x1C32, "INTELBANQ" }, - { 0x1C33, "EK-TEAM GmbH" }, - { 0x1C34, "Pro-Active" }, - { 0x1C35, "Superna Inc." }, - { 0x1C36, "Axiom Manufacturing" }, - { 0x1C37, "Sonavation, Inc." }, - { 0x1C38, "Kirin Techno-System Company, Limited" }, - { 0x1C39, "Quantronix, Inc." }, - { 0x1C3A, "CCV Deutschland GmbH" }, - { 0x1C3B, "Nivis, LLC" }, - { 0x1C3C, "INFOTURE, INC." }, - { 0x1C3D, "NONIN MEDICAL INC." }, - { 0x1C3E, "Wep Peripherals" }, - { 0x1C3F, "Amfit, Inc." }, - { 0x1C40, "EZ PROTOTYPES" }, - { 0x1C41, "CompX Fort" }, - { 0x1C42, "VERCET LLC" }, - { 0x1C43, "PeCon GmbH" }, - { 0x1C44, "Fukasawa Co." }, - { 0x1C45, "NavCom Technology Inc." }, - { 0x1C46, "Hitachi Zosen Corporation" }, - { 0x1C47, "Andrew Telecommunication Product SRL" }, - { 0x1C48, "International Truck and Engine Corporation" }, - { 0x1C49, "Cherng Weei Technology Corp." }, - { 0x1C4A, "Cathay Tri-Tech., Inc." }, - { 0x1C4B, "Geratherm Respiratory GmbH" }, - { 0x1C4C, "SYSTECH" }, - { 0x1C4D, "Everest Display Inc." }, - { 0x1C4E, "Koninklijke Gazelle N.V." }, - { 0x1C4F, "Beijing Sigmachip Co., Ltd." }, - { 0x1C50, "Chatsworth Data Corporation" }, - { 0x1C51, "Wisecube Co., Ltd." }, - { 0x1C52, "FLEETWOOD ELECTRONICS LTD." }, - { 0x1C53, "Heartland Data Co." }, - { 0x1C54, "NU-LEC INDUSTRIES" }, - { 0x1C55, "LGS" }, - { 0x1C56, "RED DIGITAL CINEMA" }, - { 0x1C57, "Zalman Tech Co., Ltd." }, - { 0x1C58, "IVA Corporation" }, - { 0x1C59, "SIXNET, LLC" }, - { 0x1C5A, "Fisher and Paykel Healthcare Limited" }, - { 0x1C5B, "FUTURE WAVES PTE Ltd." }, - { 0x1C5C, "CELLMETRIC LTD." }, - { 0x1C5D, "KB Kommutatcionnoy apparatury LTD." }, - { 0x1C5E, "Fueltech Ind. & Com. Prod. Elet. Ltda." }, - { 0x1C5F, "Watec Co., Ltd." }, - { 0x1C60, "Vision & Control GmbH" }, - { 0x1C61, "ASI DataMyte, Inc." }, - { 0x1C62, "LITEPOINT CORP." }, - { 0x1C63, "DLP Design, Inc." }, - { 0x1C64, "QSI Corporation" }, - { 0x1C65, "PROCENTEC" }, - { 0x1C66, "The Trane Company" }, - { 0x1C67, "Sugar Creek Solutions LLC" }, - { 0x1C68, "Trace Systems, Inc." }, - { 0x1C69, "MPB Communications" }, - { 0x1C6A, "Regula Ltd." }, - { 0x1C6B, "Philips & Lite-ON Digital Solutions Corporation" }, - { 0x1C6C, "Skydigital Inc." }, - { 0x1C6D, "Bioptigen Inc." }, - { 0x1C6E, "MINELAB ELECTRONICS PTY LTD." }, - { 0x1C6F, "SUN-A CORPORATION" }, - { 0x1C70, "Wessa Engineering" }, - { 0x1C71, "HUMANWARE LTD." }, - { 0x1C72, "EMTEC Elektronische Messtechnik GmbH" }, - { 0x1C73, "AMT Co., Ltd." }, - { 0x1C74, "PHOTOVOX srl" }, - { 0x1C75, "ARTURIA" }, - { 0x1C76, "Sun-Light Electronic Technologies Inc." }, - { 0x1C77, "Kaetat Industrial Co., Ltd." }, - { 0x1C78, "Mindray DS USA, Inc." }, - { 0x1C79, "Unigen Corporation" }, - { 0x1C7A, "Egis Technology, Inc." }, - { 0x1C7B, "Shenzhen Luxshare Precision Industry Co., Ltd." }, - { 0x1C7C, "DELCOP LLC" }, - { 0x1C7D, "STARKEY LABORATORIES INC." }, - { 0x1C7E, "Hydrometer GmbH" }, - { 0x1C7F, "FILTRONIC DEFENCE LIMITED" }, - { 0x1C80, "Hoffmann + Krippner GmbH" }, - { 0x1C81, "MOTOSOFT b.v." }, - { 0x1C82, "Atracsys LLC" }, - { 0x1C83, "BEKA Elektronik" }, - { 0x1C84, "DRS Tactical Systems" }, - { 0x1C85, "Audyssey Laboratories, Inc." }, - { 0x1C86, "Tallahassee Technologies, Inc." }, - { 0x1C87, "2N TELEKOMUNIKACE a.s." }, - { 0x1C88, "Somagic, Inc." }, - { 0x1C89, "HONGKONG WEIDIDA ELECTRON LIMITED" }, - { 0x1C8A, "SHIN HEUNG PRECISION CO., LTD." }, - { 0x1C8B, "Bridgestone Cycle Co., Ltd." }, - { 0x1C8C, "noax Technologies AG" }, - { 0x1C8D, "Payter BV" }, - { 0x1C8E, "ASTRON INTERNATIONAL CORP." }, - { 0x1C8F, "Scolis Technologies (India) Pvt. Ltd." }, - { 0x1C90, "Pixela (Shanghai) Co., Ltd." }, - { 0x1C91, "Hutchinson Technology Incorporated" }, - { 0x1C92, "JDD Enterprises" }, - { 0x1C93, "Airspan Networks" }, - { 0x1C94, "Maerzhaeuser Wetzlar GmbH & Co. KG." }, - { 0x1C95, "OVATION SYSTEMS LIMITED" }, - { 0x1C96, "Tesselon, LLC" }, - { 0x1C97, "PEBBLE ENTERTAINMENT GmbH" }, - { 0x1C98, "ALPINE ELECTRONICS, INC." }, - { 0x1C99, "KETEREX, Inc." }, - { 0x1C9A, "Simple Step LLC" }, - { 0x1C9B, "Ohden Co., Ltd." }, - { 0x1C9C, "Technological Solutions Laboratory" }, - { 0x1C9D, "Descuentos y Electronicos AVA" }, - { 0x1C9E, "Shanghai Longcheer 3G Technology Co., Ltd." }, - { 0x1C9F, "SISS Technology Inc." }, - { 0x1CA0, "ACCARIO Inc." }, - { 0x1CA1, "Symwave, Inc." }, - { 0x1CA2, "G-coder Systems AB" }, - { 0x1CA3, "CAPAZ GmbH" }, - { 0x1CA4, "METRICO WIRELESS INC." }, - { 0x1CA5, "HASLER RAIL AG" }, - { 0x1CA6, "TECHNO-AP Limited Company" }, - { 0x1CA7, "BAE SYSTEMS AUSTRALIA LIMITED" }, - { 0x1CA8, "ROCCAT STUDIO GmbH" }, - { 0x1CA9, "THE TINTOMETER LTD." }, - { 0x1CAA, "Accel Semiconductor Corp." }, - { 0x1CAB, "SCS Engineering, Inc." }, - { 0x1CAC, "SHENZHEN KINSTONE D&T DEVELOP CO., LTD." }, - { 0x1CAD, "ONE-TOO" }, - { 0x1CAE, "MPMAN" }, - { 0x1CAF, "2WCOM GmbH" }, - { 0x1CB0, "LEGRAND FRANCE" }, - { 0x1CB1, "Enforce Device Inc." }, - { 0x1CB2, "PCO AG" }, - { 0x1CB3, "Aces Electronics Co., Ltd." }, - { 0x1CB4, "OPEX CORPORATION" }, - { 0x1CB5, "Boonton Electronics" }, - { 0x1CB6, "IDEACOM TECHNOLOGY INC." }, - { 0x1CB7, "EASTERN TIMES TECHNOLOGY CO., LTD." }, - { 0x1CB8, "Ferguson Beauregard" }, - { 0x1CB9, "DIVERSIFIED TECHNICAL SYSTEMS, INC." }, - { 0x1CBA, "MERIDIAN AUDIO LTD." }, - { 0x1CBB, "DATATEC CO., LTD." }, - { 0x1CBC, "Zizzle, LLC" }, - { 0x1CBD, "Wha Shin Co., Ltd." }, - { 0x1CBE, "Texas Instruments - Stellaris" }, - { 0x1CBF, "FORTAT SKYMARK INDUSTRIAL COMPANY" }, - { 0x1CC0, "PlantSense" }, - { 0x1CC1, "EXAKTIME INC." }, - { 0x1CC2, "CC Systems AB" }, - { 0x1CC3, "Biocomfort Diagnostics GmbH & Co. KG" }, - { 0x1CC4, "Byte Paradigm sprl" }, - { 0x1CC5, "Rane Corporation" }, - { 0x1CC6, "Digital Force Technologies" }, - { 0x1CC7, "GELOGIC" }, - { 0x1CC8, "Iofy Corporation" }, - { 0x1CC9, "COMAP, spol. s r. o." }, - { 0x1CCA, "NextWave Broadband Inc." }, - { 0x1CCB, "Lattebox Co., Ltd." }, - { 0x1CCC, "DA-DESIGN OY" }, - { 0x1CCD, "Bodatong Technology (Shenzhen) Co., Ltd." }, - { 0x1CCE, "DATA MODUL" }, - { 0x1CCF, "Konami Digital Entertainment Co., Ltd." }, - { 0x1CD0, "VEGATECH CO., LTD." }, - { 0x1CD1, "ARTAFLEX" }, - { 0x1CD2, "Christ Elektronik GmbH" }, - { 0x1CD3, "ATSUMI ELECTRIC CO., LTD." }, - { 0x1CD4, "adp corporation" }, - { 0x1CD5, "Firecomms Ltd." }, - { 0x1CD6, "Antonio Precise Products Manufactory Ltd." }, - { 0x1CD7, "GMC-I Gossen-Metrawatt GmbH" }, - { 0x1CD8, "Dash Navigation, Inc." }, - { 0x1CD9, "TL Industries" }, - { 0x1CDA, "NAVICO" }, - { 0x1CDB, "Cat Technologies Ltd." }, - { 0x1CDC, "Advanced Medical Electronics Corp." }, - { 0x1CDD, "YOOSAMFLUTE CO., LTD." }, - { 0x1CDE, "Telecommunications Technology Association (TTA)" }, - { 0x1CDF, "WonTen Technology Co., Ltd." }, - { 0x1CE0, "EDIMAX TECHNOLOGY CO., LTD." }, - { 0x1CE1, "Amphenol KAE" }, - { 0x1CE2, "Extron Electronics" }, - { 0x1CE3, "Australian Simulation Control Systems Pty., Ltd." }, - { 0x1CE4, "High Leah Electronics, Inc." }, - { 0x1CE5, "SimPhonics, Inc." }, - { 0x1CE6, "SOPRO" }, - { 0x1CE7, "FASY SPA" }, - { 0x1CE8, "Alcorn McBride, Inc." }, - { 0x1CE9, "Cadmus Payment Solutions Ltd." }, - { 0x1CEA, "MESTEK, INC." }, - { 0x1CEB, "SMARTWI" }, - { 0x1CEC, "Siemens AG I & S Postal Automation" }, - { 0x1CED, "DEWESOFT d.o.o." }, - { 0x1CEE, "Production Technology Center Kyushuu" }, - { 0x1CEF, "Siemens LD-A" }, - { 0x1CF0, "SA VALIDY" }, - { 0x1CF1, "dresden elektronik ingenieurtechnik gmbh" }, - { 0x1CF2, "TrellisWare Technologies, Inc." }, - { 0x1CF3, "Lion Power Co., Ltd." }, - { 0x1CF4, "SK INTERFACES LTD." }, - { 0x1CF5, "Swirlnet A/S" }, - { 0x1CF6, "Atlantic Zeiser GmbH" }, - { 0x1CF7, "Electric-Spin" }, - { 0x1CF8, "Biometric Associates" }, - { 0x1CF9, "Aipermon GmbH & Co. KG" }, - { 0x1CFA, "Daco Scientific Limited" }, - { 0x1CFB, "Livescribe Inc." }, - { 0x1CFC, "ANDES TECHNOLOGY CORPORATION" }, - { 0x1CFD, "Flextronics Digital Design Japan, LTD." }, - { 0x1CFE, "Cryptsoft Pty. Ltd." }, - { 0x1CFF, "Tad Radio of Canada Inc." }, - { 0x1D00, "MicroStone Corporation" }, - { 0x1D01, "SNIF Labs" }, - { 0x1D02, "DevGuru" }, - { 0x1D03, "ICON INTERNATIONAL DIGITAL LIMITED" }, - { 0x1D04, "Itronics" }, - { 0x1D05, "DESTURA S.R.L." }, - { 0x1D06, "BBK ELECTRONICS CORPORATION LIMITED" }, - { 0x1D07, "Solid-Motion" }, - { 0x1D08, "NINGBO HENTEK DRAGON ELECTRONICS CO., LTD." }, - { 0x1D09, "TechFaith Wireless Technology Limited" }, - { 0x1D0A, "Visteon Corporation" }, - { 0x1D0B, "HAN HUA CABLE & WIRE TECHNOLOGY (J.X.) CO., LTD." }, - { 0x1D0C, "LAKS GmbH" }, - { 0x1D0D, "TDK Marketing Europe GmbH" }, - { 0x1D0E, "deister electronic GmbH" }, - { 0x1D0F, "NEO ELECTRONICS (HK) CO., LIMITED" }, - { 0x1D10, "Jiangsu Shinco Digital Technology Co., Ltd." }, - { 0x1D11, "Xtend Technologies Pvt. Ltd." }, - { 0x1D12, "UAB TELTONIKA" }, - { 0x1D13, "L3 Communications - Telemetry West" }, - { 0x1D14, "ALPHA-SAT TECHNOLOGY LIMITED" }, - { 0x1D15, "FUJIFILM RECORDING MEDIA GmbH" }, - { 0x1D16, "KABA MAS CORPORATION" }, - { 0x1D17, "C-THRU MUSIC Ltd." }, - { 0x1D18, "APICAL INSTRUMENTS, INC." }, - { 0x1D19, "Dexatek Technology Ltd." }, - { 0x1D1A, "Boeckeler Instruments, Inc." }, - { 0x1D1B, "HumanBeams Inc." }, - { 0x1D1C, "Novatron Oy" }, - { 0x1D1D, "SYNESTHESIA CORPORATION" }, - { 0x1D1E, "OFFCODE" }, - { 0x1D1F, "Diostech Co., Ltd." }, - { 0x1D20, "SAMTACK INC." }, - { 0x1D21, "COMPUSULT LIMITED" }, - { 0x1D22, "ELCOM s.r.o." }, - { 0x1D23, "Netsushin Co., Ltd." }, - { 0x1D24, "PHOTON KINETICS" }, - { 0x1D25, "Trinity Security Systems, Inc." }, - { 0x1D26, "ADVANCED ELECTRONICS LTD." }, - { 0x1D27, "Prime Sense Ltd." }, - { 0x1D28, "JORDAN VALLEY SEMICONDUCTORS LTD." }, - { 0x1D29, "Horng Tong Enterprise Co., Ltd." }, - { 0x1D2A, "LyconSys GmbH & Co. KG" }, - { 0x1D2B, "BEN-RI ELECTRONICA S.A." }, - { 0x1D2C, "equinux AG" }, - { 0x1D2D, "Fraunhofer IBMT" }, - { 0x1D2E, "I.S.V. Co., Ltd." }, - { 0x1D2F, "JACO, INC." }, - { 0x1D30, "Sinosun Technology Ltd." }, - { 0x1D31, "XINTRONIX LIMITED" }, - { 0x1D32, "ELECTRONICA MECHATRONIC SYSTEMS (I) PVT. LTD." }, - { 0x1D33, "Lockheed Martin - Maritime Systems & Sensors" }, - { 0x1D34, "DREAM LINK LTD." }, - { 0x1D35, "ISS Manufacturing Limited" }, - { 0x1D36, "Volucris, Inc." }, - { 0x1D37, "Phoenix Microelectronics (China) Co., Ltd." }, - { 0x1D38, "Ergowerx Int'l LLC/Smartfish Technologies" }, - { 0x1D39, "XECURENEXUS Co., LTD." }, - { 0x1D3A, "P. R. Glassel & Associates, Inc." }, - { 0x1D3B, "J & C Technology Co., Ltd." }, - { 0x1D3C, "Tomei Tsushin Kogyo Co., Ltd." }, - { 0x1D3D, "R&D Center of Biometric Technology-BMSTU" }, - { 0x1D3E, "EMCON Emanation Control Limited" }, - { 0x1D3F, "Photon Control Inc." }, - { 0x1D40, "EDANIS Elektronik AG" }, - { 0x1D41, "Teletronic Rossendorf GmbH" }, - { 0x1D42, "DRAGON JOY LIMITED" }, - { 0x1D43, "Montage Technology, Inc." }, - { 0x1D44, "Adirondack Digital Imaging Systems, Inc." }, - { 0x1D45, "Qisda Corporation" }, - { 0x1D46, "nSys Design Systems" }, - { 0x1D47, "ATAUCE" }, - { 0x1D48, "Shenzhen XinYonghui Precise Technology Co., Ltd." }, - { 0x1D49, "SHENZHEN LINKCONN ELECTRONICS CO., LTD." }, - { 0x1D4A, "HKS Co., Ltd." }, - { 0x1D4B, "DARIM VISION CO." }, - { 0x1D4C, "ARK-DESIGN Co., Ltd." }, - { 0x1D4D, "Pegatron Corporation" }, - { 0x1D4E, "INPHI CORPORATION" }, - { 0x1D4F, "ADVANCED CHIP EXPRESS INC." }, - { 0x1D50, "OPENMOKO, Inc." }, - { 0x1D51, "Sengital Limited" }, - { 0x1D52, "ELECTROBYTE di GARAVAGLIA MATTIA" }, - { 0x1D53, "Innofidei Inc." }, - { 0x1D54, "ZARAM TECHNOLOGY, Inc." }, - { 0x1D55, "XRONet Corporation" }, - { 0x1D56, "Verico International Co., Ltd." }, - { 0x1D57, "Feeling Technology Corp." }, - { 0x1D58, "SUZUKI Engineering" }, - { 0x1D59, "3DSP" }, - { 0x1D5A, "Hillcrest Laboratories, Inc." }, - { 0x1D5B, "Smartronix, Inc." }, - { 0x1D5C, "Fresco Logic Inc." }, - { 0x1D5D, "QIXING INDUSTRIAL (HK) CO." }, - { 0x1D5E, "Tonium AB" }, - { 0x1D5F, "ViVOtech, Inc." }, - { 0x1D60, "ASAP International Co., Ltd." }, - { 0x1D61, "ACCEMIC GmbH & CO. KG" }, - { 0x1D62, "KYORITSU ELECTRIC CO., LTD." }, - { 0x1D63, "Nippon Seiki Co., Ltd." }, - { 0x1D64, "MobilMAX Technology Inc." }, - { 0x1D65, "Moteurs LEROY SOMER" }, - { 0x1D66, "StreamBuster" }, - { 0x1D67, "DYNAMIC INNOVATIONS LIMITED" }, - { 0x1D68, "SEMA ELECTRONICS (H.K.) CO., Ltd." }, - { 0x1D69, "Walta Electronic Co., Ltd." }, - { 0x1D6A, "ARICENT TECHNOLOGIES (HOLDINGS) LTD." }, - { 0x1D6B, "The Linux Foundation" }, - { 0x1D6C, "Man & Machine, Inc." }, - { 0x1D6D, "VARISYS LIMITED" }, - { 0x1D6E, "EUROTECH" }, - { 0x1D6F, "Seluxit" }, - { 0x1D70, "MULTIPLE ACCESS COMMUNICATIONS LTD." }, - { 0x1D71, "Finisar Corporation" }, - { 0x1D72, "Mobiltex Data Ltd." }, - { 0x1D73, "Signal Processing Devices Sweden AB" }, - { 0x1D74, "LG Innotek Co., Ltd." }, - { 0x1D75, "DICOM, spol. s r.o." }, - { 0x1D76, "LongCheng Electronic & Communication CO., LTD." }, - { 0x1D77, "Yueqing Changling Electronic Instrument Corp., Ltd." }, - { 0x1D78, "CAMBRIDGE SEMICONDUCTOR LTD." }, - { 0x1D79, "Shenzhen Innosystem Technology Ltd." }, - { 0x1D7A, "SHINWA INTERNATIONAL HOLDINGS LTD." }, - { 0x1D7B, "Single Strand Co., Ltd." }, - { 0x1D7C, "KarmelSonix" }, - { 0x1D7D, "Seoul Commtech Co., Ltd." }, - { 0x1D7E, "WAVESAT" }, - { 0x1D7F, "MoBeam, Inc." }, - { 0x1D80, "PLDA" }, - { 0x1D81, "YongXin Plastic & Hardware Co., Ltd." }, - { 0x1D82, "HERTZ SYSTEMTECHNIK GmbH" }, - { 0x1D83, "Mantech International" }, - { 0x1D84, "Kechenda Plastic Electronic Factory" }, - { 0x1D85, "NINGBO SHUNSHENG COMMUNICATION APPARATUS CO., LTD." }, - { 0x1D86, "C.D.N. CORPORATION" }, - { 0x1D87, "RHK TECHNOLOGY, INC." }, - { 0x1D88, "Mahr GmbH" }, - { 0x1D89, "Hunter Associates" }, - { 0x1D8A, "OSASI Technos Inc. (Tokyo Headquarters)" }, - { 0x1D8B, "MEDTRONIC" }, - { 0x1D8C, "Wuxi AlphaScale IC Systems, Inc." }, - { 0x1D8D, "EXEO SYSTEMS" }, - { 0x1D8E, "Capistrano Labs, Inc." }, - { 0x1D8F, "Viprinet GmbH" }, - { 0x1D90, "CITIZEN SYSTEMS JAPAN CO., LTD." }, - { 0x1D91, "BYD COMPANY LIMITED" }, - { 0x1D92, "SPECTRONIC DEVICES LTD." }, - { 0x1D93, "Tokyo System Development Co., Ltd." }, - { 0x1D94, "ENCIRIS TECHNOLOGIES" }, - { 0x1D95, "SYSTRONIK Elektronik und Systemtechnik GmbH" }, - { 0x1D96, "CHIRSON LTD." }, - { 0x1D97, "Telonics" }, - { 0x1D98, "OUTLINE ELECTRONICS LTD." }, - { 0x1D99, "Shanghai HSIC Application System Co., Ltd." }, - { 0x1D9A, "Vubiq, Inc." }, - { 0x1D9B, "Techno Source" }, - { 0x1D9C, "SONIM TECHNOLOGIES, INC." }, - { 0x1D9D, "Sigma Elektro GmbH" }, - { 0x1D9E, "CSR, Inc." }, - { 0x1D9F, "KUNMING ELECTRONICS CO., LTD." }, - { 0x1DA0, "Parade Technologies, Inc." }, - { 0x1DA1, "COVIDENCE A/S" }, - { 0x1DA2, "LAMBDA, INC." }, - { 0x1DA3, "bebro electronic GmbH" }, - { 0x1DA4, "BTICINO" }, - { 0x1DA5, "CATHEXIS INNOVATIONS INC." }, - { 0x1DA6, "Inepro BV" }, - { 0x1DA7, "ENDRA Inc." }, - { 0x1DA8, "VIOLET" }, - { 0x1DA9, "In-Circuit GmbH" }, - { 0x1DAA, "Alcatel-Lucent" }, - { 0x1DAB, "MAGELLAN GPS" }, - { 0x1DAC, "MOBOTIX AG" }, - { 0x1DAD, "DATNET KFT" }, - { 0x1DAE, "ellipsis INC." }, - { 0x1DAF, "Breas Medical AB" }, - { 0x1DB0, "GreenPeak Technologies NV" }, - { 0x1DB1, "Reliable Controls Corporation" }, - { 0x1DB2, "Duali Inc." }, - { 0x1DB3, "Arcelik A.S." }, - { 0x1DB4, "Montalvo Systems" }, - { 0x1DB5, "BRYSTON LTD." }, - { 0x1DB6, "eDimensional, Inc." }, - { 0x1DB7, "SMedia Technology Corporation" }, - { 0x1DB8, "HD MEDICAL INC." }, - { 0x1DB9, "LITEN UP TECHNOLOGIES INC." }, - { 0x1DBA, "BancTec, Inc." }, - { 0x1DBB, "Condalo GmbH" }, - { 0x1DBC, "Shenzhen HOJY Technology Co., Ltd." }, - { 0x1DBD, "Terawins" }, - { 0x1DBE, "S.R.N. Corporation" }, - { 0x1DBF, "Signostics Pty. Ltd." }, - { 0x1DC0, "DATAFIELD INDIA PVT.LTD." }, - { 0x1DC1, "Laser Drive" }, - { 0x1DC2, "Datalogic Mobile Inc." }, - { 0x1DC3, "PoLabs" }, - { 0x1DC4, "TRANSICS" }, - { 0x1DC5, "Pixim Inc." }, - { 0x1DC6, "Miyama, Inc." }, - { 0x1DC7, "Leroy Automatique Industrielle" }, - { 0x1DC8, "GC Corporation" }, - { 0x1DC9, "Hitachi Koki Co., Ltd." }, - { 0x1DCA, "The IVOXX Corp." }, - { 0x1DCB, "IFTEST AG" }, - { 0x1DCC, "Document Capture Technologies, Inc." }, - { 0x1DCD, "HIN KUI MACHINE & METAL INDUSTRIAL CO., LTD." }, - { 0x1DCE, "SIMTEC Elektronik GmbH" }, - { 0x1DCF, "INVIX Co., Ltd." }, - { 0x1DD0, "ABB AS, Division Automation Products" }, - { 0x1DD1, "EFJohnson" }, - { 0x1DD2, "LEO BODNAR" }, - { 0x1DD3, "Dajac, Inc." }, - { 0x1DD4, "ARMELIN WIDGET CORPORATION" }, - { 0x1DD5, "MetaGeek, LLC" }, - { 0x1DD6, "Solomon Technology Corp." }, - { 0x1DD7, "REDMERE TECHNOLOGY" }, - { 0x1DD8, "BUFFALO KOKUYO SUPPLY INC." }, - { 0x1DD9, "EFFICERE TECHNOLOGIES" }, - { 0x1DDA, "TA Instruments" }, - { 0x1DDB, "Abon Touchsystems Inc." }, - { 0x1DDC, "id Quantique" }, - { 0x1DDD, "DOKING ELECTRONIC TECHNOLOGY CO., LTD." }, - { 0x1DDE, "TridonicAtco" }, - { 0x1DDF, "L&T Technology Services" }, - { 0x1DE0, "Shenzhen Excelstor Technology Ltd." }, - { 0x1DE1, "Actions Microelectronics Co., Ltd." }, - { 0x1DE2, "ENTERY INDUSTRIAL CO., LTD." }, - { 0x1DE3, "SHENZHEN REX ELECTRONICS CO., LTD." }, - { 0x1DE4, "DAEWOO ELECTRONICS CORPORATION" }, - { 0x1DE5, "AMONTEC" }, - { 0x1DE6, "MICRORISC S.R.O." }, - { 0x1DE7, "MIDAS TECHNOLOGY" }, - { 0x1DE8, "Applied Systems Engineering, Inc." }, - { 0x1DE9, "Seco Technology Co., Ltd." }, - { 0x1DEA, "Yesin Electronics Technology Co., Ltd." }, - { 0x1DEB, "SHIUH CHI PRECISION INDUSTRY CO., LTD." }, - { 0x1DEC, "HAGER CONTROLS SAS" }, - { 0x1DED, "COOLIT SYSTEMS, INC." }, - { 0x1DEE, "JCM II, Inc." }, - { 0x1DEF, "KYOTO KAGAKU CO., LTD." }, - { 0x1DF0, "TRICKLESTAR LIMITED" }, - { 0x1DF1, "HUATIANYUAN ELECTRONIC INDUSTRY CO., LTD." }, - { 0x1DF2, "China Telecommunication Technology Labs - Terminals" }, - { 0x1DF3, "CRESYN CO., LTD." }, - { 0x1DF4, "SHEN ZHEN FORMAN PRECISION INDUSTRY CO., LTD." }, - { 0x1DF5, "Universal Remote Control, Inc." }, - { 0x1DF6, "TakeMS International AG" }, - { 0x1DF7, "Mirics Semiconductor Ltd." }, - { 0x1DF8, "The Charles Machine Works, Inc." }, - { 0x1DF9, "Komax AG" }, - { 0x1DFA, "BLOCKMASTER AB" }, - { 0x1DFB, "marco Systemanalyse und Entwicklung GmbH" }, - { 0x1DFC, "YUNNAN NANTIAN ELECTRONICS INFORMATION CO., LTD." }, - { 0x1DFD, "Quality Thermistor, Inc." }, - { 0x1DFE, "BEDA Precision" }, - { 0x1DFF, "InfraRed Integrated Systems Ltd." }, - { 0x1E00, "Jupiter Systems" }, - { 0x1E01, "Dynalloy, Inc." }, - { 0x1E02, "GLOBEMASTER TECHNOLOGIES CO., LTD." }, - { 0x1E03, "OXFORD INSTRUMENTS ANALYTICAL OY" }, - { 0x1E04, "Coolsand Technologies (Hong Kong) Ltd." }, - { 0x1E05, "Microtronic AG" }, - { 0x1E06, "Moore Industries International" }, - { 0x1E07, "GETA ELECTRONICS (DONG GUAN) CO., LTD." }, - { 0x1E08, "Inventure, Inc." }, - { 0x1E09, "Baldwin Boxall Communication Ltd." }, - { 0x1E0A, "NOX Medical" }, - { 0x1E0B, "TUBITAK UEKAE" }, - { 0x1E0C, "NATIONAL HYBRID, INC." }, - { 0x1E0D, "NEOWAVE" }, - { 0x1E0E, "SHANGHAI BASECOM LTD." }, - { 0x1E0F, "mSilica Inc." }, - { 0x1E10, "FLIR Integrated Imaging Solutions" }, - { 0x1E11, "Hoya Xponent" }, - { 0x1E12, "OCTRIAN" }, - { 0x1E13, "Burgundy Electric, LLC" }, - { 0x1E14, "YANtide Corporation" }, - { 0x1E15, "mStation" }, - { 0x1E16, "SMARTIO" }, - { 0x1E17, "Mirion Technologies Inc." }, - { 0x1E18, "MIGHT Co., Ltd." }, - { 0x1E19, "Torus Networks Co., Ltd." }, - { 0x1E1A, "HITEC RCD KOREA" }, - { 0x1E1B, "e-Practical Solutions" }, - { 0x1E1C, "CMS PRODUCTS" }, - { 0x1E1D, "Kanguru Solutions" }, - { 0x1E1E, "Trans New Technology, Inc." }, - { 0x1E1F, "INVIA" }, - { 0x1E20, "JDSU" }, - { 0x1E21, "NEONUMERIC" }, - { 0x1E22, "LEDCO" }, - { 0x1E23, "Aeronix, Inc." }, - { 0x1E24, "Cine-tal Systems, Inc." }, - { 0x1E25, "3M Cogent, Inc." }, - { 0x1E26, "Multi Channel Systems MCS GmbH" }, - { 0x1E27, "NASA / Johnson Space Center / EV2" }, - { 0x1E28, "Raptor Innovations International" }, - { 0x1E29, "Festo AG & Co. KG" }, - { 0x1E2A, "NANOFORTI INC." }, - { 0x1E2B, "3M CMD (Communication Markets Division)" }, - { 0x1E2C, "KRONIK ELEKTRONIK SANAYI VETICARET LIMITED SIRKETI" }, - { 0x1E2D, "Cinterion Wireless Modules GmbH" }, - { 0x1E2E, "Syrinx Industrial Electronics b.v." }, - { 0x1E2F, "Celrun Co., Ltd." }, - { 0x1E30, "Kohler Co." }, - { 0x1E31, "Greatbatch" }, - { 0x1E32, "Opti-Sciences, Inc." }, - { 0x1E33, "KOBIAN CANADA INC." }, - { 0x1E34, "Sensory, Inc." }, - { 0x1E35, "BELLING Co., Ltd." }, - { 0x1E36, "Insulet Corporation" }, - { 0x1E37, "Rehoboth Tech. Co., Ltd." }, - { 0x1E38, "QRS Music Technologies Inc." }, - { 0x1E39, "YIS Corporation" }, - { 0x1E3A, "Continental Automotive Systems Inc." }, - { 0x1E3B, "MICROBIT 2.0 AB" }, - { 0x1E3C, "Vapor Bus Int'l Div of Westinghouse Air Brake Tech Corp" }, - { 0x1E3D, "Chipsbrand Technologies (HK) Co., Limited" }, - { 0x1E3E, "EMS Aviation" }, - { 0x1E3F, "JJ Keller & Associates Inc." }, - { 0x1E40, "SciLog, Inc." }, - { 0x1E41, "Cleverscope Ltd." }, - { 0x1E42, "SSE GmbH" }, - { 0x1E43, "Sagem Mobiles" }, - { 0x1E44, "SHIMANO INC." }, - { 0x1E45, "TADANO LTD." }, - { 0x1E46, "Danfoss A/S" }, - { 0x1E47, "HUNG TA H.T.ENTERPRISE CO., LTD." }, - { 0x1E48, "LABAU Technology" }, - { 0x1E49, "FES LLC" }, - { 0x1E4A, "CHIRON TECHNOLOGY LTD." }, - { 0x1E4B, "exxact GmbH" }, - { 0x1E4C, "Stereotaxis, Inc." }, - { 0x1E4D, "BST International GmbH" }, - { 0x1E4E, "Etron Technology, Inc." }, - { 0x1E4F, "SECOM Co., Ltd." }, - { 0x1E50, "VILTECHMEDA UAB" }, - { 0x1E51, "DiMoto" }, - { 0x1E52, "SZ TELSTAR CO., LTD." }, - { 0x1E53, "WYPLAY" }, - { 0x1E54, "TypeMatrix Inc." }, - { 0x1E55, "Memorysolution GmbH" }, - { 0x1E56, "EURINTEL" }, - { 0x1E57, "Bundesdruckerei GmbH" }, - { 0x1E58, "Horner APG" }, - { 0x1E59, "inTera Tecnologia" }, - { 0x1E5A, "VOXTRONIC TECHNOLOGY" }, - { 0x1E5B, "APRICO A/S" }, - { 0x1E5C, "Enova Technology Corp." }, - { 0x1E5D, "SAT Corporation" }, - { 0x1E5E, "Touch International" }, - { 0x1E5F, "Relpol SA" }, - { 0x1E60, "SEA Signalisation" }, - { 0x1E61, "Anoto AB" }, - { 0x1E62, "Uriver Inc." }, - { 0x1E63, "DRAEGER MEDICAL" }, - { 0x1E64, "IMSTORAGE CO., LTD." }, - { 0x1E65, "THE BOEING CO." }, - { 0x1E66, "KAPSYS" }, - { 0x1E67, "Orban/CRL Systems, Inc." }, - { 0x1E68, "TrekStor GmbH & Co. KG" }, - { 0x1E69, "Hormann Funkwerk Kolleda GmbH" }, - { 0x1E6A, "RGB Spectrum" }, - { 0x1E6B, "iRex Technologies B.V." }, - { 0x1E6C, "Sureshotgps Pty. Ltd." }, - { 0x1E6D, "WAN SHIH ELECTRONIC (H.K.) CO., LTD." }, - { 0x1E6E, "F&D Feinwerk-Und Drucktechnik GmbH" }, - { 0x1E6F, "Images Scientific Instruments Inc." }, - { 0x1E70, "POSBRO Inc." }, - { 0x1E71, "NZXT Corporation" }, - { 0x1E72, "Federal Signal Corporation" }, - { 0x1E73, "COMLINK ELECTRONICS CO., LTD." }, - { 0x1E74, "COBY COMMUNICATIONS, LIMITED" }, - { 0x1E75, "TLS Communication GmbH" }, - { 0x1E76, "Proview Technology (Shenzhen) Co., Ltd." }, - { 0x1E77, "Core Micro Technology Inc." }, - { 0x1E78, "Flextronics R & D (Shenzhen) Co., Ltd." }, - { 0x1E79, "ISA Co., Ltd." }, - { 0x1E7A, "The Tsurumi-Seiki Company, Limited" }, - { 0x1E7B, "Zurich Instruments AG" }, - { 0x1E7C, "biostep GmbH" }, - { 0x1E7D, "ROCCAT GmbH" }, - { 0x1E7E, "Bright Star Engineering Inc." }, - { 0x1E7F, "NEXS ELECTRONIC CORP." }, - { 0x1E80, "InterDigital Communications LLC" }, - { 0x1E81, "KIDS PREFERRED, LLC." }, - { 0x1E82, "Nortech Systems" }, - { 0x1E83, "AMICUS WIRELESS" }, - { 0x1E84, "VIVAX CORPORATION" }, - { 0x1E85, "Gigaset Communications GmbH" }, - { 0x1E86, "Japan Meditech Co., Ltd." }, - { 0x1E87, "W&W Communications Inc." }, - { 0x1E88, "GBS Laboratories, LLC" }, - { 0x1E89, "Vtion Information Technology (Fujian) Co., Ltd." }, - { 0x1E8A, "HIBEST Electronic (DongGuan) Co., Ltd." }, - { 0x1E8B, "ImTech, Inc." }, - { 0x1E8C, "Data Conversion Systems Ltd." }, - { 0x1E8D, "HIGHVOLT Prueftechnik Dresden GmbH" }, - { 0x1E8E, "EADS Secure Networks" }, - { 0x1E8F, "PublicSolution GmbH" }, - { 0x1E90, "Mego Afek" }, - { 0x1E91, "Other World Computing" }, - { 0x1E92, "Beyond Question Learning Technologies, Inc." }, - { 0x1E93, "GSI Group" }, - { 0x1E94, "RealD" }, - { 0x1E95, "DIRECTV, Inc." }, - { 0x1E96, "BlueAnt Wireless" }, - { 0x1E97, "TOMMYCA HONG KONG LIMITED" }, - { 0x1E98, "COMPASS SYSTEMS CORP." }, - { 0x1E99, "General Dynamics C4 Systems" }, - { 0x1E9A, "MANTHAN SEMICONDUCTOR PVT. LTD." }, - { 0x1E9B, "Netcom Sicherheitstechnik GmbH" }, - { 0x1E9C, "FirstPaper, LLC" }, - { 0x1E9D, "GEOTEST AG" }, - { 0x1E9E, "InnoSys Inc." }, - { 0x1E9F, "Chase Peabody and Associates, Inc." }, - { 0x1EA0, "DiabloSport, Inc." }, - { 0x1EA1, "NANOBASE" }, - { 0x1EA2, "N.V. Nederlandsche Apparatenfabriek Nedap" }, - { 0x1EA3, "Concraft Holding Co., Ltd." }, - { 0x1EA4, "MOBILE SYSTEM TECHNOLOGIES INC." }, - { 0x1EA5, "CEN LINK CO., LTD." }, - { 0x1EA6, "novero GmbH" }, - { 0x1EA7, "SEMITEK INTERNATIONAL (HK) HOLDING LTD." }, - { 0x1EA8, "Shenzhen Excelsecu Data Technology Co., Ltd." }, - { 0x1EA9, "ANDERS ELECTRONICS PLC" }, - { 0x1EAA, "Zeebo, Inc." }, - { 0x1EAB, "Fujian Newland Auto-ID Tech. Co., Ltd." }, - { 0x1EAC, "Thinkware Systems" }, - { 0x1EAD, "Industrial Control Communications, Inc." }, - { 0x1EAE, "YESCNC CO., LTD." }, - { 0x1EAF, "Continental Trading GmbH" }, - { 0x1EB0, "Centers for Disease Control & Prevention (CDC)" }, - { 0x1EB1, "Kramer Electronics Ltd." }, - { 0x1EB2, "IWAKI CO., LTD." }, - { 0x1EB3, "SAE MAGNETICS (HK) LTD." }, - { 0x1EB4, "YuhDing Precision Industry (KunShan) Co., Ltd." }, - { 0x1EB5, "Diablo Technologies Inc." }, - { 0x1EB6, "PHYLINKS LIMITED" }, - { 0x1EB7, "WIN WIN PRECISION INDUSTRIAL CO., LTD." }, - { 0x1EB8, "MODACOM CO., LTD." }, - { 0x1EB9, "Campbell Scientific Inc." }, - { 0x1EBA, "HITTITE MICROWAVE CORP." }, - { 0x1EBB, "NuCORE Technology, Inc." }, - { 0x1EBC, "Beijing Novel-Super Media Investment Co., Ltd." }, - { 0x1EBD, "Wireless Matrix Corp." }, - { 0x1EBE, "Qwizdom, Inc." }, - { 0x1EBF, "Yulong Computer Telecommunication Scientific" }, - { 0x1EC0, "VIGORHOOD PHOTOELECTRIC SHENZHEN CO., LTD." }, - { 0x1EC1, "PROTEK DEVICES" }, - { 0x1EC2, "CHUO ELECTRONICS CO., LTD." }, - { 0x1EC3, "ANDREAS STIHL AG & Co. KG" }, - { 0x1EC4, "ELTRONIC SOLUTION A/S" }, - { 0x1EC5, "SIDSA" }, - { 0x1EC6, "PHYWORKS LTD." }, - { 0x1EC7, "Gefen Inc." }, - { 0x1EC8, "TelePath Technologies Co., Ltd." }, - { 0x1EC9, "MOSER BAER INDIA LIMITED" }, - { 0x1ECA, "Mintpass Co., Ltd." }, - { 0x1ECB, "Advanced Mobile Telecom Co., Ltd." }, - { 0x1ECC, "Enfora, Inc." }, - { 0x1ECD, "Alverix Inc." }, - { 0x1ECE, "MyungMin Systems, Inc." }, - { 0x1ECF, "MDR Grup S.R.L." }, - { 0x1ED0, "Hirschmann Car Communication GmbH" }, - { 0x1ED1, "DIGITAL CHINA NETWORKS (BEIJING) LIMITED" }, - { 0x1ED2, "Crevis Co., Ltd." }, - { 0x1ED3, "Forsis GmbH" }, - { 0x1ED4, "Transwitch (Israel) Ltd." }, - { 0x1ED5, "LLC GlobalTest" }, - { 0x1ED6, "adidas International" }, - { 0x1ED7, "Headplay, Inc." }, - { 0x1ED8, "Fender Musical Instruments Corp." }, - { 0x1ED9, "ALBUMteam, Ltd." }, - { 0x1EDA, "AIRTIES WIRELESS NETWORKS" }, - { 0x1EDB, "BLACKMAGIC DESIGN PTY." }, - { 0x1EDC, "B-DeltaCom" }, - { 0x1EDD, "IRIDIUM SATELLITE LLC" }, - { 0x1EDE, "steute Schaltgerate GmbH & Co. KG" }, - { 0x1EDF, "Selectwireless Co., Ltd." }, - { 0x1EE0, "KYUDEN TECHNOSYSTEMS CORPORATION" }, - { 0x1EE1, "Matrix Key Inc." }, - { 0x1EE2, "NOVA GAMING" }, - { 0x1EE3, "3D INNOVATIONS, LLC" }, - { 0x1EE4, "Luff Technology Co., Ltd." }, - { 0x1EE5, "Spring Soft K.K." }, - { 0x1EE6, "SHENZHEN EVERWIN PRECISION TECHNOLOGY CO., LTD." }, - { 0x1EE7, "EPCOS" }, - { 0x1EE8, "ONDA COMMUNICATION S.p.a." }, - { 0x1EE9, "PC PARTNER LIMITED" }, - { 0x1EEA, "Yullin Technologies Co., Ltd." }, - { 0x1EEB, "GEOTATE" }, - { 0x1EEC, "CTC Analytics AG" }, - { 0x1EED, "Helo Oy / Helo Ltd." }, - { 0x1EEE, "RigiSystems AG" }, - { 0x1EEF, "I.C.Y. B.V." }, - { 0x1EF0, "Thunder Tiger Corp." }, - { 0x1EF1, "PQ Computing Ltd." }, - { 0x1EF2, "Vircion Inc." }, - { 0x1EF3, "JIANGXI SHIP ELECTRONICS CO., LTD." }, - { 0x1EF4, "TATA ELXSI LTD." }, - { 0x1EF5, "Impinj, Inc." }, - { 0x1EF6, "EADS Deutschland GmbH" }, - { 0x1EF7, "ZiiLABS Ltd." }, - { 0x1EF8, "CRITICAL LINK, LLC" }, - { 0x1EF9, "US Army Electronic Proving Ground" }, - { 0x1EFA, "SEIKO Precision Inc." }, - { 0x1EFB, "IMI Hydronic Engineering International SA" }, - { 0x1EFC, "IMOGEN STUDIO" }, - { 0x1EFD, "ROFIN-SINAR LASER GMBH" }, - { 0x1EFE, "Sound Design Technologies" }, - { 0x1EFF, "Kinemetrics, Inc." }, - { 0x1F00, "YUEQING ZHONGLI COMPUTER ELECTRONICS CO., LTD." }, - { 0x1F01, "Geo Studio Technology" }, - { 0x1F02, "Australian National University" }, - { 0x1F03, "PTW Freiburg GmbH" }, - { 0x1F04, "Watlow" }, - { 0x1F05, "Kyosai Technos Co., Ltd." }, - { 0x1F06, "K.T.E.-Keter Technologies Europe" }, - { 0x1F07, "OPTOQUEST Co., Ltd." }, - { 0x1F08, "Digital Ally Inc." }, - { 0x1F09, "DURAG GmbH" }, - { 0x1F0A, "AUROX Ltd." }, - { 0x1F0B, "INTRONIX TEST INSTURMENTS, INC." }, - { 0x1F0C, "Fourier Systems Ltd." }, - { 0x1F0D, "NAMOS" }, - { 0x1F0E, "Inflexis Corporation" }, - { 0x1F0F, "Action Technology (SZ) Co., Ltd." }, - { 0x1F10, "LTW TECHNOLOGY CO., LTD." }, - { 0x1F11, "VIRAGE LOGIC" }, - { 0x1F12, "Photometrics" }, - { 0x1F13, "CENTURY SYSTEMS Co., Ltd." }, - { 0x1F14, "Astoria Networks GmbH" }, - { 0x1F15, "Schmitt Industries Inc." }, - { 0x1F16, "Olidata SpA" }, - { 0x1F17, "APIS Device, Inc." }, - { 0x1F18, "Teseq GmbH" }, - { 0x1F19, "POLATIS INC." }, - { 0x1F1A, "Sanden Retail Systems Corporation" }, - { 0x1F1B, "NORTHROP GRUMMAN SPERRY MARINE" }, - { 0x1F1C, "LXE, INC." }, - { 0x1F1D, "How Weih Precision Technology (Shenzhen) Co., Ltd." }, - { 0x1F1E, "TSIEN (UK) LTD." }, - { 0x1F1F, "RaaX Co., Ltd." }, - { 0x1F20, "Shenzhen Tenwei Electronics Co., Ltd." }, - { 0x1F21, "Scosche Industries" }, - { 0x1F22, "STAr Technologies, Inc." }, - { 0x1F23, "KOUEI SYSTEM, LTD." }, - { 0x1F24, "EBTRON INC." }, - { 0x1F25, "Victron Energy B.V." }, - { 0x1F26, "INCAP GmbH" }, - { 0x1F27, "KEE Action Sports (Hater Paintball)" }, - { 0x1F28, "Cal-Comp Electronics & Communications" }, - { 0x1F29, "Analogix Semiconductor, Inc." }, - { 0x1F2A, "Scene Double Ltd." }, - { 0x1F2B, "JUKI CORPORATION" }, - { 0x1F2C, "SELESTA INGEGNERIA SPA" }, - { 0x1F2D, "Liteye Systems, Inc." }, - { 0x1F2E, "ARMOUR GROUP PLC." }, - { 0x1F2F, "UPOS SYSTEM SP. Z O.O." }, - { 0x1F30, "RENA GmbH" }, - { 0x1F31, "SASKEN COMMUNICATION TECH LTD." }, - { 0x1F32, "COCHLEAR TECHNOLOGY CENTRE BELGIUM" }, - { 0x1F33, "GrupoPIE Portugal, S.A." }, - { 0x1F34, "Dutronics" }, - { 0x1F35, "Amphenol ShouhMin Industry (ShenZhen) Co., Ltd" }, - { 0x1F36, "ddm hopt + schuler GmbH & Co. KG" }, - { 0x1F37, "Next Step Solutions Limited" }, - { 0x1F38, "Kesumo, LLC" }, - { 0x1F39, "Sumitomo Electric Networks, Inc." }, - { 0x1F3A, "Allwinner Technology Co., Ltd." }, - { 0x1F3B, "Biocryptodisk Sdn Bhd" }, - { 0x1F3C, "Chang Yang Electronics Company Ltd." }, - { 0x1F3D, "Advanced Engineering Services Co., Ltd." }, - { 0x1F3E, "Telenot Electronic GmbH" }, - { 0x1F3F, "SECA GmbH & Co. KG" }, - { 0x1F40, "JiangSu Dongda Integrated Circuits Sys. Eng. Tech. Co." }, - { 0x1F41, "Nipro Diagnostics, Inc" }, - { 0x1F42, "ID2P TECHNOLOGIES, INC." }, - { 0x1F43, "RAPID BRIDGE LLC" }, - { 0x1F44, "Digital Business Process (dba: The Neat Company)" }, - { 0x1F45, "QUALCOMM ENTERPRISE SERVICES" }, - { 0x1F46, "Gener8, Inc." }, - { 0x1F47, "Orb Networks, Inc." }, - { 0x1F48, "H-TRONIC GmbH" }, - { 0x1F49, "Exelis, Inc." }, - { 0x1F4A, "Key Ingredient Corporation" }, - { 0x1F4B, "Precision System Science Co., Ltd." }, - { 0x1F4C, "Cyber Sport Pty., Ltd." }, - { 0x1F4D, "SHENZHEN GENIATECH INC., LTD." }, - { 0x1F4E, "OFF-NET SERVICE LIMITED" }, - { 0x1F4F, "EXAR CORPORATION - JAPAN" }, - { 0x1F50, "KEMPPI OY" }, - { 0x1F51, "Helmut Hund GmbH" }, - { 0x1F52, "Systems & Electronic Development FZCO (SEDCO)" }, - { 0x1F53, "SK telesys" }, - { 0x1F54, "LOEC, INC." }, - { 0x1F55, "Fujitsu Electronics Europe GmbH" }, - { 0x1F56, "MUT" }, - { 0x1F57, "PIGNOLO S.P.A." }, - { 0x1F58, "Inmarsat" }, - { 0x1F59, "EL.MO. S.P.A." }, - { 0x1F5A, "Micronova srl." }, - { 0x1F5B, "KYODO COMMUNICATIONS & ELECTRONICS INC." }, - { 0x1F5C, "MIDORI ANZEN CO., LTD." }, - { 0x1F5D, "Mobii Systems (Pty) Ltd." }, - { 0x1F5E, "Johnson Outdoors Marine Electronics, Inc." }, - { 0x1F5F, "NETCLEUS SYSTEMS Corporation" }, - { 0x1F60, "Young at Heart International Ltd." }, - { 0x1F61, "Flexocard GmbH" }, - { 0x1F62, "Elquest Corporation" }, - { 0x1F63, "IriTech, Inc." }, - { 0x1F64, "actionXL, Inc." }, - { 0x1F65, "Taylor Technologies, Co., Ltd." }, - { 0x1F66, "Hokkaido Electronics Corporation" }, - { 0x1F67, "MICRO INNOVATIONS CORP." }, - { 0x1F68, "General Dynamics UK Limited" }, - { 0x1F69, "NVIS, Inc." }, - { 0x1F6A, "AJA VIDEO SYSTEMS INC." }, - { 0x1F6B, "Muve, Inc." }, - { 0x1F6C, "Cadex Electronics Inc." }, - { 0x1F6D, "AMTI" }, - { 0x1F6E, "AccuVein LLC" }, - { 0x1F6F, "ALIPHCOM, INC." }, - { 0x1F70, "MKD Technology Inc." }, - { 0x1F71, "Huaya Microelectronics (HK) Ltd." }, - { 0x1F72, "GM INSTRUMENTS LTD." }, - { 0x1F73, "Record4Free.TV AG" }, - { 0x1F74, "UNISTO Ltd." }, - { 0x1F75, "Innostor Co., Ltd." }, - { 0x1F76, "CYBER-RAIN, INC." }, - { 0x1F77, "POSITRON PUBLIC SAFETY SYSTEMS" }, - { 0x1F78, "UNION TOOL CO." }, - { 0x1F79, "Rosen Technology and Research Center GmbH" }, - { 0x1F7A, "WhiteOak Controls Inc." }, - { 0x1F7B, "AVMAP SRL" }, - { 0x1F7C, "Voltopia e.U." }, - { 0x1F7D, "UNICARD S.A." }, - { 0x1F7E, "Canon India Private Limited" }, - { 0x1F7F, "NOVA Sensors" }, - { 0x1F80, "MagicPixel Inc." }, - { 0x1F81, "HYB D.O.O." }, - { 0x1F82, "TANDBERG TELECOM AS" }, - { 0x1F83, "Beauty Up Co., Ltd." }, - { 0x1F84, "Inverness Medical Innovations, Inc." }, - { 0x1F85, "Netronix Inc." }, - { 0x1F86, "Skyworth Overseas Development Limited" }, - { 0x1F87, "STANTUM" }, - { 0x1F88, "Modu Ltd." }, - { 0x1F89, "Dongguan Goldconn Electronics Co., Ltd." }, - { 0x1F8A, "Morning Star Industrial Co., Ltd." }, - { 0x1F8B, "Rittal GmbH & Co. KG" }, - { 0x1F8C, "Reference, LLC." }, - { 0x1F8D, "DEVICE FUNCTIONS" }, - { 0x1F8E, "SENSE INSIDE GmbH" }, - { 0x1F8F, "Narda Safety Test Solutions GmbH" }, - { 0x1F90, "PURE TECHNOLOGIES" }, - { 0x1F91, "Wilhelm Mikroelektronik GmbH" }, - { 0x1F92, "INTERNATIONAL TECHNIDYNE CORP." }, - { 0x1F93, "Alcohol Monitoring Systems, Inc." }, - { 0x1F94, "Microhard Systems Inc." }, - { 0x1F95, "Art of Technology AG" }, - { 0x1F96, "Ascend Geo, LLC" }, - { 0x1F97, "OZMO, INC. DBA OZMO DEVICES" }, - { 0x1F98, "DSP Design Limited" }, - { 0x1F99, "TOKAI RIKEN CO., LTD." }, - { 0x1F9A, "Barron Associates, Inc." }, - { 0x1F9B, "UBIQUITI Networks, Inc." }, - { 0x1F9C, "ARVOO Engineering BV" }, - { 0x1F9D, "Tri Works" }, - { 0x1F9E, "MUTECH LIMITED" }, - { 0x1F9F, "CasaTools, LLC" }, - { 0x1FA0, "XLNT IDEA, INC." }, - { 0x1FA1, "Curtis Instruments, Inc." }, - { 0x1FA2, "AMETEK DENMARK A/S" }, - { 0x1FA3, "LAIRD TECHNOLOGIES" }, - { 0x1FA4, "BRIDGEPORT INSTRUMENTS, LLC" }, - { 0x1FA5, "DELTA DORE" }, - { 0x1FA6, "Daylight Solutions, Inc." }, - { 0x1FA7, "COSMOS WEB CO., LTD." }, - { 0x1FA8, "TCL Technoly Electronics (Hui Zhou) Co., Ltd." }, - { 0x1FA9, "Digital Information Technologies Corporation" }, - { 0x1FAA, "Zhong Shan City Li Tai Electronic Industrial Co., Ltd." }, - { 0x1FAB, "SAMSUNG DIGITAL IMAGING CO., LTD." }, - { 0x1FAC, "Franklin Technology Inc." }, - { 0x1FAD, "Cresta Technology Inc." }, - { 0x1FAE, "Lumidigm, Inc." }, - { 0x1FAF, "Weintek Labs, Inc." }, - { 0x1FB0, "Discera, Inc." }, - { 0x1FB1, "Weatronic GmbH" }, - { 0x1FB2, "WITHINGS" }, - { 0x1FB3, "Matchbeeper AB" }, - { 0x1FB4, "Owl Computing Technologies, Inc." }, - { 0x1FB5, "Unify Software and Solutions GmbH & Co. KG" }, - { 0x1FB6, "SheKel" }, - { 0x1FB7, "J & D Tech Co., Ltd." }, - { 0x1FB8, "DORMA TIME + ACCESS GmbH" }, - { 0x1FB9, "Lake Shore Cryotronics, Inc." }, - { 0x1FBA, "DERMALOG Identification Systems GmbH" }, - { 0x1FBB, "PC Worth Int'l Co., Ltd." }, - { 0x1FBC, "Kurzweil Education Systems, Inc." }, - { 0x1FBD, "STACK LTD." }, - { 0x1FBE, "CGS" }, - { 0x1FBF, "OVAL Corporation" }, - { 0x1FC0, "JUNE-ON Co., Ltd." }, - { 0x1FC1, "Blue Chip Technology Limited" }, - { 0x1FC2, "Poken SA" }, - { 0x1FC3, "ICOP Digital, Inc." }, - { 0x1FC4, "Alfons Haar Maschinenbau GmbH & Co. KG" }, - { 0x1FC5, "Adaxys Solutions AG" }, - { 0x1FC6, "LAUREL BANK MACHINES CO., LTD." }, - { 0x1FC7, "mrs GmbH" }, - { 0x1FC8, "Medis Technologies Ltd." }, - { 0x1FC9, "NXP Semiconductors" }, - { 0x1FCA, "ON TIM Technologies Ltd." }, - { 0x1FCB, "Thermo Process Instruments" }, - { 0x1FCC, "Hiro" }, - { 0x1FCD, "Aurora Scientific Inc." }, - { 0x1FCE, "WEBSCAN Inc." }, - { 0x1FCF, "ACK Co., Ltd." }, - { 0x1FD0, "GILSON S.A.S." }, - { 0x1FD1, "TEKWorx Limited" }, - { 0x1FD2, "LG Display Co., Ltd." }, - { 0x1FD3, "ASK SA" }, - { 0x1FD4, "FINSECUR" }, - { 0x1FD5, "Dream Multimedia GmbH" }, - { 0x1FD6, "Logitek Electronic Systems, Inc." }, - { 0x1FD7, "ASELSAN Elektronik Sanayi ve Ticaret. A.S." }, - { 0x1FD8, "Guangzhou Tianhe Changjiang Communication Industrial Co" }, - { 0x1FD9, "Knox Company" }, - { 0x1FDA, "Beckwith Electric Co., Inc." }, - { 0x1FDB, "Delphin Technology AG" }, - { 0x1FDC, "HOSA TECHNOLOGY, INC." }, - { 0x1FDD, "CHASE GLORY INDUSTRIAL LTD." }, - { 0x1FDE, "ILX Lightwave" }, - { 0x1FDF, "SEPURA PLC" }, - { 0x1FE0, "REALFLEET Co., Ltd." }, - { 0x1FE1, "Ubixum, Inc." }, - { 0x1FE2, "Aetas Systems Inc." }, - { 0x1FE3, "Amaranthine, LLC" }, - { 0x1FE4, "HANDY TECH ELEKTRONIK GmbH" }, - { 0x1FE5, "KUKA Roboter GmbH" }, - { 0x1FE6, "BOOKHAM INC." }, - { 0x1FE7, "VERTEX WIRELESS CO., LTD." }, - { 0x1FE8, "103mm Tech" }, - { 0x1FE9, "Harvard Bioscience" }, - { 0x1FEA, "SIMPLO TECHNOLOGY CO., LTD." }, - { 0x1FEB, "Tecella" }, - { 0x1FEC, "NIAN YEONG ENTERPRISE CO., LTD." }, - { 0x1FED, "SYSACOM R&D Plus Inc." }, - { 0x1FEE, "GALILEO ENGINEERING SRL" }, - { 0x1FEF, "RESOL - Elektronische Regelungen GmbH" }, - { 0x1FF0, "Kyoto Electronics Manufacturing Co., Ltd." }, - { 0x1FF1, "Remote Operations Solutions" }, - { 0x1FF2, "Carl Valentin GmbH" }, - { 0x1FF3, "SINTEF Energy Research" }, - { 0x1FF4, "HYUNDAI PETATEL INC." }, - { 0x1FF5, "Changzhou Wujin BEST Electronic Cables Co., Ltd." }, - { 0x1FF6, "ClickTech LLC" }, - { 0x1FF7, "Guangzhou Shi Rui Electronics Co., Ltd." }, - { 0x1FF8, "Infinite Memories" }, - { 0x1FF9, "Schulze Elektronik GmbH" }, - { 0x1FFA, "ARYGON Technologies AG" }, - { 0x1FFB, "Pololu Corporation" }, - { 0x1FFC, "Azimut Production Association JSC" }, - { 0x1FFD, "TESSERA, INC." }, - { 0x1FFE, "HOST ENGINEERING, INC." }, - { 0x1FFF, "Ideofy Inc." }, - { 0x2000, "RongTong Info & Tech Co., Ltd." }, - { 0x2001, "D-Link Corporation" }, - { 0x2002, "DAP Technologies Ltd." }, - { 0x2003, "detectomat GmbH" }, - { 0x2004, "Shanghai Bellmann Digital Source Co., Ltd." }, - { 0x2005, "Balluff GmbH" }, - { 0x2006, "Lenovo Mobile Communication Technology Ltd." }, - { 0x2007, "LEYIO" }, - { 0x2008, "ThingMagic, Inc." }, - { 0x2009, "MPEDIA" }, - { 0x200A, "ADVANCED RELAY CORP." }, - { 0x200B, "TRANSISTOR DEVICES INC." }, - { 0x200C, "HANPIN ELECTRON CO., LTD." }, - { 0x200D, "Belkin Electronic (Changzhou) Co., Ltd." }, - { 0x200E, "DAIICHI PARTS (HK) CO., LTD." }, - { 0x200F, "Progind Srl" }, - { 0x2010, "Tectonica Australia Pty. Ltd." }, - { 0x2011, "SHENZHEN HEXIN COM. TECH. CO., LTD." }, - { 0x2012, "Applied Radar, Inc." }, - { 0x2013, "PCTV Systems" }, - { 0x2014, "ONKEN CORPORATION" }, - { 0x2015, "Shenzhen Ephone Communication Technology Co., Ltd." }, - { 0x2016, "Norbit AS" }, - { 0x2017, "NAL Research Corporation" }, - { 0x2018, "SilverPAC, Inc." }, - { 0x2019, "Electronics Development Corp." }, - { 0x201A, "Vortran Laser Technology, Inc." }, - { 0x201B, "1064138 Ontario Ltd. O/A UNI-TEC ELECTRONICS" }, - { 0x201C, "Freeport Resources Enterprises Corp." }, - { 0x201D, "Dongguan Shunhui Electronic Co., Ltd." }, - { 0x201E, "Qingdao Haier Telecom Co., Ltd." }, - { 0x201F, "W.E.M. INC." }, - { 0x2020, "Shanghai BroadMobi Communication Technology Co., Ltd." }, - { 0x2021, "Smartd ltd" }, - { 0x2022, "AMICON Ltd." }, - { 0x2023, "Berthold Technologies GmbH & Co. KG" }, - { 0x2024, "Shoto Technologies LLC" }, - { 0x2025, "NANOSENSE" }, - { 0x2026, "EASUN REYROLLE LIMITED" }, - { 0x2027, "LOAD SYSTEMS INTERNATIONAL, INC." }, - { 0x2028, "DETAS TECHNOLOGY LTD." }, - { 0x2029, "MYTRAK HEALTH SYSTEM INC." }, - { 0x202A, "Fast Forward Video, Inc." }, - { 0x202B, "Damalini AB" }, - { 0x202C, "Enhanced Vision" }, - { 0x202D, "Snowbush IP (a division of Gennum)" }, - { 0x202E, "Lumio Inc." }, - { 0x202F, "US ARMY RDECOM-ARDEC" }, - { 0x2030, "VITEC Multimedia" }, - { 0x2031, "Vistec AG" }, - { 0x2032, "GFMesstechnik GmbH" }, - { 0x2033, "WYMA Tecnologia Ltda." }, - { 0x2034, "iSoft Silicon, Inc." }, - { 0x2035, "seowonintech" }, - { 0x2036, "Eitech Co., Ltd." }, - { 0x2037, "Control Devices Australia Pty., Ltd." }, - { 0x2038, "Wescor Inc." }, - { 0x2039, "SE-Elektronic GmbH" }, - { 0x203A, "Parallels, Inc." }, - { 0x203B, "EIT, Inc." }, - { 0x203C, "Steptechnica Co., Ltd." }, - { 0x203D, "Encore Electronics" }, - { 0x203E, "Pascher Instruments AB" }, - { 0x203F, "WPG System Pte. Ltd." }, - { 0x2040, "Hauppauge Computer Works, Inc." }, - { 0x2041, "WILL BEST (ELECTRONICS) LTD." }, - { 0x2042, "Eberspaecher Electronics GmbH & Co. KG" }, - { 0x2043, "Mobius Microsystems" }, - { 0x2044, "NOVUS PRODUTOS ELETRONICOS LTDA." }, - { 0x2045, "EMH - Energie-Messtechnik GmbH" }, - { 0x2046, "AbleNet Inc." }, - { 0x2047, "Texas Instruments Incorporated (MSP430 Group)" }, - { 0x2048, "Hongtech Electronics Co., Ltd." }, - { 0x2049, "APACEWAVE TECHNOLOGIES" }, - { 0x204A, "Enclustra GmbH" }, - { 0x204B, "HANSHIN INFORMATION TECHNOLOGY INC." }, - { 0x204C, "M7Lab., Co., Ltd." }, - { 0x204D, "Orthodyne Electronics" }, - { 0x204E, "LINO MANFROTTO + CO. S.P.A." }, - { 0x204F, "VIDEOTEC SpA" }, - { 0x2050, "CBF Systems, Inc." }, - { 0x2051, "N.A.T. GmbH" }, - { 0x2052, "Movidius Ltd." }, - { 0x2053, "HANSHIN TERMINAL CO., LTD." }, - { 0x2054, "Source R & D Inc. (DBA WARPIA)" }, - { 0x2055, "Opti B. I. Communications, Ltd." }, - { 0x2056, "CliniComp International Inc." }, - { 0x2057, "DICE ELECTRONICS, LLC" }, - { 0x2058, "NANO RIVER TECHNOLOGIES" }, - { 0x2059, "SMART Temps LLC" }, - { 0x205A, "Hankook Tire" }, - { 0x205B, "TRUMPF Medizin Systeme GmbH" }, - { 0x205C, "Shenzhen Tronixin Electronics Co., Ltd." }, - { 0x205D, "RESMED LTD." }, - { 0x205E, "CTI PRODUCTS, Inc." }, - { 0x205F, "Capella Microsystems Inc." }, - { 0x2060, "U.S. Army Aviation & Missile R & D & Engineering Center" }, - { 0x2061, "FIGMENT DESIGN LABORATORIES" }, - { 0x2062, "Trulife" }, - { 0x2063, "AirMagnet Inc." }, - { 0x2064, "Shenzhen AnNet Technology Co., Ltd." }, - { 0x2065, "MEASUREMENT SPECIALTIES INC." }, - { 0x2066, "Unicorn Electronics Components Co., Ltd." }, - { 0x2067, "TSB LAO COMPANY LIMITED" }, - { 0x2068, "Seven 45 Studios" }, - { 0x2069, "Vanguard Rugged Storage, LLC" }, - { 0x206A, "Fujian Star-net Communication Co., Ltd." }, - { 0x206B, "CETIM" }, - { 0x206C, "Seeker Technology Corp." }, - { 0x206D, "Hunan GreatWall Information Financial Equipment Co.Ltd." }, - { 0x206E, "ZAO MIRCOM" }, - { 0x206F, "JTOUCH Corporation" }, - { 0x2070, "Infinite Response, Inc." }, - { 0x2071, "SYSTEM S.P.A." }, - { 0x2072, "GOOD YEAR ELECTRONIC MFG. CO., LTD." }, - { 0x2073, "Shenzhen R-Way Technology Co., Ltd." }, - { 0x2074, "UNIVERSAL CHAMPION ELECTROACOUSTIC TECHNOLOGY COMPANY" }, - { 0x2075, "SecureKey Technologies Inc." }, - { 0x2076, "SHINKAWA Sensor Technology, Inc." }, - { 0x2077, "Shenzhen Gongjin Electronics Co., Ltd." }, - { 0x2078, "Epsilon Electronics, Inc dba Power Acoustik Electronics" }, - { 0x2079, "New Concept Gaming Ltd." }, - { 0x207A, "C.E.T.W.I.N System Solutions Sweden AB" }, - { 0x207B, "Technetix Group Ltd." }, - { 0x207C, "NESA International, Inc." }, - { 0x207D, "CESI Technology Co., Ltd." }, - { 0x207E, "ENHANCED VIDEO DEVICES, INC." }, - { 0x207F, "Profound BV" }, - { 0x2080, "Barnes and Noble" }, - { 0x2081, "UTRONIX Elektronikutreckling AB" }, - { 0x2082, "EKOMINI INC." }, - { 0x2083, "XEL SOLUTIONS LTD." }, - { 0x2084, "I Zone Technologies Co., Ltd." }, - { 0x2085, "SIXENSE ENTERTAINMENT INC." }, - { 0x2086, "SHENZHEN CATIC INFORMATION TECHNOLOGY INDUSTRY CO., LTD" }, - { 0x2087, "Cando Corporation" }, - { 0x2088, "WALTON CHAINTECH CORPORATION" }, - { 0x2089, "microdrones GmbH" }, - { 0x208A, "TECHNO ROAD Inc." }, - { 0x208B, "KONTRON EMBEDDED COMPUTERS GmbH" }, - { 0x208C, "Linkbit, Inc." }, - { 0x208D, "Attero Tech, LLC" }, - { 0x208E, "Luxshare-ICT" }, - { 0x208F, "Chi Mei Optoelectronics Corporation" }, - { 0x2090, "Transition Networks" }, - { 0x2091, "Callpod, Inc." }, - { 0x2092, "Logina" }, - { 0x2093, "Ambu A/S" }, - { 0x2094, "Yoostar Entertainment Group, Inc." }, - { 0x2095, "CE LINK LIMITED" }, - { 0x2096, "Shenzhen Microconn Investment and Development Co., Ltd." }, - { 0x2097, "USBPARTNER" }, - { 0x2098, "TouchTable, Inc." }, - { 0x2099, "Systematic Development Group, LLC" }, - { 0x209A, "Avedis Zildjian Company" }, - { 0x209B, "SATEL OY" }, - { 0x209C, "iPulse Systems" }, - { 0x209D, "Vector Co., Ltd." }, - { 0x209E, "GlideTV Inc." }, - { 0x209F, "Alcolizer Technology" }, - { 0x20A0, "Flirc" }, - { 0x20A1, "BRAINZSQUARE CO., LTD." }, - { 0x20A2, "SCANMATIK" }, - { 0x20A3, "Sterilucent" }, - { 0x20A4, "Itron Metering Solutions" }, - { 0x20A5, "Cardiorobotics, Inc." }, - { 0x20A6, "ZheJiang SEENSUN Communication&Electronic Equipment Co." }, - { 0x20A7, "GREAT LUSTRE (SPEEDY) CO., LTD." }, - { 0x20A8, "nLighten Technologies (Shanghai) Co., Ltd." }, - { 0x20A9, "Autotronic Controls Corp." }, - { 0x20AA, "ED-CONTRIVE Co., Ltd." }, - { 0x20AB, "Identification International, Inc." }, - { 0x20AC, "Wintek Corporation" }, - { 0x20AD, "Japan Probe Co., Ltd." }, - { 0x20AE, "SoCChip (Wuxi Youxin IC Design Co., Ltd.)" }, - { 0x20AF, "Shenzhen CARVE Electronics Co., Ltd." }, - { 0x20B0, "ICOMM TELE LIMITED" }, - { 0x20B1, "XMOS Ltd." }, - { 0x20B2, "Clubbhouse Inventions LLC" }, - { 0x20B3, "Hannstouch Solution Inc." }, - { 0x20B4, "SANDBRIDGE TECHNOLOGIES, INC." }, - { 0x20B5, "ACD Gruppe" }, - { 0x20B6, "Bohle AG" }, - { 0x20B7, "Qi Hardware, Inc." }, - { 0x20B8, "PARA INDUSTRIAL CO., LTD." }, - { 0x20B9, "TLAY Technologies Co., Ltd." }, - { 0x20BA, "jwin Electronics Corp." }, - { 0x20BB, "THALES TRANSPORTATION SYSTEMS" }, - { 0x20BC, "Guangzhou Pingzhong Electronic Technology Co., Ltd." }, - { 0x20BD, "KETEK" }, - { 0x20BE, "BURY GmbH & Co. KG" }, - { 0x20BF, "Dwyer Instruments, Inc." }, - { 0x20C0, "FENGHUA KINGSUN CO., LTD." }, - { 0x20C1, "HARWIN ASIA PTE. LTD." }, - { 0x20C2, "Sumitomo Electric Ind., Ltd., Optical Comm. R&D Lab" }, - { 0x20C3, "TECNOMOTOR ELETRONICA DO BRASIL S/A" }, - { 0x20C4, "Communications Laboratories, Inc. (Comlabs)" }, - { 0x20C5, "A.U. Physics Enterprises" }, - { 0x20C6, "Mutto Optronics Corporation" }, - { 0x20C7, "HMC INTERNATIONAL" }, - { 0x20C8, "CEC TELECOM CO., LTD." }, - { 0x20C9, "SYSTEMCORP Pty., Ltd." }, - { 0x20CA, "TRIPHOS Co., Ltd." }, - { 0x20CB, "Dave Smith Instruments" }, - { 0x20CC, "TAKARA" }, - { 0x20CD, "Schweers Informationstechnologie GmbH" }, - { 0x20CE, "Mini-Circuits" }, - { 0x20CF, "Gridmark Limited" }, - { 0x20D0, "FRESENIUS VIAL" }, - { 0x20D1, "Dascom Europe GmbH" }, - { 0x20D2, "ROBOTEQ INC." }, - { 0x20D3, "Provo Craft" }, - { 0x20D4, "SCDi" }, - { 0x20D5, "Lenexpo Inc. (dba: Atlona)" }, - { 0x20D6, "Bensussen Deutsch & Associates, Inc. (BDA)" }, - { 0x20D7, "SHENZHEN ZILI ELECTRONICS CO. LTD." }, - { 0x20D8, "Changzhou Xinchao Technologies, Inc." }, - { 0x20D9, "ZHEJIANG YONGCHENGGONG DIANSU.CO., LTD." }, - { 0x20DA, "LumaSense Technologies A/S" }, - { 0x20DB, "KTS GmbH" }, - { 0x20DC, "KCS Digital, Inc." }, - { 0x20DD, "FORTREND TAIWAN SCIENTIFIC CORP." }, - { 0x20DE, "OneSail HK Ltd." }, - { 0x20DF, "SIMTEC ELECTRONICS" }, - { 0x20E0, "Realway Electronics Technology Limited" }, - { 0x20E1, "Daiichi Co., Ltd." }, - { 0x20E2, "ASEQ INSTRUMENTS" }, - { 0x20E3, "LAUDA DR.R.WOBSER GMBH & CO. KG" }, - { 0x20E4, "Onecell Technologies" }, - { 0x20E5, "Cardreader, Inc." }, - { 0x20E6, "Brooks Automation, Inc." }, - { 0x20E7, "Scientific Digital Imaging plc" }, - { 0x20E8, "Jow Tong Technology Co., Ltd." }, - { 0x20E9, "adp Gauselmann GmbH" }, - { 0x20EA, "CACTUS TECHNOLOGIES, LIMITED" }, - { 0x20EB, "AOS Technologies AG" }, - { 0x20EC, "AMBIR TECHNOLOGY, INC." }, - { 0x20ED, "TRANZFINITY, INC." }, - { 0x20EE, "Emotiva Audio Corp." }, - { 0x20EF, "TIGRIS Elektronik GmbH" }, - { 0x20F0, "Insight Technology Incorporated" }, - { 0x20F1, "NET GmbH" }, - { 0x20F2, "Secured Mobility" }, - { 0x20F3, "Flexcore" }, - { 0x20F4, "TRENDnet" }, - { 0x20F5, "MKS Instruments - Technology for Productivity" }, - { 0x20F6, "EXMAN ELECTRIC" }, - { 0x20F7, "XIMEA s.r.o." }, - { 0x20F8, "Guangzhou Somic Digital & Electronic Technology Co, Ltd" }, - { 0x20F9, "Medical Computer Systems, Ltd." }, - { 0x20FA, "IC Intracom" }, - { 0x20FB, "Aptina Imaging Corporation" }, - { 0x20FC, "PIE SOFT LAB CORPORATION" }, - { 0x20FD, "NOVO NORDISK A/S" }, - { 0x20FE, "Bittium USA Inc." }, - { 0x20FF, "PNI Sensor Corp." }, - { 0x2100, "RT Systems Inc." }, - { 0x2101, "NAS Technologies Corp." }, - { 0x2102, "Vitalograph Ltd." }, - { 0x2103, "OHMORI ELECTRIC INDUSTRIES CO., LTD." }, - { 0x2104, "Tobii AB" }, - { 0x2105, "Retail Innovation HTT AB" }, - { 0x2106, "Sharp Korea Corporation" }, - { 0x2107, "Amstore CD Production Ltd." }, - { 0x2108, "NEATO ROBOTICS" }, - { 0x2109, "VIA Labs, Inc." }, - { 0x210A, "PULSUS TECHNOLOGIES" }, - { 0x210B, "Work Microwave GmbH" }, - { 0x210C, "DOT HILL SYSTEMS" }, - { 0x210D, "Plastoform Industries Ltd." }, - { 0x210E, "Commscope" }, - { 0x210F, "Tyco / Scott Health & Safety" }, - { 0x2110, "carina system co., ltd." }, - { 0x2111, "alphaNUCLEAR Inc." }, - { 0x2112, "Point Of Pay Pty. Ltd." }, - { 0x2113, "Softkinetic" }, - { 0x2114, "Innovision Technology Corporation Ltd." }, - { 0x2115, "Alliance Material Co., Ltd." }, - { 0x2116, "KT Tech Inc." }, - { 0x2117, "Frama AG" }, - { 0x2118, "RF WINDOW" }, - { 0x2119, "MoreDNA Technology Co., Ltd." }, - { 0x211A, "PILLKEY HOLDING BV" }, - { 0x211B, "MENTOR GmbH & Co. Praezisions-Bauteile KG" }, - { 0x211C, "SWENC Technology Co., Ltd." }, - { 0x211D, "Mutualink, Inc." }, - { 0x211E, "Dongbu HiTek" }, - { 0x211F, "XINETWORKS CO., LTD." }, - { 0x2120, "Odirrus Limited" }, - { 0x2121, "Escort Data Logging Systems Ltd." }, - { 0x2122, "ZEDEL" }, - { 0x2123, "SYNTEK DEVELOPMENT LTD." }, - { 0x2124, "ELSAGDATAMAT S.P.A." }, - { 0x2125, "FIBERPRO INC." }, - { 0x2126, "SUZA INTERNATIONAL FRANCE" }, - { 0x2127, "FutureDial, Inc." }, - { 0x2128, "Naval Research Laboratory" }, - { 0x2129, "Tokushu Denshi Kairo, Inc." }, - { 0x212A, "Kappa optronics GmbH" }, - { 0x212B, "GR Telecom Co., Ltd." }, - { 0x212C, "Shenzhen Linoya Electronic Co., Ltd." }, - { 0x212D, "Dong Guan City Wanhong Electric Co., Ltd." }, - { 0x212E, "Amphenol AssembleTech (Xiamen) Co., Ltd." }, - { 0x212F, "SUZUKI MUSICAL INST. MFG. CO., LTD." }, - { 0x2130, "Sanmu Communication Technology (H.K.) Ltd." }, - { 0x2131, "IES Co., Ltd." }, - { 0x2132, "EDAS, Inc." }, - { 0x2133, "SIGNOTEC GmbH" }, - { 0x2134, "CANESTA, INC." }, - { 0x2135, "W.O.M. World of Medicine AG" }, - { 0x2136, "Compunow Trading Corp." }, - { 0x2137, "Beyonics Technology Limited" }, - { 0x2138, "iVina, Inc." }, - { 0x2139, "Eigenlabs Ltd." }, - { 0x213A, "Carlo Gavazzi" }, - { 0x213B, "UICO, Inc." }, - { 0x213C, "ICON Health & Fitness" }, - { 0x213D, "DRS Data & Imaging Systems, Inc." }, - { 0x213E, "Phase Matrix, Inc." }, - { 0x213F, "Digitron Instrumentation Ltd." }, - { 0x2140, "Sichuan Jiuzhou Electric Group Co., Ltd." }, - { 0x2141, "ZT Group Int'l, Inc." }, - { 0x2142, "Enginuity Communications" }, - { 0x2143, "InDevR Inc." }, - { 0x2144, "Sea Tel, Inc." }, - { 0x2145, "Ballard Technology" }, - { 0x2146, "Victorinox AG" }, - { 0x2147, "Chin-Ban Electronics (Hong Kong) Co., Ltd." }, - { 0x2148, "Visteon Sistemas Automotives Ltda." }, - { 0x2149, "MasTouch Optoelectronics Technologies Co., Ltd." }, - { 0x214A, "Interlink Electronics" }, - { 0x214B, "AMECO TECHNOLOGIES (SHENZHEN) CO., LTD." }, - { 0x214C, "Y Soft Corporation" }, - { 0x214D, "SyTech Corporation" }, - { 0x214E, "Swiftpoint Limited" }, - { 0x214F, "Attainment Company, Inc." }, - { 0x2150, "AZOTEQ (PTY) LTD." }, - { 0x2151, "SeaSpace Corporation" }, - { 0x2152, "AD Semiconductor Co., Ltd." }, - { 0x2153, "Mastertouch Solutions Electronics Co., Ltd." }, - { 0x2154, "Trace Lighting Ltd." }, - { 0x2155, "Teledyne Controls" }, - { 0x2156, "Weistech Technology Co., Ltd." }, - { 0x2157, "Digital Imaging Technology" }, - { 0x2158, "TA WEI TECHNOLOGY CO., LTD." }, - { 0x2159, "TRIASX Pty Ltd." }, - { 0x215A, "Sling Media, Inc." }, - { 0x215B, "2D Debus & Diebold Messsysteme GmbH" }, - { 0x215C, "OTOVATION, LLC" }, - { 0x215D, "GeNUA mbH" }, - { 0x215E, "ST Embedded Engineering, LLC" }, - { 0x215F, "DECIMATOR DESIGN PTY LTD." }, - { 0x2160, "PULOON Technology Inc." }, - { 0x2161, "BEA SA" }, - { 0x2162, "Prime Audio Inc." }, - { 0x2163, "Digital Rapids Corp." }, - { 0x2164, "Witek System" }, - { 0x2165, "CONTROL SOLUTIONS, INC." }, - { 0x2166, "JVC KENWOOD Corporation" }, - { 0x2167, "Zhejiang Fousine Science & Technology Co., Ltd." }, - { 0x2168, "TZYR HWEY ENTERPRISE CO., LTD." }, - { 0x2169, "TIANJIN SHENNAN INFORMATION SECURITY CO., LTD." }, - { 0x216A, "Shenzhen San Jing Electronics Co., Ltd." }, - { 0x216B, "XceedID Corporation" }, - { 0x216C, "UniDisplay Inc." }, - { 0x216D, "BENSON MEDICAL INSTRUMENTS" }, - { 0x216E, "KHOMP INDUSTRIA E COMERCIO LTDA" }, - { 0x216F, "ALTAIR SEMICONDUCTOR" }, - { 0x2170, "Wurtec, Inc." }, - { 0x2171, "Bokam Engineering, Inc." }, - { 0x2172, "Torrey Pines Logic, Inc." }, - { 0x2173, "HUIZHOU HUANGJI PRECISIONS FLEX ELECTRONICAL CO., LTD." }, - { 0x2174, "Transcend Information, Inc." }, - { 0x2175, "Light Blue Optics, Inc." }, - { 0x2176, "TMC - Allion Test Labs" }, - { 0x2177, "CHAUVIN ARNOUX" }, - { 0x2178, "Ion Science" }, - { 0x2179, "UGtizer Corp." }, - { 0x217A, "Triple Eye" }, - { 0x217B, "BDP Semiconductors Ltd." }, - { 0x217C, "Sensitech Inc." }, - { 0x217D, "Bilcare Technologies Singapore Pte. Ltd." }, - { 0x217E, "TP RADIO" }, - { 0x217F, "REAL EAR A/S" }, - { 0x2180, "Icare Finland Oy" }, - { 0x2181, "GLOBAL TRAFFIC TECHNOLOGIES, LLC" }, - { 0x2182, "XAC Automation Corp." }, - { 0x2183, "Bonutti Research" }, - { 0x2184, "GOOD WILL Instrument Co., Ltd." }, - { 0x2185, "FUJIWORK Co., Ltd." }, - { 0x2186, "Home Server Technologies Inc." }, - { 0x2187, "ESPACE SERVICES MULTIMEDIAS" }, - { 0x2188, "CalDigit, Inc." }, - { 0x2189, "SEMNTECH" }, - { 0x218A, "EXELYS LLC" }, - { 0x218B, "Blackbird Technologies Inc." }, - { 0x218C, "Gammadata Instrument AB" }, - { 0x218D, "Adaptive I/O Technologies, Inc." }, - { 0x218E, "UNITRO-Fleischmann" }, - { 0x218F, "DHEF INC." }, - { 0x2190, "esonic Co., Ltd." }, - { 0x2191, "SecureAT Co., Ltd." }, - { 0x2192, "FlexRadio Systems" }, - { 0x2193, "Schnick-Schnack-Systems GmbH" }, - { 0x2194, "ROTH + WEBER GmbH" }, - { 0x2195, "Hans Eckes Hardware & Software" }, - { 0x2196, "XPMOBILE" }, - { 0x2197, "W & D, LLC" }, - { 0x2198, "Wonde Proud Technology Co., Ltd." }, - { 0x2199, "Image and Information Technology" }, - { 0x219A, "COSMO ELECTRONICS CO., LTD." }, - { 0x219B, "TPK Touch Solutions Inc." }, - { 0x219C, "SEAL ONE AG" }, - { 0x219D, "BDR Technologies Ltd." }, - { 0x219E, "VALKEE OY" }, - { 0x219F, "VENTIS" }, - { 0x21A0, "AXELSPACE Corporation" }, - { 0x21A1, "EMOTIV SYSTEMS INC." }, - { 0x21A2, "ABB Low Voltage Products" }, - { 0x21A3, "Optcom Co., Ltd." }, - { 0x21A4, "ELECTRONIC ARTS" }, - { 0x21A5, "Genesis Technology USA, Inc." }, - { 0x21A6, "YUPITERU CORPORATION" }, - { 0x21A7, "PAYPRINT SRL" }, - { 0x21A8, "GE Intelligent Platforms, Inc." }, - { 0x21A9, "Saleae LLC" }, - { 0x21AA, "TAKASAKI KYODO COMPUTING CENTER CO., LTD." }, - { 0x21AB, "Planeta Informatica Ltda." }, - { 0x21AC, "infoSense Technology Inc." }, - { 0x21AD, "Wobbegong Fitness and Therapy Products Pty. Ltd." }, - { 0x21AE, "Philips and Neusoft Medical System Co., Ltd." }, - { 0x21AF, "Euro-CB Phils. Inc." }, - { 0x21B0, "Grace Industries, Incorporated" }, - { 0x21B1, "TATA CONSULTANCY SERVICES" }, - { 0x21B2, "Felix Meier GmbH" }, - { 0x21B3, "Dongguan Teconn Electronics Technology Co., Ltd." }, - { 0x21B4, "Wavelength Audio, Ltd." }, - { 0x21B5, "SHENZHEN JASON ELECTRONICS CO., LTD." }, - { 0x21B6, "EUROAVIONICS GmbH & Co. KG" }, - { 0x21B7, "STAIB INSTRUMENTE GmbH" }, - { 0x21B8, "KONTRONIK GmbH" }, - { 0x21B9, "ZP ENGINEERING s.r.l." }, - { 0x21BA, "SI2 MICROSYSTEMS, Ltd." }, - { 0x21BB, "WWPass Corporation" }, - { 0x21BC, "Skyhawke Technologies, LLC" }, - { 0x21BD, "Code Red Technologies, Ltd." }, - { 0x21BE, "KEC Co., Ltd." }, - { 0x21BF, "Mayo Clinic" }, - { 0x21C0, "PIXTREE, Inc." }, - { 0x21C1, "Baumann Electronic Controls, LLC" }, - { 0x21C2, "Shenzhen V-Interface Technology Co., Ltd." }, - { 0x21C3, "MASIMO LABORATORIES INC." }, - { 0x21C4, "Longsys Electronics (HK) Co., Ltd." }, - { 0x21C5, "Vukic Computer Instruments GmbH" }, - { 0x21C6, "PSS Hong Kong Limited" }, - { 0x21C7, "Unisoku Co., Ltd." }, - { 0x21C8, "IDONDEMAND INC." }, - { 0x21C9, "Innoteletek, Inc." }, - { 0x21CA, "RAE Systems Inc." }, - { 0x21CB, "Vodafone Ltd." }, - { 0x21CC, "ChipsWork Microelectronics Corp." }, - { 0x21CD, "Infoxelle Co., Ltd." }, - { 0x21CE, "Polostar Technology Corporation" }, - { 0x21CF, "HISATOMI ELECTRIC IND. CO., LTD." }, - { 0x21D0, "Red Rapids" }, - { 0x21D1, "ADDER TECHNOLOGY LTD." }, - { 0x21D2, "NeoLAB Convergence" }, - { 0x21D3, "Compupack Technology Co., Ltd." }, - { 0x21D4, "Eduplayer Co., Ltd." }, - { 0x21D5, "M.G.F." }, - { 0x21D6, "Agecodagis SARL" }, - { 0x21D7, "VINCIAMO, Inc." }, - { 0x21D8, "P & A Technologies, Inc." }, - { 0x21D9, "Verification Technology, Inc." }, - { 0x21DA, "Valor Auto Companion, Inc." }, - { 0x21DB, "G-Max Technology Co., Ltd." }, - { 0x21DC, "ABB S.p.A., Low Voltage Products Division" }, - { 0x21DD, "Looxcie, Inc." }, - { 0x21DE, "Cloud Engines, Inc." }, - { 0x21DF, "Quanser Consulting Inc." }, - { 0x21E0, "OpenPattern" }, - { 0x21E1, "CAEN S.P.A." }, - { 0x21E2, "Ascension Technology Corp." }, - { 0x21E3, "Crest Technology Inc." }, - { 0x21E4, "Xcellen Co., Ltd." }, - { 0x21E5, "Kruglov Evgeniy Vladimirovich" }, - { 0x21E6, "OCZ Technology Group" }, - { 0x21E7, "Sagemcom Broadband SAS" }, - { 0x21E8, "BOEHNKE + PARTNER GmbH Steuerungssysteme" }, - { 0x21E9, "Jiafuh Metal & Plastic (ShenZhen) Co., Ltd." }, - { 0x21EA, "JUST MAKE ELECTRONICS CO., LTD." }, - { 0x21EB, "KOKORO CO., LTD." }, - { 0x21EC, "ApniCure, Inc." }, - { 0x21ED, "Accuphase Laboratories, Inc." }, - { 0x21EE, "MAVIN TECHNOLOGY INC." }, - { 0x21EF, "FEMTO Messtechnik GmbH" }, - { 0x21F0, "LivingLab Development Co., Ltd." }, - { 0x21F1, "ABS Group AB" }, - { 0x21F2, "Palmer Environmental Ltd." }, - { 0x21F3, "Inspired Instruments Inc." }, - { 0x21F4, "Minebea Technologies Taiwan Co., Ltd." }, - { 0x21F5, "Shenzhen Strong Rising Electronics Co., Ltd." }, - { 0x21F6, "QSR Automations, Inc." }, - { 0x21F7, "Wuerth-Elektronik eiSos GmbH & Co. KG" }, - { 0x21F8, "Goeasily Int'l Co., Ltd." }, - { 0x21F9, "American Thermal Instruments" }, - { 0x21FA, "Pitsco, Inc." }, - { 0x21FB, "HELIOS Electronic Design & Manufacture" }, - { 0x21FC, "Thum + Mahr GmbH" }, - { 0x21FD, "Associated Controls (Australia) Pty., Limited" }, - { 0x21FE, "ELAP S.p.A." }, - { 0x21FF, "DEIF A/S" }, - { 0x2200, "Nuribom" }, - { 0x2201, "Elan Digital Systems Ltd." }, - { 0x2202, "Walex Electronic (Wu Xi) Co., Ltd." }, - { 0x2203, "Shin Shin Co., Ltd." }, - { 0x2204, "Innov-X Systems Inc." }, - { 0x2205, "3eYamaichi Electronics Co., Ltd." }, - { 0x2206, "Wiretek International Investment Ltd." }, - { 0x2207, "Fuzhou Rockchip Electronics Co., Ltd." }, - { 0x2208, "CONNFLY ELECTRONIC CO., LTD." }, - { 0x2209, "SPoT LLC" }, - { 0x220A, "Anton Paar GmbH" }, - { 0x220B, "IKARIA Holdings, Inc." }, - { 0x220C, "Island Technology Co., Ltd." }, - { 0x220D, "Humanline Co., Ltd." }, - { 0x220E, "NetComm Ltd." }, - { 0x220F, "Italdata Ingegneria Dell'Idea s.p.a." }, - { 0x2210, "Klavis Technologies" }, - { 0x2211, "FLUID COMPONENTS INTERNATIONAL LLC" }, - { 0x2212, "Dev-Audio Pty. Ltd. (Dev-Audio)" }, - { 0x2213, "Ascon Co., Ltd." }, - { 0x2214, "Pollin Electronic GmbH" }, - { 0x2215, "InCOMM Technologies Co., Ltd." }, - { 0x2216, "Environmental Systems Corporation" }, - { 0x2217, "FTS Forest Technology Systems Ltd." }, - { 0x2218, "Listen Technologies Corp." }, - { 0x2219, "Hogahm Technology" }, - { 0x221A, "ZTEX" }, - { 0x221B, "Kyodo Denshi Engineering Co., Ltd." }, - { 0x221C, "CORTEX TECHNOLOGY APS" }, - { 0x221D, "fischertechnik GmbH" }, - { 0x221E, "Linktec Technologies Co., Ltd." }, - { 0x221F, "Resolution Audio" }, - { 0x2220, "FAMAS SYSTEM S.P.A." }, - { 0x2221, "EnovateIT Inc." }, - { 0x2222, "SOFTMECHA" }, - { 0x2223, "Ratioplast-Optoelectronics GmbH" }, - { 0x2224, "LM Technologies Ltd." }, - { 0x2225, "GETT Geratetechnik GmbH" }, - { 0x2226, "PLANAR LLC" }, - { 0x2227, "Northtronics Pty., Ltd." }, - { 0x2228, "Dantec Dynamics A/S" }, - { 0x2229, "Key Technologies, Inc." }, - { 0x222A, "ILI TECHNOLOGY CORP." }, - { 0x222B, "ALPHAMEDIA CO., LTD." }, - { 0x222C, "TOHAN DENSHI KIKI Co., Ltd." }, - { 0x222D, "LEIFHEIT AG" }, - { 0x222E, "OXYSEC s.r.l." }, - { 0x222F, "Tcom Technology Co., Ltd." }, - { 0x2230, "Plugable Technologies" }, - { 0x2231, "Coregate Inc." }, - { 0x2232, "NAMUGA Co., Ltd." }, - { 0x2233, "ARGtek Communication Inc." }, - { 0x2234, "T-CONN PRECISION CORPORATION" }, - { 0x2235, "WoundVision" }, - { 0x2236, "ACELLA" }, - { 0x2237, "Kobo Inc." }, - { 0x2238, "ELMO Motion Control Ltd." }, - { 0x2239, "PEIKER acustic GmbH & Co., KG" }, - { 0x223A, "BKtel Communications GmbH" }, - { 0x223B, "Crystalfontz America, Inc." }, - { 0x223C, "Audio Research Corp." }, - { 0x223D, "AlfaPlus Semiconductor, Inc." }, - { 0x223E, "Home Electronics" }, - { 0x223F, "Oga, Inc." }, - { 0x2240, "NETTALK.COM INC." }, - { 0x2241, "Envision Interface Engineering, LLC" }, - { 0x2242, "Zhihe Electronics Technology Co., Ltd." }, - { 0x2243, "EMIC CORPORATION" }, - { 0x2244, "Kronos" }, - { 0x2245, "ASPEED Technology Inc." }, - { 0x2246, "Nanjing Frentec Co., Ltd." }, - { 0x2247, "CHUNGHWA PICTURE TUBES, LTD." }, - { 0x2248, "KAISE CORPORATION" }, - { 0x2249, "Long Range Systems, Inc." }, - { 0x224A, "ORMEC SYSTEMS CORP." }, - { 0x224B, "Sirit Inc." }, - { 0x224C, "Datron World Communications, Inc." }, - { 0x224D, "Tescom Co., Ltd." }, - { 0x224E, "RDH2 Science" }, - { 0x224F, "APDM, INC." }, - { 0x2250, "Evernew Wire & Cable Co., Ltd." }, - { 0x2251, "QuieTek Corp." }, - { 0x2252, "TSANSUN TECH. CO., LTD." }, - { 0x2253, "Arpage AG" }, - { 0x2254, "RPO" }, - { 0x2255, "COOPER WIRELESS" }, - { 0x2256, "Mathias Fuchss Software - Entwicklung" }, - { 0x2257, "On the Go Video, Inc." }, - { 0x2258, "D+H Mechatronic AG" }, - { 0x2259, "Skypine Electronics (Shenzhen) Co., Ltd." }, - { 0x225A, "Vivanco GmbH" }, - { 0x225B, "Lineage Power" }, - { 0x225C, "Digital Check Corp" }, - { 0x225D, "Sagem Securite" }, - { 0x225E, "Unholtz-Dickie Corp." }, - { 0x225F, "Ace Karaoke Corp." }, - { 0x2260, "Multigig, Inc." }, - { 0x2261, "DOM-Sicherheitstechnik GmbH & Co. KG" }, - { 0x2262, "VIETTEL GROUP" }, - { 0x2263, "Nuovations" }, - { 0x2264, "Entourage Systems, Inc." }, - { 0x2265, "DailyCare BioMedical Inc." }, - { 0x2266, "Psychology Software Tools, Inc." }, - { 0x2267, "Boreal Genomics" }, - { 0x2268, "EXSUSS, Inc." }, - { 0x2269, "Schlumberger Ltd." }, - { 0x226A, "Ooma, Inc." }, - { 0x226B, "Bruker Nano GmbH" }, - { 0x226C, "HAL Communications Corp." }, - { 0x226D, "Wrenchman, Inc." }, - { 0x226E, "DISPLAX" }, - { 0x226F, "Koyo Trading Co., Ltd." }, - { 0x2270, "XiaMen GaoLuChang Electronics Co. Ltd." }, - { 0x2271, "Karl Storz GmbH & Co. KG" }, - { 0x2272, "E.E.P.D." }, - { 0x2273, "IMAX Corporation" }, - { 0x2274, "Morgan Schaffer Inc." }, - { 0x2275, "ReliOn Inc." }, - { 0x2276, "Pioneer CBC" }, - { 0x2277, "Ortho Neuro Technologies, Inc." }, - { 0x2278, "Infratec Datentechnik GmbH" }, - { 0x2279, "Goossens Engineering" }, - { 0x227A, "FLOM Corporation" }, - { 0x227B, "CYBELEC SA" }, - { 0x227C, "S. & A.S. LTD." }, - { 0x227D, "Unitec Co., Ltd." }, - { 0x227E, "JSC " }, - { 0x227F, "Granite River Labs" }, - { 0x2280, "Life Technologies Corp." }, - { 0x2281, "GI CORPORATION" }, - { 0x2282, "Mamiya Digital Imaging Co., Ltd." }, - { 0x2283, "NIHON DEMPA KOGYO Co., Ltd." }, - { 0x2284, "SuperSonic Inc." }, - { 0x2285, "IRIS ID" }, - { 0x2286, "Altierre Corporation" }, - { 0x2287, "Shenzhen Oversea Win Technology Co., Ltd." }, - { 0x2288, "Dt&C (Digital Technology and Certification)" }, - { 0x2289, "Sun Fair Electric Wire & Cable (HK) Co., Ltd." }, - { 0x228A, "Hotron Precision Electronic Ind. Corp." }, - { 0x228B, "Shenzhen DLK Electronics Technology Co., Ltd." }, - { 0x228C, "Analogic Corporation" }, - { 0x228D, "8D TECHNOLOGIES INC." }, - { 0x228E, "EKO Instruments Co., Ltd." }, - { 0x228F, "SIGMATEK GmbH & Co. KG" }, - { 0x2290, "Touchplus information Corp." }, - { 0x2291, "Vallen Systeme GmbH" }, - { 0x2292, "Global Industrial Services, Ltd." }, - { 0x2293, "Berger Elektronik GmbH" }, - { 0x2294, "KoCo Connector AG" }, - { 0x2295, "Sound ID" }, - { 0x2296, "Musashi Engineering Company Limited" }, - { 0x2297, "Grain Media, Inc." }, - { 0x2298, "PULSION Medical Systems AG" }, - { 0x2299, "BRAIN VISION SYSTEMS (BVS)" }, - { 0x229A, "Control Express Finland OY" }, - { 0x229B, "SFC Smart Fuel Cell AG" }, - { 0x229C, "Raytheon Company" }, - { 0x229D, "Solacia Inc." }, - { 0x229E, "JV2R - MacWay" }, - { 0x229F, "RRC power solutions GmbH" }, - { 0x22A0, "Winpos System Co., Ltd." }, - { 0x22A1, "Shenzhen Jiuzhou Electric Co., Ltd." }, - { 0x22A2, "Disruptive Ltd." }, - { 0x22A3, "DexCom" }, - { 0x22A4, "InnoComm Mobile Technology Corp." }, - { 0x22A5, "Yu Jeong System Co., Ltd." }, - { 0x22A6, "Pie Digital, Inc." }, - { 0x22A7, "Fortinet, Inc." }, - { 0x22A8, "OTTO" }, - { 0x22A9, "Valor Communication, Inc." }, - { 0x22AA, "AppliedMicro" }, - { 0x22AB, "Trigence Semiconductor, Inc." }, - { 0x22AC, "Sensor Switch, Inc." }, - { 0x22AD, "DCP Microdevelopments Limited" }, - { 0x22AE, "Buerkert Werke GmbH" }, - { 0x22AF, "JW Fishers Mfg." }, - { 0x22B0, "Business Security OL AB" }, - { 0x22B1, "Secret Labs LLC" }, - { 0x22B2, "EDGE Tech Corp." }, - { 0x22B3, "SOMFY" }, - { 0x22B4, "NIPPON ANTENNA Co., Ltd." }, - { 0x22B5, "Thyracont Vacuum Instruments GmbH" }, - { 0x22B6, "IMTRADEX Hoer-/Sprechsysteme GmbH" }, - { 0x22B7, "Unjo AB" }, - { 0x22B8, "Motorola Mobility Inc." }, - { 0x22B9, "eTurboTouch Technology Inc." }, - { 0x22BA, "Technology Innovation Holdings Ltd." }, - { 0x22BB, "Saris Cycling Group" }, - { 0x22BC, "OPWILL Technologies (Beijing) Co., Ltd." }, - { 0x22BD, "Basis Software, Inc." }, - { 0x22BE, "Cheetah-Medical Ltd." }, - { 0x22BF, "Bit Cauldron Corporation" }, - { 0x22C0, "ReLia Diagnostic Systems, Inc." }, - { 0x22C1, "ATEK Products, LLC" }, - { 0x22C2, "Fast And Safe Technology Co., Ltd." }, - { 0x22C3, "Tsinghua Tongfang Co., Ltd." }, - { 0x22C4, "Fresenius Medical Care Deutschland GmbH" }, - { 0x22C5, "Himax Technologies, Inc." }, - { 0x22C6, "Baker Hughes Production Quest" }, - { 0x22C7, "MEMUP" }, - { 0x22C8, "Shenzhen Xinerchang Electronics Co., Ltd." }, - { 0x22C9, "StepOver GmbH" }, - { 0x22CA, "Amimon Ltd." }, - { 0x22CB, "Forware Spain S.L." }, - { 0x22CC, "LAONEX CO., LTD." }, - { 0x22CD, "Kinova" }, - { 0x22CE, "Metters Industries" }, - { 0x22CF, "Marquess Co., Limited" }, - { 0x22D0, "Norsonic AS" }, - { 0x22D1, "ZeitControl GmbH" }, - { 0x22D2, "ZETT OPTICS GmbH" }, - { 0x22D3, "FAAC SpA" }, - { 0x22D4, "Laview Technology Ltd." }, - { 0x22D5, "Yellow Soft Co., Ltd." }, - { 0x22D6, "Numatic International Ltd." }, - { 0x22D7, "IntelliTech International, Inc." }, - { 0x22D8, "Shantery Co., Ltd." }, - { 0x22D9, "GuangDong OPPO Mobile Telecommunications Corp., Ltd." }, - { 0x22DA, "TXTR GmbH" }, - { 0x22DB, "Phase One A/S" }, - { 0x22DC, "TILERA CORPORATION" }, - { 0x22DD, "Kawasaki Heavy Industries, Ltd." }, - { 0x22DE, "WeTelecom" }, - { 0x22DF, "Medicom-MTD" }, - { 0x22E0, "Secunet Security Networks AG" }, - { 0x22E1, "TempoTec Corp" }, - { 0x22E2, "IDEA!" }, - { 0x22E3, "Escort, Inc." }, - { 0x22E4, "Shenyang Tongzhen Precision Electronic Technology Co." }, - { 0x22E5, "Mine Safety Appliances Co." }, - { 0x22E6, "Labo America, Inc." }, - { 0x22E7, "ZAFFER BVBA" }, - { 0x22E8, "Audio Partnership" }, - { 0x22E9, "Orion Diagnostica OY" }, - { 0x22EA, "Bit Trade One, Ltd." }, - { 0x22EB, "Vizimax Inc." }, - { 0x22EC, "Kozio, Inc." }, - { 0x22ED, "HannStar Display Corp." }, - { 0x22EE, "Struers A/S" }, - { 0x22EF, "Edutor Technologies India Private Limited" }, - { 0x22F0, "Allen + Heath Ltd." }, - { 0x22F1, "DATEQ BV" }, - { 0x22F2, "Quest Payment Systems" }, - { 0x22F3, "Zephyr Technology Corporation" }, - { 0x22F4, "Olive Global Holding Pvt. Ltd." }, - { 0x22F5, "oTHE Technology Inc." }, - { 0x22F6, "Clear Pulse Co., Ltd." }, - { 0x22F7, "Drivven, Inc." }, - { 0x22F8, "Universal Sats Ltd." }, - { 0x22F9, "Compass, s.r.l." }, - { 0x22FA, "Sifteo Inc." }, - { 0x22FB, "Beijing Chiplight IC Design Co., Ltd." }, - { 0x22FC, "ModusLink Global Solutions, Inc." }, - { 0x22FD, "Miltope Corp." }, - { 0x22FE, "Protium Technologies, Inc." }, - { 0x22FF, "Avnet" }, - { 0x2300, "Nanjing Magon Opto-Electrical Science & Technology Co." }, - { 0x2301, "Imaginant Inc." }, - { 0x2302, "Rafael Advanced Defense Systems Ltd." }, - { 0x2303, "Grosvenor Technology Ltd." }, - { 0x2304, "Pinnacle" }, - { 0x2305, "Lindemann Audiotechnik GmbH" }, - { 0x2306, "Syba Multimedia, Inc." }, - { 0x2307, "Madboy Audio International Oy" }, - { 0x2308, "UV Networks, Inc." }, - { 0x2309, "TimeLink Inc." }, - { 0x230A, "Data Locker Inc." }, - { 0x230B, "Shanda Interactive Entertainment Limited" }, - { 0x230C, "GarTech Enterprises, Inc." }, - { 0x230D, "Linktop Technology Co., Ltd." }, - { 0x230E, "eDAQ Pty., Ltd." }, - { 0x230F, "applause.elfmimi.jp" }, - { 0x2310, "WCE, Inc." }, - { 0x2311, "Francotyp-Postalia GmbH" }, - { 0x2312, "Learning Curve Brands, Inc." }, - { 0x2313, "Kunshan Jiahua Electronics Co., Ltd." }, - { 0x2314, "INQ Mobile Limited" }, - { 0x2315, "Avery Design Systems, Inc." }, - { 0x2316, "DongGuan Potec Electric Industrial Co., Ltd." }, - { 0x2317, "Huawei Device Co., Ltd." }, - { 0x2318, "Solar Components LLC" }, - { 0x2319, "Loewe Opta GmbH" }, - { 0x231A, "SANWA KAGAKU KENKYUSHO CO., LTD." }, - { 0x231B, "winner story Co., Ltd." }, - { 0x231C, "SONUUS LIMITED" }, - { 0x231D, "Fervian Technologies Limited" }, - { 0x231E, "Chongqing CYIT Communication Technologies Co., Ltd." }, - { 0x231F, "FandF Co., Ltd." }, - { 0x2320, "Redring AB" }, - { 0x2321, "iKingdom Corp. (d.b.a. iConnectivity)" }, - { 0x2322, "RichWave Technology Corp." }, - { 0x2323, "EFI TECHNOLOGY s.r.l." }, - { 0x2324, "Ubisense Limited" }, - { 0x2325, "Simbex" }, - { 0x2326, "CKM Electronics Co., Ltd." }, - { 0x2327, "DreamSecurity" }, - { 0x2328, "Radio Systems Corporation" }, - { 0x2329, "Infinite Technologies JLT" }, - { 0x232A, "Skalar Analytical b.v." }, - { 0x232B, "Zhuhai Pantum Technology Co., Ltd." }, - { 0x232C, "Digital Lumens" }, - { 0x232D, "Edinburgh Instruments Ltd." }, - { 0x232E, "EA, Elektro-Automatik GmbH & Co. KG" }, - { 0x232F, "Motic China Group Co., Ltd." }, - { 0x2330, "Tensorcom, Inc." }, - { 0x2331, "PUZZLE LOGIC INC." }, - { 0x2332, "Coges S.p.A." }, - { 0x2333, "Zamzee Co." }, - { 0x2334, "Opticos srl" }, - { 0x2335, "Personable Inc." }, - { 0x2336, "Vix Technology (Aust) Ltd." }, - { 0x2337, "linked IP GmbH" }, - { 0x2338, "RedE Innovations" }, - { 0x2339, "Sierra Nevada Corporation" }, - { 0x233A, "Telpar" }, - { 0x233B, "taberna pro medicum GmbH" }, - { 0x233C, "Julabo" }, - { 0x233D, "Microtech System" }, - { 0x233E, "Aastra Telecom Inc." }, - { 0x233F, "Stage Tec GmbH" }, - { 0x2340, "Teleepoch Limited" }, - { 0x2341, "Arduino, LLC" }, - { 0x2342, "nextEDGE Technology, K.K." }, - { 0x2343, "AquaScan A/S" }, - { 0x2344, "HAMBURG INDUSTRIES CO., LTD." }, - { 0x2345, "ZOWIE GEAR" }, - { 0x2346, "Data Transfer & Communications Ltd." }, - { 0x2347, "iControl Networks" }, - { 0x2348, "Ubisys Technology" }, - { 0x2349, "P2 Engineering Group, LLC" }, - { 0x234A, "Cypress Technology Co., Ltd." }, - { 0x234B, "Free Software Initiative of Japan" }, - { 0x234C, "Zenverge Inc." }, - { 0x234D, "Skype Inc." }, - { 0x234E, "Anewin" }, - { 0x234F, "VaniOs Consulting" }, - { 0x2350, "ZiiLABS Pte. Ltd." }, - { 0x2351, "EmbCodeAB" }, - { 0x2352, "SKYTEX Technology Inc." }, - { 0x2353, "PHiON Technology Inc." }, - { 0x2354, "BirdBrain Technologies LLC" }, - { 0x2355, "Pacific Northwest National Laboratory (PNNL)" }, - { 0x2356, "Grid Connect Inc." }, - { 0x2357, "TP-LINK Technologies Co., Ltd." }, - { 0x2358, "Greenconn Corporation" }, - { 0x2359, "Shenzhen Autone-Tronic Technology Co., Ltd." }, - { 0x235A, "Top Yang Technology Enterprise Co., Ltd." }, - { 0x235B, "KangXiang Electronic Co., Ltd." }, - { 0x235C, "Neuralieve" }, - { 0x235D, "Wavepod Technologies LLC" }, - { 0x235E, "Sage Electronic Engineering LLC" }, - { 0x235F, "Delux Technology Co., Ltd." }, - { 0x2360, "AudioProbe Inc." }, - { 0x2361, "Artiza Networks, Inc." }, - { 0x2362, "Intuity Medical" }, - { 0x2363, "SplitFish Ltd." }, - { 0x2364, "Friedrich Leutert GmbH & Co. KG" }, - { 0x2365, "Midwest Microwave Solutions" }, - { 0x2366, "Bitmanufaktur GmbH" }, - { 0x2367, "Teenage Engineering" }, - { 0x2368, "Peterson Electro-Musical Products, Inc." }, - { 0x2369, "Telspan Data, LLC" }, - { 0x236A, "SiBEAM, Inc." }, - { 0x236B, "Era Optoelectronics Inc." }, - { 0x236C, "ZheJiang Chunsheng Electronics Co., Ltd." }, - { 0x236D, "e-supplies Co., Ltd." }, - { 0x236E, "Idex ASA" }, - { 0x236F, "Risun Electric Information Technology Co., Ltd." }, - { 0x2370, "Vlatacom d.o.o." }, - { 0x2371, "Zetron, Inc." }, - { 0x2372, "Shenzhen Techaser Technologies Co., Ltd." }, - { 0x2373, "Pumatronix Equipamentos Eletronicos Ltda." }, - { 0x2374, "Codan Limited" }, - { 0x2375, "Nexell Co., Ltd." }, - { 0x2376, "Realfiction Aps" }, - { 0x2377, "Musa srl" }, - { 0x2378, "OnLive, INC." }, - { 0x2379, "Geotechnical Instruments (UK) Ltd." }, - { 0x237A, "Danatronics, Corp." }, - { 0x237B, "YUKAI Engineering" }, - { 0x237C, "POWERVAR" }, - { 0x237D, "CradlePoint, Inc." }, - { 0x237E, "Ernie Ball, Inc." }, - { 0x237F, "He Shan World Fair Electronics Technology Ltd." }, - { 0x2380, "Law Enforcement Associates, Inc." }, - { 0x2381, "IPE Music" }, - { 0x2382, "Trigaudio, Inc." }, - { 0x2383, "Super Pioneer Co., Ltd." }, - { 0x2384, "Tamara Electronics Design" }, - { 0x2385, "Booyco Electronics (Pty) Ltd." }, - { 0x2386, "Raydium Semiconductor Corporation" }, - { 0x2387, "N&S Services, Inc. dba XIM Technologies" }, - { 0x2388, "High Density Devices" }, - { 0x2389, "ShenZhen Handin Tech Co., Ltd." }, - { 0x238A, "ASAHI SANGYO CO., LTD." }, - { 0x238B, "Hytera Communications Co., Ltd." }, - { 0x238C, "Japan Care Net Service Corporation" }, - { 0x238D, "OMNIO Corporation" }, - { 0x238E, "Xtralis" }, - { 0x238F, "TRS Star GmbH" }, - { 0x2390, "Triex Technologies, Inc." }, - { 0x2391, "FUKUDA CO., LTD." }, - { 0x2392, "Deltatee Enterprises Ltd." }, - { 0x2393, "WonATech Co., Ltd." }, - { 0x2394, "J.MORITA MFG. CORP." }, - { 0x2395, "CNOGA MEDICAL LTD." }, - { 0x2396, "Advanced Multi Tech Pte. Ltd." }, - { 0x2397, "Simaudio Ltd." }, - { 0x2398, "Bluetechnix" }, - { 0x2399, "Lightwares" }, - { 0x239A, "Adafruit Industries LLC" }, - { 0x239B, "TZ Medical, Inc." }, - { 0x239C, "Braebon Medical Corporation" }, - { 0x239D, "Memjet Labels, Inc." }, - { 0x239E, "Rubin Informatikai Zrt." }, - { 0x239F, "Nikola Engineering Inc." }, - { 0x23A0, "BIFIT" }, - { 0x23A1, "Pepperl+Fuchs GmbH" }, - { 0x23A2, "Mobile Peak Holdings, Ltd." }, - { 0x23A3, "Dongguan City ShengJing Electronics Co., Ltd." }, - { 0x23A4, "MINGTECH CHINA CO., LTD." }, - { 0x23A5, "Instytut Fotonowy Sp. Z o.o." }, - { 0x23A6, "Tronical Components GmbH" }, - { 0x23A7, "System In Frontier Inc." }, - { 0x23A8, "Sagio A/S" }, - { 0x23A9, "SiliconGo Microelectronics Inc." }, - { 0x23AA, "DOK (HK) Trading Limited" }, - { 0x23AB, "SZZT ELECTRONICS CO., LTD" }, - { 0x23AC, "Marunix Electron Limited" }, - { 0x23AD, "voxeljet technology GmbH" }, - { 0x23AE, "DIGITAL DEVICES UG" }, - { 0x23AF, "iOWA AB" }, - { 0x23B0, "Seniorsoft Development Co., Ltd." }, - { 0x23B1, "Riken Keiki Co., Ltd." }, - { 0x23B2, "SEER Technology, Inc." }, - { 0x23B3, "Straubtec GmbH & Co. KG" }, - { 0x23B4, "Dental Wings Inc." }, - { 0x23B5, "Crowcon Detection Instruments Limited" }, - { 0x23B6, "FULL ELECTRONIC system" }, - { 0x23B7, "Isca Networks" }, - { 0x23B8, "Daruma Telecomunicacoes e Informatica S/A" }, - { 0x23B9, "Green Energy Options Ltd." }, - { 0x23BA, "Playback Designs LLC" }, - { 0x23BB, "EMI STOP CORP." }, - { 0x23BC, "ARIDIAN TECHNOLOGY COMPANY INC." }, - { 0x23BD, "Musashi Engineering, Inc." }, - { 0x23BE, "Raynet Technologies Pte. Ltd." }, - { 0x23BF, "Environics Oy" }, - { 0x23C0, "Kotec" }, - { 0x23C1, "MakerBot Industries" }, - { 0x23C2, "CREALOGIX E-Banking AG" }, - { 0x23C3, "Cydle Corp." }, - { 0x23C4, "Media Engineering" }, - { 0x23C5, "Promega Corporation" }, - { 0x23C6, "plawa-feinwerktechnik GmbH & Co. KG" }, - { 0x23C7, "GCI Technologies Corp." }, - { 0x23C8, "IML Ltd." }, - { 0x23C9, "IRM Touch Inc." }, - { 0x23CA, "IHP GmbH Innovations for High Performance Microelectro" }, - { 0x23CB, "Point Core SARL" }, - { 0x23CC, "Avitech International Corp." }, - { 0x23CD, "Avconn Precise Connector Co., Ltd." }, - { 0x23CE, "Gembird Electronics Ltd." }, - { 0x23CF, "Admesy BV" }, - { 0x23D0, "Youjie" }, - { 0x23D1, "LUFFT Mess-und Regeltechnik GmbH" }, - { 0x23D2, "WEAVERSMIND Inc." }, - { 0x23D3, "RFTECH SRL" }, - { 0x23D4, "ALLTRAX, Inc." }, - { 0x23D5, "SerialTek" }, - { 0x23D6, "DONGGUAN LICHENG ELECTRONICS CO., LTD." }, - { 0x23D7, "PENNYWISE PERIPHERALS PTY. LTD." }, - { 0x23D8, "CREATOR (CHINA) TECH CO., LTD." }, - { 0x23D9, "SIGLEAD Inc." }, - { 0x23DA, "THK Co., Ltd." }, - { 0x23DB, "Sonicweld" }, - { 0x23DC, "Phonic Ear, Inc. Frontrow Division" }, - { 0x23DD, "Ningbo Sunny Opotech Co., Ltd." }, - { 0x23DE, "ZAO Papillon" }, - { 0x23DF, "WebAthletics BV" }, - { 0x23E0, "BitifEye Digital Test Solutions GmbH" }, - { 0x23E1, "Vidyo, Inc." }, - { 0x23E2, "Shape Medical Systems, Inc." }, - { 0x23E3, "Christie Digital Systems Canada Inc." }, - { 0x23E4, "General Microsystems Sdn Bhd" }, - { 0x23E5, "Antelope Audio" }, - { 0x23E6, "DIGIT MOBILE INC." }, - { 0x23E7, "ROGER Dariusz Wensker Grzegorz Wensker S.P.j." }, - { 0x23E8, "Propellerhead Software AB" }, - { 0x23E9, "Peregrine Technology Co., Ltd." }, - { 0x23EA, "Inputek" }, - { 0x23EB, "TOPPAN FORMS CO., LTD." }, - { 0x23EC, "Alacer Biomedica Industria Eletronica Ltda." }, - { 0x23ED, "Optomotive, mehatronika d.o.o." }, - { 0x23EE, "Sofird, Inc." }, - { 0x23EF, "PPHU AWEX RAFAL STANUCH" }, - { 0x23F0, "Ecotronics Limited" }, - { 0x23F1, "WIMM Labs" }, - { 0x23F2, "Northern Digital Inc." }, - { 0x23F3, "Funke Digital TV" }, - { 0x23F4, "NXT Plc" }, - { 0x23F5, "Speed Conn Electronics (Shenzhen) Co., Ltd." }, - { 0x23F6, "Gamesman Ltd." }, - { 0x23F7, "TechRhythm, Inc." }, - { 0x23F8, "Xiangde Electronic Technologies (Shenzhen) Co., Ltd." }, - { 0x23F9, "RT Systems (Pty) Ltd." }, - { 0x23FA, "DJO, LLC" }, - { 0x23FB, "Janich & Klass Computertechnik GmbH" }, - { 0x23FC, "SesKion GmbH" }, - { 0x23FD, "AWare, Inc." }, - { 0x23FE, "Express Way Limited" }, - { 0x23FF, "UIworks Electronics" }, - { 0x2400, "Shenzhen Chuangyitong Technology Co., Ltd" }, - { 0x2401, "Deltronic Labs" }, - { 0x2402, "DA FACT" }, - { 0x2403, "XTRAMUS TECHNOLOGIES" }, - { 0x2404, "GE MDS" }, - { 0x2405, "Custom Computer Services, Inc." }, - { 0x2406, "WIseKey" }, - { 0x2407, "Incasolution Co., Ltd." }, - { 0x2408, "Catalyst Enterprises, Inc." }, - { 0x2409, "BCInet, Inc." }, - { 0x240A, "Infron Teknolojik Sistemleri San. Ve Tic. Ltd. STI" }, - { 0x240B, "Kawamura Electric, Inc." }, - { 0x240C, "Maples Micro System Corp" }, - { 0x240D, "Chinachip Technology Limited" }, - { 0x240E, "JEFF ROWLAND DESIGN GROUP, INC" }, - { 0x240F, "Trantek Electronics Co., Ltd." }, - { 0x2410, "Tenebraex Corp." }, - { 0x2411, "Industrial Scientific Oldham SAS" }, - { 0x2412, "Invision Biometrics Ltd." }, - { 0x2413, "Skyviia Corporation" }, - { 0x2414, "Leopold Kostal GmbH & Co. KG" }, - { 0x2415, "CipherLab Co., Ltd." }, - { 0x2416, "FUTURE DESIGNS, INC." }, - { 0x2417, "INIT GmbH" }, - { 0x2418, "Irphotonics" }, - { 0x2419, "Shenzhen Dnine Technology Co., Ltd." }, - { 0x241A, "The Silanna Group Pty. Ltd." }, - { 0x241B, "Dongguan City Qirui Electronics Co., Ltd." }, - { 0x241C, "ATMOS Medizin Technik GmbH & Co. KG" }, - { 0x241D, "Redbird Flight Simulations, Inc." }, - { 0x241E, "SHENZHEN FUNDUN TECHNOLOGY CO., LTD." }, - { 0x241F, "Global Geo Supplies, Inc." }, - { 0x2420, "M Seven System Limited" }, - { 0x2421, "Anasphere, Inc." }, - { 0x2422, "Tom Communication Industrial Co., Ltd." }, - { 0x2423, "Bio-Med Devices Inc." }, - { 0x2424, "CREATZ Inc." }, - { 0x2425, "PIQX Imaging Pte. Ltd." }, - { 0x2426, "Johnson Controls, Inc. - Building Efficiency Business" }, - { 0x2427, "Winkelmann UK Ltd." }, - { 0x2428, "SANTEC CORPORATION" }, - { 0x2429, "IWSCOPE Inc." }, - { 0x242A, "HUR OY" }, - { 0x242B, "Philips Healthcare" }, - { 0x242C, "ARMSTEL, Inc." }, - { 0x242D, "Flastar Technology Co., Ltd." }, - { 0x242E, "Vossloh-Schwabe Deutschland GmbH" }, - { 0x242F, "GPH Co., Ltd." }, - { 0x2430, "APE GmbH" }, - { 0x2431, "Yamazaki Co., Ltd." }, - { 0x2432, "Ceton Corp." }, - { 0x2433, "Asetek A/S" }, - { 0x2434, "NOVA electronics, Inc." }, - { 0x2435, "PAKSENSE, INC." }, - { 0x2436, "MediTECH Electronic GmbH" }, - { 0x2437, "NIKETECH ELECTRONICS GROUP LIMITED" }, - { 0x2438, "Innopower Technology Corporation" }, - { 0x2439, "Comex Electronics AB" }, - { 0x243A, "Mobile Devices Ingenierie" }, - { 0x243B, "OTAX Electronics (ShenZhen) Co., Ltd." }, - { 0x243C, "DiZiC Co., Ltd." }, - { 0x243D, "emz - Hanauer GmbH & Co KGaA" }, - { 0x243E, "Savi Elettronica srl" }, - { 0x243F, "Photonic GesmbH & Co. KG" }, - { 0x2440, "RB GeneralEkonomik" }, - { 0x2441, "TV One" }, - { 0x2442, "University of Central Florida" }, - { 0x2443, "Aessent Technology Ltd." }, - { 0x2444, "NetModule AG" }, - { 0x2445, "TOMY Company, Ltd." }, - { 0x2446, "Avionics Interface Technologies" }, - { 0x2447, "Knick Elektronische Messgerate GmbH & Co. KG" }, - { 0x2448, "Winterhalter GmbH" }, - { 0x2449, "SHAEFER GmbH" }, - { 0x244A, "Onzo Ltd." }, - { 0x244B, "Applied Technical Systems" }, - { 0x244C, "MinebeaMitsumi Inc." }, - { 0x244D, "Pantec Biosolutions AG" }, - { 0x244E, "ShopGuard Ltd." }, - { 0x244F, "iWall A/S" }, - { 0x2450, "Boule Medical AB" }, - { 0x2451, "AEM Performance Electronics" }, - { 0x2452, "Speeder Electronics Co., Ltd." }, - { 0x2453, "BAANTO" }, - { 0x2454, "Velosti Technology Limited" }, - { 0x2455, "Anton/Bauer, Inc." }, - { 0x2456, "CKD NIKKI DENSO CO., LTD" }, - { 0x2457, "Alcomp. Inc." }, - { 0x2458, "Bluegiga Technologies Oy" }, - { 0x2459, "Secure Holdings Limited" }, - { 0x245A, "KONDOH SEISAKUSHO Co., Ltd." }, - { 0x245B, "Zixsys Inc." }, - { 0x245C, "Steinbauer Electronics GmbH" }, - { 0x245D, "ID Technologies" }, - { 0x245E, "LNT - Automation GmbH" }, - { 0x245F, "Chord Electronics Limited" }, - { 0x2460, "NELS, Ltd." }, - { 0x2461, "Beam Communications" }, - { 0x2462, "IDENTICA S.A." }, - { 0x2463, "BAP Precision Ltd." }, - { 0x2464, "Nestlabs" }, - { 0x2465, "Microsoft Surface Hub" }, - { 0x2466, "Fractal Audio Systems, LLC" }, - { 0x2467, "Nektar Technology, Inc." }, - { 0x2468, "New Cosmos Electric Co., Ltd." }, - { 0x2469, "Gloria Music Corp." }, - { 0x246A, "UNH Interoperability Laboratory" }, - { 0x246B, "Perfect Fortune Electric Wire & Cable (ShenZhen) Co. Ltd." }, - { 0x246C, "Shanghai Fudan Microelectronics Co., Ltd." }, - { 0x246D, "TrackMan A/S" }, - { 0x246E, "Movinto Fun AB" }, - { 0x246F, "STORK PRINTS AUSTRIA GmbH" }, - { 0x2470, "Hale Microsystems" }, - { 0x2471, "Bloonn Srl" }, - { 0x2472, "Bossa Nova Robotics, Inc." }, - { 0x2473, "Trend Control Systems Limited" }, - { 0x2474, "Stamps.com" }, - { 0x2475, "JCM American Corporation" }, - { 0x2476, "Yost Engineering Inc." }, - { 0x2477, "UbiVelox" }, - { 0x2478, "Sonix Technology (Shenzhen) Co., Ltd." }, - { 0x2479, "smartek d.o.o." }, - { 0x247A, "Suzhou Jutze Technologies Co., Ltd" }, - { 0x247B, "Digibras Industria do Brasil S.A" }, - { 0x247C, "Fullconn Industry Inc." }, - { 0x247D, "JARGY CO. LTD." }, - { 0x247E, "GEWA music GmbH" }, - { 0x247F, "Lynx Studio Technology, Inc." }, - { 0x2480, "Omniware Inc." }, - { 0x2481, "Shenzhen SKY DRAGON Audio-Video Technology Co., Ltd." }, - { 0x2482, "SmartRoom LLC" }, - { 0x2483, "Valups Corp." }, - { 0x2484, "Unipolar Optics-Electrical Technology Co., Ltd." }, - { 0x2485, "Dream SAS" }, - { 0x2486, "DCG Systems, Inc." }, - { 0x2487, "SHANGHAI VEI SHENG AUTO PARTS MANUFACTURING CO., LTD." }, - { 0x2488, "SuperD Co., Ltd." }, - { 0x2489, "Irvine Sensors Corporation" }, - { 0x248A, "TeLink Semiconductor (Shanghai) Co., Ltd." }, - { 0x248B, "DONGGUAN SYNCONN PRECISION INDUSTRY CO. LTD." }, - { 0x248C, "Avicenna Instruments, LLC" }, - { 0x248D, "Digital Matter Pty Ltd." }, - { 0x248E, "Pulsar Informatics, Inc." }, - { 0x248F, "HMS Industrial Networks AB" }, - { 0x2490, "Zealtek electronic Co. Ltd." }, - { 0x2491, "OBSERVATOR instruments b.v." }, - { 0x2492, "Mofiria Corporation" }, - { 0x2493, "Sensolutions Inc." }, - { 0x2494, "Invoxia" }, - { 0x2495, "Summit Semiconductor LLC" }, - { 0x2496, "Dongguan DaTang Industrial Investment Co., Ltd." }, - { 0x2497, "HyunWoo Electronics Co., Ltd." }, - { 0x2498, "Aurora SFC Systems, Inc." }, - { 0x2499, "Governors America Corp." }, - { 0x249A, "Anedio, LLC" }, - { 0x249B, "Miller Electric Mfg. Co." }, - { 0x249C, "M2TECH SRL" }, - { 0x249D, "Ken-A-Vision Manufacturing Company, Inc." }, - { 0x249E, "Tlab West Systems AB" }, - { 0x249F, "ABC PCB Sarl" }, - { 0x24A0, "VIMAR SPA" }, - { 0x24A1, "AUTONICS Corporation" }, - { 0x24A2, "SafeTech Ltd." }, - { 0x24A3, "BioTillion, LLC" }, - { 0x24A4, "Primare AB" }, - { 0x24A5, "OWANDY" }, - { 0x24A6, "Shenzhen Pangngai Industrial Co., Ltd." }, - { 0x24A7, "PROMAX ELECTRONICA S.A." }, - { 0x24A8, "Hermes electronic GmbH" }, - { 0x24A9, "ASolid Technology Co., Ltd." }, - { 0x24AA, "Wasatch Photonics" }, - { 0x24AB, "IMERJ LTD." }, - { 0x24AC, "ToMiTec GmbH" }, - { 0x24AD, "embedded brains GmbH" }, - { 0x24AE, "Shenzhen Rapoo Technology Co., Ltd." }, - { 0x24AF, "Integrated Corporation" }, - { 0x24B0, "Echometer Company" }, - { 0x24B1, "SCR Engineers Ltd." }, - { 0x24B2, "DelSys Inc." }, - { 0x24B3, "Simbionix Ltd." }, - { 0x24B4, "Leema Acoustics" }, - { 0x24B5, "3C TEK CORP." }, - { 0x24B6, "Shenzhen New-Conn International Co., Ltd." }, - { 0x24B7, "Medical Equipment Europe GmbH" }, - { 0x24B8, "DongGuan CJ TOUCH Electronic Co., Ltd." }, - { 0x24B9, "Hoshin Electronics Co., Ltd." }, - { 0x24BA, "PRADOTEC Corporation Sdn. Bhd." }, - { 0x24BB, "SHANGHAI LIGHTSURFING INFORMATION TECHNOLOGY CO., LTD." }, - { 0x24BC, "Sartorius AG" }, - { 0x24BD, "Smart Solution" }, - { 0x24BE, "Mutewatch AB" }, - { 0x24BF, "NBS Payment Solutions, Inc." }, - { 0x24C0, "Chaney Instrument Co." }, - { 0x24C1, "Maction Technologies, Inc." }, - { 0x24C2, "DiCon Fiberoptics, Inc." }, - { 0x24C3, "Covaris, Inc." }, - { 0x24C4, "CMITECH Co., Ltd." }, - { 0x24C5, "HUINTECH" }, - { 0x24C6, "Xbox 3rd Party Partners" }, - { 0x24C7, "Laser Technology, Inc." }, - { 0x24C8, "CHAPP INC." }, - { 0x24C9, "Pilot Electronic (China) Ltd." }, - { 0x24CA, "SMARTEH d.o.o." }, - { 0x24CB, "Servotronix Motion Control Ltd." }, - { 0x24CC, "JSB Tech Pte. Ltd." }, - { 0x24CD, "Viking360.com LLC" }, - { 0x24CE, "Shenzhen Deren Electronic Co., Ltd." }, - { 0x24CF, "Lytro, Inc." }, - { 0x24D0, "Smith Micro Software, Inc." }, - { 0x24D1, "POS & Solution Company" }, - { 0x24D2, "DADT Holdings, LLC" }, - { 0x24D3, "Lexking Technology Co., Ltd." }, - { 0x24D4, "KOMATSU ELECTRONIC CO., LTD." }, - { 0x24D5, "SATEL Ltd." }, - { 0x24D6, "Develer S.r.l." }, - { 0x24D7, "ACORDE TECHNOLOGIES" }, - { 0x24D8, "Pittway Tecnologica Srl" }, - { 0x24D9, "Unfors Instruments AB" }, - { 0x24DA, "KYOCERA ELCO Korea Co., Ltd." }, - { 0x24DB, "DDUSB Technology" }, - { 0x24DC, "Aladdin Software Security R.D." }, - { 0x24DD, "Kingspan Environmental Ltd." }, - { 0x24DE, "Navicron" }, - { 0x24DF, "ALGO System. Co" }, - { 0x24E0, "Yoctopuce Sarl" }, - { 0x24E1, "Paratronic S.A." }, - { 0x24E2, "Digital Information Technology Studies (Shenzhen) Ltd." }, - { 0x24E3, "Beijing TianYu Communication Equipment Co., Ltd." }, - { 0x24E4, "Bytec Group Limited" }, - { 0x24E5, "Lanmark Controls Inc." }, - { 0x24E6, "ACI Analytical Control Instruments GmbH" }, - { 0x24E7, "maxon motor ag" }, - { 0x24E8, "ivee" }, - { 0x24E9, "Microelectronics Technology Inc." }, - { 0x24EA, "ZEBEX INDUSTRIES INC." }, - { 0x24EB, "SHENZHEN PCTX TECHNOLOGY DEVELOPMENT CO., LTD." }, - { 0x24EC, "CE-Infosys GmbH" }, - { 0x24ED, "ZEN FACTORY GROUP (ASIA) LTD." }, - { 0x24EE, "A C S Co., Ltd." }, - { 0x24EF, "DATONG PLC" }, - { 0x24F0, "Das Keyboard - Metadot" }, - { 0x24F1, "Silicon Communication Technology" }, - { 0x24F2, "Secure Electrans LTD." }, - { 0x24F3, "MartinLogan Ltd." }, - { 0x24F4, "Mind Media BV" }, - { 0x24F5, "QRS Diagnostic" }, - { 0x24F6, "Aplix IP Holdings Corporation" }, - { 0x24F7, "Seneye Ltd." }, - { 0x24F8, "Bang & Olufsen A/S" }, - { 0x24F9, "TOSHIBA MITSUBISHI-ELECTRIC INDUSTRIAL SYSTEMS CORP." }, - { 0x24FA, "Vectronix AG" }, - { 0x24FB, "GTECH Corporation" }, - { 0x24FC, "GPEG International" }, - { 0x24FD, "Nichiyu Giken Kogyo Co., Ltd." }, - { 0x24FE, "GOMETRICS, S.L." }, - { 0x24FF, "Acroname Inc." }, - { 0x2500, "Ettus Research LLC" }, - { 0x2501, "Bridge Publications, Inc." }, - { 0x2502, "Canadian Automotive Instruments Ltd." }, - { 0x2503, "Kurth Electronic GmbH" }, - { 0x2504, "Nemic Lambda Ltd." }, - { 0x2505, "Xiroku Accupoint Technology Inc." }, - { 0x2506, "Hind Technology Group" }, - { 0x2507, "Advion BioSystems" }, - { 0x2508, "Symplex Communications, Inc." }, - { 0x2509, "Chain-In Electronic Co., Ltd." }, - { 0x250A, "H-Squared" }, - { 0x250B, "Nautilus Lifeline Ltd." }, - { 0x250C, "PHX Inc." }, - { 0x250D, "Alstom Grid SAS" }, - { 0x250E, "Beijing MOPS Technology Co., Ltd." }, - { 0x250F, "itplants ltd." }, - { 0x2510, "SE Elektronische Systeme" }, - { 0x2511, "Morita Tech Co., Ltd." }, - { 0x2512, "RNDPLUS Co., Ltd." }, - { 0x2513, "RMI Laser, LLC" }, - { 0x2514, "Fullpower Technologies" }, - { 0x2515, "AMITEK" }, - { 0x2516, "Cooler Master Co., Ltd." }, - { 0x2517, "Marel EHF" }, - { 0x2518, "Anite Telecoms Inc." }, - { 0x2519, "n-gineric gmbh" }, - { 0x251A, "Daiichi Electronics" }, - { 0x251B, "Stable Imaging Solutions, LLC" }, - { 0x251C, "snom technology AG" }, - { 0x251D, "Fortebio Inc." }, - { 0x251E, "Polara Engineering, Inc." }, - { 0x251F, "Golden Emperor International Ltd." }, - { 0x2520, "ANA-U GmbH" }, - { 0x2521, "Fundacion Tekniker" }, - { 0x2522, "Light Harmonic" }, - { 0x2523, "Recon Instruments Inc." }, - { 0x2524, "CVRx" }, - { 0x2525, "Barron McCann Technology Ltd." }, - { 0x2526, "Weide Electronics Co., Ltd." }, - { 0x2527, "Software Bisque, Inc." }, - { 0x2528, "BittWare Inc." }, - { 0x2529, "SUZHOU XINYA ELECTRIC COMMUNICATION CO., LTD." }, - { 0x252A, "SUZHOU KELI TECHNOLOGY DEVELOPMENT CO., LTD." }, - { 0x252B, "TOP Exactitude Industry (ShenZhen) Co., Ltd." }, - { 0x252C, "VIGO System S.A." }, - { 0x252D, "Nokia Siemens Networks" }, - { 0x252E, "Heliox Technologies, Inc." }, - { 0x252F, "Pentronic AB" }, - { 0x2530, "STT Emtec AB" }, - { 0x2531, "Proteus Industries Inc." }, - { 0x2532, "C.R.D.E. (Cahors Group)" }, - { 0x2533, "Osaka Micro Computer, Inc." }, - { 0x2534, "Russia's Institute of Radionavigation and Time" }, - { 0x2535, "ShenZhen Hogend Precision Technology Co., Ltd." }, - { 0x2536, "Ubisys Technology Co., Ltd." }, - { 0x2537, "Norel Systems Ltd." }, - { 0x2538, "Cochlear Ltd." }, - { 0x2539, "Club Electronics" }, - { 0x253A, "System Sacom Industry Corporation" }, - { 0x253B, "RCF S.p.a." }, - { 0x253C, "Tri-Tech Manufacturing Inc." }, - { 0x253D, "Koss Corporation" }, - { 0x253E, "Creative Product Design Pty., Ltd." }, - { 0x253F, "ORANGE IT INC." }, - { 0x2540, "Applied Materials" }, - { 0x2541, "Shanghai AisinoChip Electronics Technology Co., Ltd." }, - { 0x2542, "Ditron S.R.L." }, - { 0x2543, "Spark Dental Technology Limited" }, - { 0x2544, "Energy Micro AS" }, - { 0x2545, "Digital Foci, Inc." }, - { 0x2546, "Ravensburger Spieleverlag GmbH" }, - { 0x2547, "YiDu Technology" }, - { 0x2548, "Pulse-Eight Limited" }, - { 0x2549, "Librestream Technologies" }, - { 0x254A, "Enegate Co., Ltd." }, - { 0x254B, "Toy Toy Toy Ltd." }, - { 0x254C, "X6D Limited" }, - { 0x254D, "ICAR VISION SYSTEMS S.L." }, - { 0x254E, "SHF Communication Technologies AG" }, - { 0x254F, "Jigeon Technologies Co., Ltd." }, - { 0x2550, "Teledyne" }, - { 0x2551, "A.E.B. Industriale S.r.l." }, - { 0x2552, "Striiv, Inc." }, - { 0x2553, "C8 MediSensor" }, - { 0x2554, "ASSA ABLOY AB" }, - { 0x2555, "Pulse Tracer, Inc." }, - { 0x2556, "United Radio-Electronic Technologies Co., Ltd." }, - { 0x2557, "Robatech AG" }, - { 0x2558, "INTECH ELECTRONICS CORP." }, - { 0x2559, "Jangus Music, Inc. (dba Wi Digital Systems)" }, - { 0x255A, "TaiDoc Technology Corp." }, - { 0x255B, "NDI Technologies, Inc." }, - { 0x255C, "HOSIWELL TECHNOLOGY CO., LTD." }, - { 0x255D, "ATEECS" }, - { 0x255E, "Beijing Bonxeon Technology Co., Ltd." }, - { 0x255F, "DORNIER-LTF GmbH" }, - { 0x2560, "e-con Systems India Private Limited" }, - { 0x2561, "Brookhaven Instruments Corp." }, - { 0x2562, "SHENGZHEN MAYA ELECTRONICS CREATION CO. LTD." }, - { 0x2563, "Shenzhen ShanWan Technology Co., Ltd." }, - { 0x2564, "TESSERA TECHNOLOGY INC." }, - { 0x2565, "Cyclone Industries Limited" }, - { 0x2566, "Cryptera A/S" }, - { 0x2567, "DongGuan LongTao Electronic Co., Ltd." }, - { 0x2568, "ALL LINK CONN. TECHNOLOGY CORP." }, - { 0x2569, "DongGuan City MingJi Electronics Co., Ltd." }, - { 0x256A, "TAIAN TECHNOLOGY (WUXI) Co., Ltd." }, - { 0x256B, "Perreaux Industries Ltd." }, - { 0x256C, "GRAPHICS TECHNOLOGY (HK) CO., LIMITED" }, - { 0x256D, "Compal Broadband Networks, Inc." }, - { 0x256E, "Valuest Co., Ltd." }, - { 0x256F, "3D CONNEXION SAM" }, - { 0x2570, "AVID Technologies, Inc." }, - { 0x2571, "CHIPMAST TECHNOLOGY CO., LTD." }, - { 0x2572, "Vmarker" }, - { 0x2573, "ESI Audiotechnik GmbH" }, - { 0x2574, "AVer Information Inc." }, - { 0x2575, "Weida Hi-Tech Co., Ltd." }, - { 0x2576, "AFO Co., Ltd." }, - { 0x2577, "LCDVF LLC" }, - { 0x2578, "MPEC Technology Limited" }, - { 0x2579, "Dongguan Wisechamp Electronic Co., Ltd." }, - { 0x257A, "Shanghai Yuga Information Technology Co., Ltd." }, - { 0x257B, "shenzhen dcard smart card tech. co., ltd." }, - { 0x257C, "Richard Woehr GmbH" }, - { 0x257D, "Panovel Technology Corporation" }, - { 0x257E, "RFL Electronics Inc." }, - { 0x257F, "8devices" }, - { 0x2580, "DJ Techtools (Golden Sol Music LLC. Is Holding Co.)" }, - { 0x2581, "Plug-up" }, - { 0x2582, "Helmholz GmbH & Co. KG" }, - { 0x2583, "VECTRUX DISTRIBUTORS LLC" }, - { 0x2584, "COSMO CO., LTD." }, - { 0x2585, "HomeChip Ltd." }, - { 0x2586, "PLANET Technology Corporation" }, - { 0x2587, "Ningbo Jiatang Electronic Co., Ltd." }, - { 0x2588, "Infinitegra, Inc." }, - { 0x2589, "Argon Technology Corporation" }, - { 0x258A, "Sino Wealth Electronic Ltd." }, - { 0x258B, "KORYO ELECTRONICS CO., LTD." }, - { 0x258C, "Fastec Imaging Corporation" }, - { 0x258D, "Sequans Communications" }, - { 0x258E, "ENJsoft Co., Ltd." }, - { 0x258F, "CME" }, - { 0x2590, "MuChip Co., Ltd." }, - { 0x2591, "Optimus Semiconductor Inc." }, - { 0x2592, "Quest International" }, - { 0x2593, "CELIZION, Inc." }, - { 0x2594, "Acsys Technologies Ltd." }, - { 0x2595, "SANYO DENKI CO., LTD." }, - { 0x2596, "Twisted Melon Inc." }, - { 0x2597, "Diagnostic Systems Associates Inc." }, - { 0x2598, "Aerocrine" }, - { 0x2599, "Q-tag AG" }, - { 0x259A, "TriQuint Semiconductor" }, - { 0x259B, "INUVIO" }, - { 0x259C, "Immedia Semiconductor Inc." }, - { 0x259D, "RCA DA AMAZONIA LTDA" }, - { 0x259E, "American Messaging Services LLC" }, - { 0x259F, "THERMO KING" }, - { 0x25A0, "Ciegus Ltd." }, - { 0x25A1, "Suitable Technologies, Inc." }, - { 0x25A2, "LEMKE ENG." }, - { 0x25A3, "Nanoteq (Pty) Ltd." }, - { 0x25A4, "ALGOLTEK, INC." }, - { 0x25A5, "Yakel Enterprises LLC" }, - { 0x25A6, "AADI AS" }, - { 0x25A7, "Beken Corporation" }, - { 0x25A8, "Guangzhou Geoelectron Science & Technology Co., Ltd." }, - { 0x25A9, "Advanced Bionics" }, - { 0x25AA, "Top Victory Investments Ltd. (HK)" }, - { 0x25AB, "Carmanah Signs" }, - { 0x25AC, "PLIGG" }, - { 0x25AD, "Aurora Networks, Inc." }, - { 0x25AE, "OXIPULSE" }, - { 0x25AF, "C&A Marketing" }, - { 0x25B0, "Musical Fidelity" }, - { 0x25B1, "Disc Soft Ltd." }, - { 0x25B2, "DRS-RSTA, Inc." }, - { 0x25B3, "DongGuan Elinke Industrial Co., Ltd." }, - { 0x25B4, "Fairhaven Health" }, - { 0x25B5, "FlatFrog Laboratories AB" }, - { 0x25B6, "Fructel AB" }, - { 0x25B7, "Neomitic Technologies S.A. de C.V." }, - { 0x25B8, "Neutronics Inc." }, - { 0x25B9, "Nujira Ltd." }, - { 0x25BA, "WITec Wissenschaftliche Instrumente & Technologie GmbH" }, - { 0x25BB, "Brunner Elektronik AG" }, - { 0x25BC, "CETRTA POT" }, - { 0x25BD, "TECHEYE SYSTEMS INC." }, - { 0x25BE, "Infinite Z" }, - { 0x25BF, "Elegant Invention" }, - { 0x25C0, "Beyond Music Industrial Co., Ltd." }, - { 0x25C1, "Vaddio" }, - { 0x25C2, "Smith + Nephew Inc." }, - { 0x25C3, "Phorus" }, - { 0x25C4, "A & R Cambridge Ltd." }, - { 0x25C5, "Securetec Detektions Systeme AG" }, - { 0x25C6, "AVA Group A/S" }, - { 0x25C7, "MEGATRON Elektronik AG & Co." }, - { 0x25C8, "Visualplanet Ltd." }, - { 0x25C9, "Proximiant" }, - { 0x25CA, "Hovding Sverige AB" }, - { 0x25CB, "ELZET80 Mikrocomputer Giesler & Danne GmbH & Co. KG" }, - { 0x25CC, "NKC Co., Ltd." }, - { 0x25CD, "Edwards Ltd." }, - { 0x25CE, "MYTEK DIGITAL" }, - { 0x25CF, "Corning Optical Communications LLC" }, - { 0x25D0, "AeVee Laboratories LLC" }, - { 0x25D1, "TOKAI-DENSHI Inc." }, - { 0x25D2, "MRA Tek LLC" }, - { 0x25D3, "Zhe Jiang Huasheng Technology Co., Ltd." }, - { 0x25D4, "LOOPCOMM TECHNOLOGY, INC." }, - { 0x25D5, "DATATON AB" }, - { 0x25D6, "KOUZIRO Co., Ltd." }, - { 0x25D7, "Audiomatica srl" }, - { 0x25D8, "Serious Integrated, Inc." }, - { 0x25D9, "Monarch Innovative Technologies Pvt. Ltd." }, - { 0x25DA, "NETATMO" }, - { 0x25DB, "Merrick Industries, Inc." }, - { 0x25DC, "Cobolt AB" }, - { 0x25DD, "bit4id srl" }, - { 0x25DE, "Gasmet Technologies OY" }, - { 0x25DF, "TTE Systems Ltd." }, - { 0x25E0, "MULTIPLEX Modellsport GmbH & Co. KG" }, - { 0x25E1, "Daimler AG" }, - { 0x25E2, "Domain Surgical" }, - { 0x25E3, "SCI Innovations Ltd." }, - { 0x25E4, "AnaJet" }, - { 0x25E5, "ALLFLEX EUROPE" }, - { 0x25E6, "Digital Drilling Data Systems, LLC" }, - { 0x25E7, "EIFELWERK Butler Systeme GmbH" }, - { 0x25E8, "ATOLL Electronique" }, - { 0x25E9, "Leybold Vacuum" }, - { 0x25EA, "Aeroflex Weinschel" }, - { 0x25EB, "Medical Intubation Technology Corp." }, - { 0x25EC, "VELUX A/S" }, - { 0x25ED, "Logic PD" }, - { 0x25EE, "Mimoco" }, - { 0x25EF, "BLITZ Co., Ltd." }, - { 0x25F0, "GOODBETTERBEST Ltd." }, - { 0x25F1, "Eden Innovations" }, - { 0x25F2, "Dongguan Jinyue Electronics Co., Ltd." }, - { 0x25F3, "Kicker" }, - { 0x25F4, "ADVANSEE" }, - { 0x25F5, "Lucas Holding bv" }, - { 0x25F6, "SaferZone Co., Ltd." }, - { 0x25F7, "Engineea Remote Technologies S.L." }, - { 0x25F8, "Keypair Co., Ltd." }, - { 0x25F9, "Donbass Soft Ltd. & Co. KG" }, - { 0x25FA, "SoftEther Corporation" }, - { 0x25FB, "RICOH IMAGING COMPANY, LTD." }, - { 0x25FC, "RWA (Hong Kong) Limited" }, - { 0x25FD, "Neuromonics Inc." }, - { 0x25FE, "Providence Enterprise Limited" }, - { 0x25FF, "Watermark Medical, Inc." }, - { 0x2600, "SMARTCORE Inc." }, - { 0x2601, "OFI Testing Equipment, Inc." }, - { 0x2602, "Magenta Research Ltd." }, - { 0x2603, "Swyx Solutions AG" }, - { 0x2604, "Shenzhen Tenda Technology, Ltd." }, - { 0x2605, "OSRAM SYLVANIA" }, - { 0x2606, "O-Network Engineering AB" }, - { 0x2607, "Prox Dynamics AS" }, - { 0x2608, "OLHO tronic GmbH" }, - { 0x2609, "FICOSA" }, - { 0x260A, "SPEMOT AG" }, - { 0x260B, "Schneider Electric Canada Inc. - Division of PCT" }, - { 0x260C, "Saiko Systems Ltd." }, - { 0x260D, "DongGuan Togran Electronic Co., Ltd." }, - { 0x260E, "DongGuan HYX Industrial Co., Ltd." }, - { 0x260F, "VITY" }, - { 0x2610, "Egan Teamboard Inc." }, - { 0x2611, "I.C.E. Co., Ltd." }, - { 0x2612, "Crave Innovations" }, - { 0x2613, "Gerd Bar GmbH" }, - { 0x2614, "VMC Consulting Corporation" }, - { 0x2615, "Gammaflux L.P." }, - { 0x2616, "PS Audio" }, - { 0x2617, "Front-End Technology, Inc." }, - { 0x2618, "MicroGate Systems Ltd." }, - { 0x2619, "Advanced Silicon SA" }, - { 0x261A, "Shandong Synthesis Electronic Technology Co., Ltd." }, - { 0x261B, "INTELLIGENT ENERGY, LTD." }, - { 0x261C, "EISST Limited" }, - { 0x261D, "Arkham Technology" }, - { 0x261E, "IFAM GmbH Erfurt" }, - { 0x261F, "Cooper Industries" }, - { 0x2620, "SUE unicon.uz Scientific, Engineering & Marketing RC" }, - { 0x2621, "CLIXUP LLC" }, - { 0x2622, "IAG Group Limited" }, - { 0x2623, "SGR Audio Pty Ltd." }, - { 0x2624, "L-3 Communications - Communications Systems West" }, - { 0x2625, "MilDef AB" }, - { 0x2626, "Aruba Networks" }, - { 0x2627, "Vectron Systems AG" }, - { 0x2628, "TEN-TEC, INC." }, - { 0x2629, "Winstars Technology Limited" }, - { 0x262A, "SAVITECH CORP." }, - { 0x262B, "YTOP Electronics Technical (Kunshan) Co., Ltd." }, - { 0x262C, "Scannx" }, - { 0x262D, "Fujian Witsi Microelectronics Technology Co., Ltd." }, - { 0x262E, "UNITEX Corporation" }, - { 0x262F, "MELAG Medizintechnik oHG" }, - { 0x2630, "ifm electronic gmbh" }, - { 0x2631, "NEOPROT TECNOLOGIA EM INFORMATICA LTDA." }, - { 0x2632, "ENSPERT Inc." }, - { 0x2633, "Inno Audio & Video (HK) Limited" }, - { 0x2634, "E.M.S. S.R.L." }, - { 0x2635, "uHDevice Technology Ltd." }, - { 0x2636, "MED-EL Medical Electronics" }, - { 0x2637, "TAEWOONG MEDICAL. CO., LTD." }, - { 0x2638, "Becker-Antriebe GmbH" }, - { 0x2639, "Xsens Technologies B.V." }, - { 0x263A, "Maury Microwave" }, - { 0x263B, "Time & Data Systems International Ltd." }, - { 0x263C, "Schultes Microcomputer-Vertriebs-GmbH & Co KG" }, - { 0x263D, "pls Programmierbare Logik & Systeme GmbH" }, - { 0x263E, "Odin TeleSystems Inc." }, - { 0x263F, "ES-Experts, Ltd." }, - { 0x2640, "Banner Engineering" }, - { 0x2641, "PRO TUNE ELECTRONIC SYSTEMS" }, - { 0x2642, "NPP ELIKS America Inc. DBA T&M Atlantic" }, - { 0x2643, "COMVOX AUDIO CO., LTD." }, - { 0x2644, "Sioux Electronics B.V." }, - { 0x2645, "Lead Data Inc." }, - { 0x2646, "Bel Canto Design, Ltd." }, - { 0x2647, "FORMER ENGINEERING SERVICE CO., LTD." }, - { 0x2648, "Telongo LLC" }, - { 0x2649, "Soundspring Audio, Inc" }, - { 0x264A, "THERMALTAKE Technology Co., Ltd." }, - { 0x264B, "Industrial Indexing Systems" }, - { 0x264C, "Si14 SpA" }, - { 0x264D, "Wolfrum Elektronik & Avionik" }, - { 0x264E, "3i Corporation" }, - { 0x264F, "RF Controls, LLC" }, - { 0x2650, "Electronics For Imaging, Inc." }, - { 0x2651, "Otis Instruments Inc." }, - { 0x2652, "Fallbrook Technologies, Inc." }, - { 0x2653, "AutoHotBox" }, - { 0x2654, "DarklingX, LLC" }, - { 0x2655, "Moog Inc." }, - { 0x2656, "Ashcroft Inc." }, - { 0x2657, "Embedia Technologies Corporation" }, - { 0x2658, "Sintermask GmbH" }, - { 0x2659, "Sundtek" }, - { 0x265A, "3Brain GmbH" }, - { 0x265B, "D-tect Systems" }, - { 0x265C, "IDEX Health + Science LLC" }, - { 0x265D, "H. Schomaecker GmbH" }, - { 0x265E, "JSC Engineering Centre Energoservice" }, - { 0x265F, "Azatrax" }, - { 0x2660, "YEONG DER (SUM-EM) Enterprises Co., Ltd." }, - { 0x2661, "WorldCast Systems" }, - { 0x2662, "MOOG Music Inc." }, - { 0x2663, "JOMESA Messsysteme GmbH" }, - { 0x2664, "NOHMI BOSAI Ltd." }, - { 0x2665, "Yamaki Electric Corporation" }, - { 0x2666, "BLX IC Design Corp., Ltd." }, - { 0x2667, "SuZhou ZhongXingLian Precision Industrial Co., Ltd." }, - { 0x2668, "Shenzhen Yuwenfa Electronic Technology Co., Ltd." }, - { 0x2669, "ME4SURE, Inc." }, - { 0x266A, "Linear LLC" }, - { 0x266B, "ProSys Development Services" }, - { 0x266C, "Brightsight BV" }, - { 0x266D, "Ergotest Innovation A.S." }, - { 0x266E, "Multimedia Link, Inc." }, - { 0x266F, "Shanghai Zhengyuan Technologies Co., Ltd." }, - { 0x2670, "Zhengzhou Xin Da Jie An Information Technology Co., Ltd" }, - { 0x2671, "Innovative Logic" }, - { 0x2672, "GoPro" }, - { 0x2673, "Wadia Digital" }, - { 0x2674, "Hoyt Monitor Technologies, LLC" }, - { 0x2675, "Peter Huber Kaeltemaschinenbau GmbH" }, - { 0x2676, "Basler AG" }, - { 0x2677, "Winegard Company" }, - { 0x2678, "Sky Deutschland GmbH & Co. KG" }, - { 0x2679, "BESTMEDIA CD-Recordable GmbH & Co. KG" }, - { 0x267A, "Xi'an YEP Telecommunication Technology Co., Ltd." }, - { 0x267B, "Palpilot International Corp." }, - { 0x267C, "OptiGene Limited" }, - { 0x267D, "KOHZU Precision Co., Ltd." }, - { 0x267E, "E.D. Bullard Company" }, - { 0x267F, "Acromag Inc." }, - { 0x2680, "DIGICO UK Limited" }, - { 0x2681, "MYLAPS B.V." }, - { 0x2682, "ROBOX S.P.A." }, - { 0x2683, "Gazogiken Co., Ltd." }, - { 0x2684, "Funkwerk Security Communications GmbH" }, - { 0x2685, "Cardo Systems Inc." }, - { 0x2686, "IP LABS Inc." }, - { 0x2687, "FITBIT" }, - { 0x2688, "Stratasys Inc." }, - { 0x2689, "StepOver Inc." }, - { 0x268A, "QEES" }, - { 0x268B, "Dimension Engineering LLC" }, - { 0x268C, "AMS-TAOS" }, - { 0x268D, "WEISS ENGINEERING LTD." }, - { 0x268E, "xyzmo Software GmbH" }, - { 0x268F, "LETech Co., Ltd." }, - { 0x2690, "K.K. Rabbit" }, - { 0x2691, "ZINK Imaging, Inc." }, - { 0x2692, "CELLIENT CO., LTD." }, - { 0x2693, "Silvershore Technology Partners" }, - { 0x2694, "RoboteX Inc." }, - { 0x2695, "DynaGen Technologies Inc." }, - { 0x2696, "Sensovation AG" }, - { 0x2697, "Anfatec Instruments" }, - { 0x2698, "EVTD Inc." }, - { 0x2699, "ECOUS Corp." }, - { 0x269A, "BETTER MANAGE INVESTMENTS LIMITED" }, - { 0x269B, "Novel Data Solutions (Suzhou) Corporation" }, - { 0x269C, "ECTRON CORPORATION" }, - { 0x269D, "Accessible Technologies, Inc." }, - { 0x269E, "Astro Gaming" }, - { 0x269F, "DKL TECHNOLOGY (SHENZHEN) CO., LTD." }, - { 0x26A0, "MIDAS" }, - { 0x26A1, "Miris AB" }, - { 0x26A2, "Eppendorf AG" }, - { 0x26A3, "EMKO ELEKTRONIK SAN. VE TIC. AS" }, - { 0x26A4, "Blue Goji" }, - { 0x26A5, "CAL TEST ELECTRONICS, INC." }, - { 0x26A6, "Radio Design Group, Inc." }, - { 0x26A7, "LOG-IN, Inc." }, - { 0x26A8, "UNIREX CORPORATION" }, - { 0x26A9, "Research Industrial Systems IT-Engineering (RISE) GmbH" }, - { 0x26AA, "YAESU MUSEN CO., LTD." }, - { 0x26AB, "Motion Control Systems, Inc." }, - { 0x26AC, "3D Robotics Inc." }, - { 0x26AD, "Global Distribution GmbH" }, - { 0x26AE, "Oscium" }, - { 0x26AF, "Bombardier Transportation GmbH, TCMS Development Ctr 2" }, - { 0x26B0, "Zhejiang Senda Electronics Co., Ltd." }, - { 0x26B1, "Bassett Electronic Systems Limited" }, - { 0x26B2, "RST Instruments Ltd." }, - { 0x26B3, "Global Inkjet Systems" }, - { 0x26B4, "Sensor Technology Limited" }, - { 0x26B5, "ELECTROCOMPANIET AS" }, - { 0x26B6, "Pacom Systems Pty. Ltd." }, - { 0x26B7, "Azusatekuno" }, - { 0x26B8, "InkControl, LLC" }, - { 0x26B9, "Satlantic LP" }, - { 0x26BA, "Freetronics Pty Ltd." }, - { 0x26BB, "Omega Elektronik Sanayi ve Ticaret A.S." }, - { 0x26BC, "CARDIN ELETTRONICA S.p.A." }, - { 0x26BD, "Integral Memory Plc." }, - { 0x26BE, "AKASA (ASIA) CORP." }, - { 0x26BF, "Broadway System, Inc." }, - { 0x26C0, "RADIODETECTION LTD." }, - { 0x26C1, "Viola Audio Laboratories" }, - { 0x26C2, "FUTURE UNIVERSITY HAKODATE" }, - { 0x26C3, "HARLEY-DAVIDSON MOTOR COMPANY" }, - { 0x26C4, "Logic Way GmbH" }, - { 0x26C5, "TOKAI RUBBER INDUSTRIES, LTD." }, - { 0x26C6, "GRAF-SYTECO GmbH & Co. KG" }, - { 0x26C7, "Beijing Stone New Technology Industry Co., Ltd." }, - { 0x26C8, "SCHMID mme - electronic product engineering" }, - { 0x26C9, "SPM INSTRUMENT AB" }, - { 0x26CA, "MSY Inc." }, - { 0x26CB, "Sung Kyung Precision Co., Ltd." }, - { 0x26CC, "Hunting Titan" }, - { 0x26CD, "Blendology Limited" }, - { 0x26CE, "ASRock Inc." }, - { 0x26CF, "The Gate Technologies" }, - { 0x26D0, "ZK Celltest, Inc." }, - { 0x26D1, "THORLABS LTD." }, - { 0x26D2, "Jiangsu Yinhe Electronics Co., Ltd." }, - { 0x26D3, "VIBRATION INSTRUMENTS CO., LTD." }, - { 0x26D4, "Truesense Imaging" }, - { 0x26D5, "Equinox Payments, LLC" }, - { 0x26D6, "Sistemi Elettronici Di Addonizio Luisa" }, - { 0x26D7, "POPSPA (HK) LTD." }, - { 0x26D8, "APR, LLC" }, - { 0x26D9, "ATC-NY" }, - { 0x26DA, "Dabi Atlante" }, - { 0x26DB, "American DJ Supply" }, - { 0x26DC, "Gato Audio" }, - { 0x26DD, "Monnit Corp." }, - { 0x26DE, "Velocity Micro, Inc." }, - { 0x26DF, "University of Cambridge" }, - { 0x26E0, "Shenzhen Shixin Digital Co., Ltd." }, - { 0x26E1, "CrucialTec Co., Ltd." }, - { 0x26E2, "Ingenieurbuero Dietzsch und Thiele PartG" }, - { 0x26E3, "SHENZHEN EXCEL DIGITAL TECHNOLOGY CO., LTD." }, - { 0x26E4, "VIZIO, Inc." }, - { 0x26E5, "Shaghal Ltd." }, - { 0x26E6, "ORC Manufacturing Co., Ltd." }, - { 0x26E7, "Fishman" }, - { 0x26E8, "Camgian Microsystems" }, - { 0x26E9, "Lumenergi Inc." }, - { 0x26EA, "OPTOVUE INC." }, - { 0x26EB, "emtrion GmbH" }, - { 0x26EC, "SLE quality engineering GmbH & Co. KG" }, - { 0x26ED, "a.tron3d GmbH" }, - { 0x26EE, "Grimm Audio" }, - { 0x26EF, "TAKEBISHI CORPORATION" }, - { 0x26F0, "EDM Corporation" }, - { 0x26F1, "Fujian LANDI Commercial Equipment Co., Ltd." }, - { 0x26F2, "AUDIS SARL" }, - { 0x26F3, "Raven Systems Design, Inc." }, - { 0x26F4, "RTW GmbH & Co. KG" }, - { 0x26F5, "Morning Star Digital Connector Co., Ltd." }, - { 0x26F6, "Sea-Bird Electronics" }, - { 0x26F7, "BFFT GmbH" }, - { 0x26F8, "Salon Transcripts, Inc." }, - { 0x26F9, "Outstanding Technology Co., Ltd." }, - { 0x26FA, "DAQ SYSTEM Co., Ltd." }, - { 0x26FB, "FLIR Advanced Imaging Systems" }, - { 0x26FC, "Raven Industries" }, - { 0x26FD, "Foot Levelers, Inc." }, - { 0x26FE, "ESPROS Photonics AG" }, - { 0x26FF, "MIA Corporation" }, - { 0x2700, "MITACHI CO., LTD." }, - { 0x2701, "Pro Design Electronic GmbH" }, - { 0x2702, "Hobart GmbH" }, - { 0x2703, "Greenwave Reality Pte. Ltd." }, - { 0x2704, "Unisun Innovation Incorporated" }, - { 0x2705, "CardioGrip Corporation" }, - { 0x2706, "iKey, Ltd." }, - { 0x2707, "Bardac Corporation" }, - { 0x2708, "Audient Limited" }, - { 0x2709, "ZEON CORPORATION" }, - { 0x270A, "Channel Islands Audio" }, - { 0x270B, "MSHeli Srl" }, - { 0x270C, "Inhon Computer Co., Ltd." }, - { 0x270D, "ROSAND Technologies" }, - { 0x270E, "Applied Security Inc." }, - { 0x270F, "Western Digital, HGST" }, - { 0x2710, "Kontron America, Inc." }, - { 0x2711, "ASD Inc." }, - { 0x2712, "US Army Benet Laboratories" }, - { 0x2713, "Datalink Electronics Ltd." }, - { 0x2714, "i'm S.p.A." }, - { 0x2715, "Photron Limited" }, - { 0x2716, "YUEN DA ELECTRONIC PRODUCTS FACTORY" }, - { 0x2717, "Xiaomi Communications Co., Ltd." }, - { 0x2718, "Tamaggo" }, - { 0x2719, "4iiii Innovations Inc." }, - { 0x271A, "KONE Industrial Ltd." }, - { 0x271B, "Tec.to" }, - { 0x271C, "KDDI Technology Corporation" }, - { 0x271D, "Gionee Communication Equipment Co., Ltd. ShenZhen" }, - { 0x271E, "Changzhou Traful Electronic Co., Ltd." }, - { 0x271F, "Shanghai Nufront Electronic Technology Co., Ltd." }, - { 0x2720, "motrona GmbH" }, - { 0x2721, "Germaneers GmbH" }, - { 0x2722, "TRANIT" }, - { 0x2723, "KUK Electronic AG" }, - { 0x2724, "XS Technology, Inc." }, - { 0x2725, "L-3 Applied Signal & Image Technology" }, - { 0x2726, "Universal Electronics Inc. (dba: TVIEW)" }, - { 0x2727, "ANM OPTO LIMITED" }, - { 0x2728, "STX-Med SPRL" }, - { 0x2729, "Regenersis (Glenrothes) Ltd." }, - { 0x272A, "StarLeaf Limited" }, - { 0x272B, "VAT Vakuumventile AG" }, - { 0x272C, "IAR Systems" }, - { 0x272D, "AKAR GAME LTD." }, - { 0x272E, "Teratronik elektronische Systeme GmbH" }, - { 0x272F, "tommis gmbh, Ingenieurburo f. Nachrichtentechnik u. Aut" }, - { 0x2730, "Camozzi spa" }, - { 0x2731, "Pebble Audio Oy" }, - { 0x2732, "Samsung Medison Co., Ltd." }, - { 0x2733, "ShenZhen SunSonny Electronic Technology Co., Ltd." }, - { 0x2734, "Wuhan XinAn LuoJia Technologies Co., Ltd." }, - { 0x2735, "Wilk Elektronik S.A." }, - { 0x2736, "Silver Palm Technologies LLC" }, - { 0x2737, "Blu Controls" }, - { 0x2738, "Bad Rabby Designs" }, - { 0x2739, "BluePacket Communications Co., Ltd." }, - { 0x273A, "Singular Technology Co., Ltd." }, - { 0x273B, "TecScan Systems Inc." }, - { 0x273C, "Etherstack Limited" }, - { 0x273D, "Thrimona Corporation" }, - { 0x273E, "LIFODAS" }, - { 0x273F, "Hughski Limited" }, - { 0x2740, "Apparent Corporation" }, - { 0x2741, "N2 Imaging Systems" }, - { 0x2742, "Organ Recovery Systems, Inc." }, - { 0x2743, "XS Embedded GmbH" }, - { 0x2744, "RIKEN KEIKI NARA MFG. Co., Ltd." }, - { 0x2745, "Unitech Electronics Co., Ltd." }, - { 0x2746, "Shenzhen YishunTai Metal Factory" }, - { 0x2747, "AHA INC. Co., Ltd." }, - { 0x2748, "Stresstech Oy" }, - { 0x2749, "GMV SISTEMAS" }, - { 0x274A, "Qdac Inc." }, - { 0x274B, "Automotive Data Solutions, Inc." }, - { 0x274C, "Atos Worldline" }, - { 0x274D, "FXI Technologies AS" }, - { 0x274E, "VECTRONIC Aerospace GmbH" }, - { 0x274F, "Dacuda AG" }, - { 0x2750, "SafeLine Sweden AB" }, - { 0x2751, "AMI International, Inc." }, - { 0x2752, "miniDSP Ltd." }, - { 0x2753, "Danville Signal Processing, Inc." }, - { 0x2754, "Trapeze Software Group, Inc." }, - { 0x2755, "Cosmic Circuits Pvt. Ltd." }, - { 0x2756, "Victor Hasselblad AB" }, - { 0x2757, "HiteVision Digital Media Technology Co., Ltd." }, - { 0x2758, "MobileEco Co., Ltd." }, - { 0x2759, "Philip Morris Products S.A." }, - { 0x275A, "Vertex Aquaristik GmbH" }, - { 0x275B, "PROPACK" }, - { 0x275C, "NITA, LLC" }, - { 0x275D, "NewSoc Tech Limited" }, - { 0x275E, "Scent Sciences Corporation" }, - { 0x275F, "Vishay Measurements Group, Inc." }, - { 0x2760, "Oxigraf, Inc." }, - { 0x2761, "CAST Navigation LLC" }, - { 0x2762, "FERMAX ELECTRONICA S.A.U." }, - { 0x2763, "PRIMES GmbH" }, - { 0x2764, "Ouman Oy" }, - { 0x2765, "Firstbeat Technologies Ltd." }, - { 0x2766, "LifeScan" }, - { 0x2767, "Cheetah Hi-Tech, Inc." }, - { 0x2768, "DongGuan City Lian Zhi Electronic Technology Co. Ltd." }, - { 0x2769, "SPI ENGINEERING Co., Ltd." }, - { 0x276A, "SUGIYAMA ELECTRIC SYSTEM INC." }, - { 0x276B, "CTI INFORMATION CENTER CO., LTD." }, - { 0x276C, "PROTEI" }, - { 0x276D, "YSTEK Technology Company" }, - { 0x276E, "RGB Lasersysteme GmbH" }, - { 0x276F, "Lightware Visual Engineering" }, - { 0x2771, "TTE Corporation" }, - { 0x2772, "Audio Tuning Vertriebs GmbH" }, - { 0x2773, "HILTI AG" }, - { 0x2774, "Novasina AG" }, - { 0x2775, "Sonardyne International Ltd." }, - { 0x2776, "KFI Trading s.r.l." }, - { 0x2777, "SingTrix LLC" }, - { 0x2778, "Cypher Labs LLC" }, - { 0x2779, "Qualnetics Corporation" }, - { 0x277A, "Occipital, Inc." }, - { 0x277B, "Moxtek, Inc" }, - { 0x277C, "SignalCore, Inc." }, - { 0x277D, "Microcom Corporation" }, - { 0x277E, "Sportable Scoreboards, Inc." }, - { 0x277F, "DongGuan City Shangjie Electronic Co., Ltd." }, - { 0x2780, "M31 Technology Corp." }, - { 0x2781, "Liteconn Co., Ltd." }, - { 0x2782, "TTS Inc." }, - { 0x2783, "Aktina Medical Corp." }, - { 0x2784, "A-One Co., Ltd." }, - { 0x2785, "Mayekawa Mfg. Co., Ltd." }, - { 0x2786, "Switch Science, Incorporation" }, - { 0x2787, "AVTECH Corporation" }, - { 0x2788, "Sanwin (HK) Electronic Technology Co., Ltd." }, - { 0x2789, "Suzhou WEIJU Electronics Technology Co., Ltd." }, - { 0x278A, "MARSHAL Corporation" }, - { 0x278B, "The Rotel Co., Ltd." }, - { 0x278C, "NAGATA ELECTRIC CO., LTD." }, - { 0x278D, "GPSports Systems Pty., Ltd." }, - { 0x278E, "TSS AB" }, - { 0x278F, "Bosch Sicherheitssysteme Engineering GmbH" }, - { 0x2790, "Cobalt Digital, Inc." }, - { 0x2791, "SunTech Medical, Inc." }, - { 0x2792, "SYSTEC Co., Limited" }, - { 0x2793, "i-KAIST" }, - { 0x2794, "SilverPlus, Inc." }, - { 0x2795, "QuantaScope Biotech" }, - { 0x2796, "Zhejiang Wellcom Technology Co., Ltd." }, - { 0x2797, "EUROIMMUN AG" }, - { 0x2798, "Turning Technologies" }, - { 0x2799, "Colorimetry Research, Inc." }, - { 0x279A, "Naim Audio Limited" }, - { 0x279B, "Bluefish Technologies Pty Ltd." }, - { 0x279C, "Advanced Anaesthesia Specialists" }, - { 0x279D, "Towa Electronics Co., Ltd." }, - { 0x279E, "Syntronix Corporation" }, - { 0x279F, "Hiragawa Electronics Industry Co., Ltd." }, - { 0x27A0, "Mondokey Limited" }, - { 0x27A1, "Autoliv Romania S.R.L." }, - { 0x27A2, "T.I.T. ENG CO., LTD." }, - { 0x27A3, "AU Optronics Corporation" }, - { 0x27A4, "Digital Act Inc." }, - { 0x27A5, "Advantest Corporation" }, - { 0x27A6, "iRobot Corporation" }, - { 0x27A7, "Delta Computer Systems, Inc." }, - { 0x27A8, "Square Inc." }, - { 0x27A9, "Global Mixed-mode Technology Inc." }, - { 0x27AA, "Just Connector Kunshan Co., Ltd." }, - { 0x27AB, "Shenzhen Maxmade Technology Co., Ltd." }, - { 0x27AC, "GP Electronics (HK) Limited" }, - { 0x27AD, "PAUL HARTMANN AG" }, - { 0x27AE, "TeleOrbit GmbH" }, - { 0x27AF, "HANNA Instruments, Inc." }, - { 0x27B0, "FOXPRO Inc." }, - { 0x27B1, "UltiMachine" }, - { 0x27B2, "OrthoAccel Technologies, Inc." }, - { 0x27B3, "Secure Systems Limited" }, - { 0x27B4, "Duerkopp Adler AG" }, - { 0x27B5, "J-MEX Inc." }, - { 0x27B6, "TechnoKom Ltd." }, - { 0x27B7, "Fraunhofer IMS" }, - { 0x27B8, "ThingM Corporation" }, - { 0x27B9, "Ziotech Corp" }, - { 0x27BA, "Aoptix Technologies, Inc." }, - { 0x27BB, "Plenom A/S" }, - { 0x27BC, "KeyView" }, - { 0x27BD, "Codethink Limited" }, - { 0x27BE, "InHand Electronics, Inc." }, - { 0x27BF, "Dongguan CPO Electronic Co., Ltd." }, - { 0x27C0, "Cadwell Laboratories, Inc." }, - { 0x27C1, "ARKAMI" }, - { 0x27C2, "ArcBotics LLC" }, - { 0x27C3, "Danfoss Turbocor Compressors Inc." }, - { 0x27C4, "KRYPTUS" }, - { 0x27C5, "SRT Marine Technology Limited" }, - { 0x27C6, "Shenzhen Huiding Technology Co. Ltd." }, - { 0x27C7, "TransluSense, LLC" }, - { 0x27C8, "Rigaku Corporation" }, - { 0x27C9, "ElaraTek LTD." }, - { 0x27CA, "JayBird LLC" }, - { 0x27CB, "ANXA Limited Hong Kong" }, - { 0x27CC, "GHL Matthias Gross GmbH & Co. KG" }, - { 0x27CD, "GHEO SA" }, - { 0x27CE, "Double Power Technology Inc." }, - { 0x27CF, "Weidmueller Interface GmbH & Co. KG" }, - { 0x27D0, "Traxon Technologies Europe GmbH" }, - { 0x27D1, "Angelbird Technologies GmbH" }, - { 0x27D2, "EURONOVATE SA" }, - { 0x27D3, "PRECIA MOLEN" }, - { 0x27D4, "Blackstar Amplification Ltd." }, - { 0x27D5, "BSkyB LTD." }, - { 0x27D6, "T3 Innovation" }, - { 0x27D7, "Senova Systems, Inc." }, - { 0x27D8, "Patriot Memory" }, - { 0x27D9, "Gallagher Group Limited" }, - { 0x27DA, "S Net Media Inc." }, - { 0x27DB, "Hiitop Technology Limited" }, - { 0x27DC, "Tennant Company" }, - { 0x27DD, "Shenzhen MinDe Electronics Technology Ltd." }, - { 0x27DE, "Newtec Cy" }, - { 0x27DF, "Charles Novacroft Direct Limited" }, - { 0x27E0, "Stelulu Technology" }, - { 0x27E1, "TRX Systems, Inc." }, - { 0x27E2, "Natus Medical Incorproated" }, - { 0x27E3, "Chemyx Inc." }, - { 0x27E4, "Easybotics LLC" }, - { 0x27E5, "Shiroshita Industrial Co., Ltd." }, - { 0x27E6, "SENECA srl" }, - { 0x27E7, "AVIWEST" }, - { 0x27E8, "takwak GmbH" }, - { 0x27E9, "Soeks Limited" }, - { 0x27EA, "Goldmund International" }, - { 0x27EB, "ACCUCOMM, INC." }, - { 0x27EC, "SEETECH CO., LTD." }, - { 0x27ED, "Tescom-Emerson Process Management" }, - { 0x27EE, "DashLogic Inc." }, - { 0x27EF, "TAIYO SEIKI CO., LTD." }, - { 0x27F0, "DITECT Corporation" }, - { 0x27F1, "VERTU Corporation Limited" }, - { 0x27F2, "Softnautics Private Limited" }, - { 0x27F3, "Indutherm Erwaermungsanlagen GmbH" }, - { 0x27F4, "LEGIC Identsystems Ltd." }, - { 0x27F5, "Relume Technologies, Inc." }, - { 0x27F6, "Advanced Simulation Technology Inc." }, - { 0x27F7, "Wyred 4 Sound" }, - { 0x27F8, "Wikipad, Inc." }, - { 0x27F9, "MIDAS Elektronik GmbH" }, - { 0x27FA, "Afag Automation AG" }, - { 0x27FB, "Barclays" }, - { 0x27FC, "CAREL SPA" }, - { 0x27FD, "GI Therapies Pty Ltd." }, - { 0x27FE, "DONGGUAN Rakecorp Co., Ltd." }, - { 0x27FF, "Cashway Technology Co., Ltd." }, - { 0x2800, "iluminage, Inc." }, - { 0x2801, "Pear Sports LLC" }, - { 0x2802, "Moixa Technology" }, - { 0x2803, "StarLine LLC" }, - { 0x2804, "4MOD Technology" }, - { 0x2805, "Shenzhen N-Pass Mobile Technology, Ltd." }, - { 0x2806, "RF DataTech" }, - { 0x2807, "Elliptic Laboratories AS" }, - { 0x2808, "FocalTech Systems, Ltd." }, - { 0x2809, "Sept Co., Ltd." }, - { 0x280A, "Culti Co., Ltd." }, - { 0x280B, "Dukane Corporation" }, - { 0x280C, "Linera" }, - { 0x280D, "Ai Electronic Industry Co., Ltd." }, - { 0x280E, "Leaf Imaging Ltd." }, - { 0x280F, "MBit Wireless, Inc." }, - { 0x2810, "Aphex, LLC" }, - { 0x2811, "DigiTalks INC." }, - { 0x2812, "Bridge Semiconductor Corp." }, - { 0x2813, "Brookfield Engineering Laboratories Inc." }, - { 0x2814, "OOO SMS-Soft" }, - { 0x2815, "KING TSUSHIN KOGYO CO., LTD." }, - { 0x2816, "Harvard Photonix" }, - { 0x2817, "Test Equipment Plus" }, - { 0x2818, "Codex Digital Limited" }, - { 0x2819, "MESSRING Systembau MSG GmbH" }, - { 0x281A, "SWAC Automation Consult GmbH" }, - { 0x281B, "HiES Tech s.r.o." }, - { 0x281C, "Presidium Instruments Pte. Ltd." }, - { 0x281D, "AISIN AW CO., LTD." }, - { 0x281E, "Symphodia Phil" }, - { 0x281F, "Motion Control, Inc." }, - { 0x2820, "Sanovas" }, - { 0x2821, "Aclima Inc." }, - { 0x2822, "REFLEXdigital" }, - { 0x2823, "Dongguan Jiumutong Industry Co., Ltd." }, - { 0x2824, "Vollsun Ltd." }, - { 0x2825, "Baumer Optronic GmbH" }, - { 0x2826, "BSH Bosch und Siemens Hausgerate GmbH" }, - { 0x2827, "DIGITTRADE GmbH" }, - { 0x2828, "SAPHYMO" }, - { 0x2829, "Scanomat A/S" }, - { 0x282A, "REDL GmbH" }, - { 0x282B, "Aevoe Inc." }, - { 0x282C, "Reichert, Inc." }, - { 0x282D, "Aeromax Technology Co., Ltd." }, - { 0x282E, "Vectawave Technology Ltd." }, - { 0x282F, "SANKEN ELECTRIC CO., LTD." }, - { 0x2830, "GD-Broadband" }, - { 0x2831, "Power Integrations" }, - { 0x2832, "Applied Research Associates" }, - { 0x2833, "Oculus VR LLC" }, - { 0x2834, "JM Concept" }, - { 0x2835, "SEIDENSHA ELECTRONICS Co., Ltd." }, - { 0x2836, "OUYA Inc." }, - { 0x2837, "Tunstall Healthcare (UK) Ltd." }, - { 0x2838, "Ontorix GmbH" }, - { 0x2839, "Grass Elektronik" }, - { 0x283A, "HIKe Mobile Co., Ltd." }, - { 0x283B, "Cellon Communications Technology (Shenzhen) Co., Ltd." }, - { 0x283C, "HIGH TEK HARNESS ENTERPRISE CO., LTD." }, - { 0x283D, "SigNET (AC) Ltd." }, - { 0x283E, "DECATHLON SA" }, - { 0x283F, "Elprosys Sp. Z.o.o." }, - { 0x2840, "Taiwan Carol Electronics Co., Ltd." }, - { 0x2841, "Artvision Technologies Inc." }, - { 0x2842, "RobotGroup" }, - { 0x2843, "SyncMOS Technologies International, Inc." }, - { 0x2844, "ELSIST Srl" }, - { 0x2845, "Systec Designs BV" }, - { 0x2846, "ATRON electronic GmbH" }, - { 0x2847, "TMG TE GmbH" }, - { 0x2848, "Sentons USA, Inc." }, - { 0x2849, "Astronics Advanced Electronic Systems Corp." }, - { 0x284A, "Yangtze Optical Fibre and Cable Company Ltd." }, - { 0x284B, "Leadingui Co., Ltd." }, - { 0x284C, "Full in Hope Co., Ltd." }, - { 0x284D, "Qltouch Tech Co., Ltd." }, - { 0x284E, "Flysky RC Model Co., Ltd." }, - { 0x284F, "ANTLIA SA" }, - { 0x2850, "Intellectual Property Group SA" }, - { 0x2851, "RETIA, a.s." }, - { 0x2852, "Virtual Console, LLC" }, - { 0x2853, "Ralston Instruments" }, - { 0x2854, "Great River Technology" }, - { 0x2855, "System Dimensions, Inc." }, - { 0x2856, "Thales Alenia Space - Italia" }, - { 0x2857, "Skardin Industrial Corporation" }, - { 0x2858, "PT Doo Won Precision Indonesia" }, - { 0x2859, "Viconn Technology (HK) Co., Ltd." }, - { 0x285A, "AiM Touch Technology Co., Ltd." }, - { 0x285B, "HARDWARE & SOFTWARE TECHNOLOGY CO., LTD." }, - { 0x285C, "URMET S.p.a." }, - { 0x285D, "Alarm.com, Inc." }, - { 0x285E, "Occam Robotics" }, - { 0x285F, "CyWee Group Limited" }, - { 0x2860, "WISYCOM UNIPERSONALE s.r.l." }, - { 0x2861, "Pacific Image Electronics Co., Ltd." }, - { 0x2862, "DeVilbiss Healthcare LLC" }, - { 0x2863, "BIOMATIQUES IDENTIFICATION SOLUTIONS PRIVATE LIMITED" }, - { 0x2864, "Wenngo Inc." }, - { 0x2865, "VIKING GmbH" }, - { 0x2866, "SLOW CONTROL" }, - { 0x2867, "DASCOM" }, - { 0x2868, "Chakra Energetics Ltd." }, - { 0x2869, "Comfort Audio AB" }, - { 0x286A, "Dipl. - Ing. H. Horstmann GmbH" }, - { 0x286B, "STANEO SAS" }, - { 0x286C, "Atest-Gaz A. M. Pachole sp. j." }, - { 0x286D, "Production Resource Group, LLC" }, - { 0x286E, "Geosense Inc." }, - { 0x286F, "Bretford Manufacturing Inc." }, - { 0x2870, "Typhoon HIL, Inc." }, - { 0x2871, "BYK-Gardner GmbH" }, - { 0x2872, "Brite Semiconductor (Shanghai) Corporation" }, - { 0x2873, "Spire Payments Holdings S.a.r.l." }, - { 0x2874, "Dexter Research Center, Inc." }, - { 0x2875, "nVideon, Inc." }, - { 0x2876, "Safety Innovations, Inc." }, - { 0x2877, "BrightSign LLC" }, - { 0x2878, "Cabletech Electronics (Hong Kong) Co., Ltd." }, - { 0x2879, "Rancore Technologies Private Limited" }, - { 0x287A, "Shenzhen Bojuxing Industrial Development Co., Ltd." }, - { 0x287B, "Pro-Tech" }, - { 0x287C, "Special Recording Systems Ltd." }, - { 0x287D, "Pettersson Elektronik AB" }, - { 0x287E, "Silicon Designs, Inc." }, - { 0x287F, "Beijing Jinke XinAn Technology Co., Ltd." }, - { 0x2880, "Black Diamond Video" }, - { 0x2881, "DX Antenna Co., Ltd." }, - { 0x2882, "GCOMM CORPORATION" }, - { 0x2883, "abatec group AG" }, - { 0x2884, "Bor" }, - { 0x2885, "Quantec SA" }, - { 0x2886, "Seeed Technology Co., Ltd." }, - { 0x2887, "Specwerkz" }, - { 0x2888, "VEX Robotics, Inc." }, - { 0x2889, "TrueVision Systems, Inc." }, - { 0x288A, "LEXIBOOK LIMITED" }, - { 0x288B, "Hierstar (Suzhou)" }, - { 0x288C, "Moswell Co., Ltd." }, - { 0x288D, "Centre for Development of Advanced Computing (C-DAC)" }, - { 0x288E, "mce-systems Ltd." }, - { 0x288F, "Voxx Accessories Corp." }, - { 0x2890, "Teknic, Inc." }, - { 0x2891, "Flytec AG" }, - { 0x2892, "NAVIgard" }, - { 0x2893, "LEVEL Ltd." }, - { 0x2894, "Hovercam" }, - { 0x2895, "INIM Electronics s.r.l." }, - { 0x2896, "TTAF Elektronik Sanayi ve Ticaret Ltd. Sti." }, - { 0x2897, "SDJ Technologies, Inc." }, - { 0x2898, "Accumetrics Associates, Inc." }, - { 0x2899, "Toptronic Industrial Co., Ltd." }, - { 0x289A, "Scan-Sense A.S." }, - { 0x289B, "DRACAL Technologies Inc." }, - { 0x289C, "TLS Corp." }, - { 0x289D, "Tyrian Systems, Inc." }, - { 0x289E, "Esselte Leitz GmbH & Co. KG" }, - { 0x289F, "inoage GmbH" }, - { 0x28A0, "I-CUBE TECHNOLOGY Co., Ltd." }, - { 0x28A1, "AVEST-SYSTEMS Private Unitary Enterprise" }, - { 0x28A2, "Meadowlark Optics Incorporated" }, - { 0x28A3, "SensoMotoric Instruments GmbH" }, - { 0x28A4, "Objective Solutions Sweden AB" }, - { 0x28A5, "TCS John Huxley" }, - { 0x28A6, "E-SEEK Inc." }, - { 0x28A7, "Hugo Brennenstuhl GmbH & Co. KG" }, - { 0x28A8, "AT Sciences, LLC" }, - { 0x28A9, "Alpha Technologies" }, - { 0x28AA, "Realta Entertainment Group" }, - { 0x28AB, "Navigil Ltd." }, - { 0x28AC, "euroBRAILLE" }, - { 0x28AD, "iDTRONIC GmbH" }, - { 0x28AE, "Zynaptic Limited" }, - { 0x28AF, "Sharkbay Technologies Pte. Ltd." }, - { 0x28B0, "PMC - Sierra" }, - { 0x28B1, "EcoTech, Inc." }, - { 0x28B2, "Siemens Infrastructure & Cities" }, - { 0x28B3, "Profoto AB" }, - { 0x28B4, "TOACK Corporation" }, - { 0x28B5, "Solacom Inc." }, - { 0x28B6, "Alcohol Countermeasure Systems Corp." }, - { 0x28B7, "Pleora Technologies Inc." }, - { 0x28B8, "Swiss Authentication Research & Development AG" }, - { 0x28B9, "Kapsch TrafficCom AB" }, - { 0x28BA, "RSscan International NV" }, - { 0x28BB, "ICP Systems b.v." }, - { 0x28BC, "Cyplex Corporation" }, - { 0x28BD, "GuangZhou Ugee Computer Technology Co., Ltd." }, - { 0x28BE, "GMG TECH. Co., Ltd." }, - { 0x28BF, "Vitetech Int'l Co., Ltd." }, - { 0x28C0, "SCVNGR, Inc." }, - { 0x28C1, "DOMMEL GmbH" }, - { 0x28C2, "Tapko Technologies GmbH" }, - { 0x28C3, "MITSUBISHI ELECTRIC SYSTEM & SERVICE CO., LTD." }, - { 0x28C4, "GALA, Inc." }, - { 0x28C5, "ShenZhen Innovate-link Precision Hardware Co., Ltd." }, - { 0x28C6, "FASTLITE" }, - { 0x28C7, "Ultimaker BV" }, - { 0x28C8, "ULTRACHIP Inc." }, - { 0x28C9, "DongGuan City DHE Wire & Cable Co., Ltd." }, - { 0x28CA, "NUMATA Corporation" }, - { 0x28CB, "GO engineering GmbH" }, - { 0x28CC, "MIWA ELECTRIC CO., LTD." }, - { 0x28CD, "SMARTMATIC INTERNATIONAL CORP." }, - { 0x28CE, "Changzhou Shi Wujin Miqi East Electronic Co., Ltd." }, - { 0x28CF, "Asiatelco Technologies Co." }, - { 0x28D0, "Stryker Corporation" }, - { 0x28D1, "Technomedica Co., Ltd." }, - { 0x28D2, "FTK Corporation" }, - { 0x28D3, "Golden Transmart International Co., Ltd." }, - { 0x28D4, "DEVIALET SAS" }, - { 0x28D5, "Vicor Corporation" }, - { 0x28D6, "Electrogamez USA Inc." }, - { 0x28D7, "Tekron International" }, - { 0x28D8, "Panda Ocean Inc." }, - { 0x28D9, "Shenzhen Yoshuo Precision Components Co., Ltd." }, - { 0x28DA, "G.SKILL Int'l Enterprice Co., Ltd." }, - { 0x28DB, "Konftel AB" }, - { 0x28DC, "Power Electronics International, Inc." }, - { 0x28DD, "AIWA COMPANY LTD. - Love Harmony (LH)" }, - { 0x28DE, "Valve Corporation" }, - { 0x28DF, "EMBED-IT" }, - { 0x28E0, "PRASIMAX" }, - { 0x28E1, "Shenzhen iSolution Technologies Co., Ltd." }, - { 0x28E2, "Surplus Electronic Technology Co., Ltd." }, - { 0x28E3, "Apollo Electrical Technology Co., Ltd." }, - { 0x28E4, "RKS, Inc." }, - { 0x28E5, "MEP TECH" }, - { 0x28E6, "BIAMP SYSTEMS" }, - { 0x28E7, "Glyph Production Technologies" }, - { 0x28E8, "Jefferson Audio Video Systems, Inc." }, - { 0x28E9, "GigaDevice Semiconductor (Beijing) Inc." }, - { 0x28EA, "Dongguan Vast Electronics Co.,Ltd" }, - { 0x28EB, "SHEN ZHEN SHI YUAN AI HARDWARE ELECTRONIC CO., LTD." }, - { 0x28EC, "Transcom Instruments Co., Ltd." }, - { 0x28ED, "Shenzhen AraTek Biometrics Technology Co., Ltd." }, - { 0x28EE, "China Mobile Group Device Co., Ltd." }, - { 0x28EF, "SEEFRONT GmbH" }, - { 0x28F0, "Elcus Electronic Company JSC" }, - { 0x28F1, "Leddartech Inc." }, - { 0x28F2, "Applied Vision Corporation" }, - { 0x28F3, "Clover Network" }, - { 0x28F4, "Sonoma Wire Works" }, - { 0x28F5, "Electrolux Laundry Systems Sweden AB" }, - { 0x28F6, "SERVOMEX Group Ltd." }, - { 0x28F7, "ANYWIRE CORPORATION" }, - { 0x28F8, "VTECH Technology Corp." }, - { 0x28F9, "Comcraft" }, - { 0x28FA, "iProtoXi Oy" }, - { 0x28FB, "Shin Hwa Contech Co., Ltd." }, - { 0x28FC, "Shandong Sinochiptp Electronic Technology Co., Ltd." }, - { 0x28FD, "Wolfson Microelectronics Plc." }, - { 0x28FE, "Marquardt Mechatronik GmbH" }, - { 0x28FF, "MIRAENANOTECH" }, - { 0x2900, "Labsphere" }, - { 0x2901, "Tolomatic Inc." }, - { 0x2902, "Woodward Inc." }, - { 0x2903, "Lightspeed Aviation" }, - { 0x2904, "Charon Technologies LLC" }, - { 0x2905, "iDea USA Products Inc." }, - { 0x2906, "Masimo Corporation" }, - { 0x2907, "Mimetics Inc." }, - { 0x2908, "Shenzhen Sen5 Technology Co., Ltd." }, - { 0x2909, "Active Mind Technology" }, - { 0x290A, "Electronic Systems Technology, Inc." }, - { 0x290B, "Beats Electronics LLC" }, - { 0x290C, "R. Hamilton & Co. Ltd." }, - { 0x290D, "IBCONN Technologies (Shenzhen) Co., Ltd." }, - { 0x290E, "Fugoo Inc." }, - { 0x290F, "AFL Noyes" }, - { 0x2910, "Cree, Inc." }, - { 0x2911, "Penetek, Inc." }, - { 0x2912, "Management Company ATOL Ltd." }, - { 0x2913, "Teladin Co., Ltd." }, - { 0x2914, "Kent Displays Inc." }, - { 0x2915, "Sage Microelectronics Corp." }, - { 0x2916, "Yota Devices Ltd." }, - { 0x2917, "Pan Xin Precision Electronics Co., Ltd." }, - { 0x2918, "Gigatronik Ingolstadt GmbH" }, - { 0x2919, "GE Analytical Instruments" }, - { 0x291A, "Anker Technology Co., Limited" }, - { 0x291B, "LONTEX PIOTR LONDZIN" }, - { 0x291C, "KEISOKUKI CENTER CO., LTD." }, - { 0x291D, "Research & Development Center ELVEES OJSC" }, - { 0x291E, "Shanghai DynamiCode Company Ltd." }, - { 0x291F, "CBN Inc." }, - { 0x2920, "Fiberplex Technologies, LLC" }, - { 0x2921, "BiovenTus, LLC" }, - { 0x2922, "Dongguan Digi-in Digital Technology Co., Ltd." }, - { 0x2923, "Vprime" }, - { 0x2924, "Chinon Corporation" }, - { 0x2925, "Flight System Consulting Inc." }, - { 0x2926, "Wildlife Acoustics, Inc." }, - { 0x2927, "BF1 Systems Ltd." }, - { 0x2928, "Dongguan Sineng Electronic Technology Co., Ltd." }, - { 0x2929, "Shenzhen Taishan Online Technology Co., Ltd." }, - { 0x292A, "T1Visions, Inc." }, - { 0x292B, "Precision Audio Device Lab Limited" }, - { 0x292C, "GENUSION, Inc." }, - { 0x292D, "Wellitec Development Limited" }, - { 0x292E, "HOYA Service Corporation" }, - { 0x292F, "Nanotec Electronic GmbH & Co. KG" }, - { 0x2930, "Ineda Systems Inc." }, - { 0x2931, "Jolla Ltd." }, - { 0x2932, "Peraso Technologies, Inc." }, - { 0x2933, "IEI Integration Corp." }, - { 0x2934, "CETA Testsysteme GmbH" }, - { 0x2935, "Nanjing Magewell Electronics Co., Ltd." }, - { 0x2936, "LEAP Motion" }, - { 0x2937, "Tmax Digital Inc." }, - { 0x2938, "Aides Technology Co., Ltd." }, - { 0x2939, "Zaber Technologies Inc." }, - { 0x293A, "The SmarTV Company" }, - { 0x293B, "Lucent Medical Systems, Inc." }, - { 0x293C, "Comcast" }, - { 0x293D, "Medicatec Inc." }, - { 0x293E, "EIDEN Co., Ltd." }, - { 0x293F, "Gan Zhou DPT-Technology Co., Ltd." }, - { 0x2940, "Shenzhen Yiwanda Electronics Co., Ltd." }, - { 0x2941, "Sanofi-Aventis Deutschland GmbH" }, - { 0x2942, "SoftLab - NSK" }, - { 0x2943, "ZAGG Inc." }, - { 0x2944, "RailComm" }, - { 0x2945, "Matrix Design Group, LLC" }, - { 0x2946, "OnAsset Intelligence Inc." }, - { 0x2947, "KAPELSE" }, - { 0x2948, "Access Network Technology Limited" }, - { 0x2949, "Shenzhen JSR Technology Co., Ltd." }, - { 0x294A, "Shenzhen Xinguodu Technology Co., Ltd." }, - { 0x294B, "snakebyte Asia Ltd." }, - { 0x294C, "Terminus Circuits Pvt Ltd." }, - { 0x294D, "Cellwise Holding Co., Ltd." }, - { 0x294E, "SHIH HUA TECHNOLOGY LTD." }, - { 0x294F, "Dollar Connection Ltd." }, - { 0x2950, "Resource One Inc." }, - { 0x2951, "Raytrix GmbH" }, - { 0x2952, "Seba Dynatronic GmbH" }, - { 0x2953, "Axes System sp. Z.o.o." }, - { 0x2954, "Human Design Medical, LLC" }, - { 0x2955, "Baidu Online Network Technology (Beijing) Co., Ltd." }, - { 0x2956, "Alfatest Ind. e Com. Produtos Eletronicos S/A" }, - { 0x2957, "OBSIDIAN RESEARCH CORPORATION" }, - { 0x2958, "Eleven Engineering Inc." }, - { 0x2959, "Inuitive" }, - { 0x295A, "ENERMAX TECHNOLOGY CORPORATION" }, - { 0x295B, "eflow Inc." }, - { 0x295C, "MediaNet M. Hermsen" }, - { 0x295D, "Positive Grid" }, - { 0x295E, "Britelite Enterprises" }, - { 0x295F, "Tecvox Connectivity, LLC" }, - { 0x2960, "Power Probe, Inc." }, - { 0x2961, "Miselu Inc." }, - { 0x2962, "Wilocity Ltd." }, - { 0x2963, "BIO-key International, Inc." }, - { 0x2964, "Kintech Co., Ltd." }, - { 0x2965, "Kortek" }, - { 0x2966, "Schatz AG" }, - { 0x2967, "St. Andrews Instrumentation Ltd." }, - { 0x2968, "Phoenix Avionics Systems, LLC" }, - { 0x2969, "Sumix" }, - { 0x296A, "Nitero, Inc." }, - { 0x296B, "Xacti Corporation" }, - { 0x296C, "KNC ONE GmbH - Research & Development" }, - { 0x296D, "Azuri Technologies Ltd" }, - { 0x296E, "LG CNS Co., Ltd." }, - { 0x296F, "Broadsound Corporation" }, - { 0x2970, "MERIDIAN SOFTWARE SYSTEMS LIMITED" }, - { 0x2971, "Ory Laboratory Ltd." }, - { 0x2972, "FiiO Electronics Technology Co., Ltd." }, - { 0x2973, "Wild Elektronik & Kunststoff GmbH & Co. KG" }, - { 0x2974, "Printrbot, Inc." }, - { 0x2975, "MPC Research Ltd." }, - { 0x2976, "COMOTA Co., Ltd." }, - { 0x2977, "Shenzhen Zowee Technology Co., Ltd." }, - { 0x2978, "Imaging Solutions Group of NY, Inc." }, - { 0x2979, "Williams Sound, LLC" }, - { 0x297A, "Innovative Developments LLC" }, - { 0x297B, "ALKERIA s.r.l." }, - { 0x297C, "HashFast Technologies LLC" }, - { 0x297D, "Krypton Solutions" }, - { 0x297E, "Shenzhen DTEC Electronic Technology Co., Ltd." }, - { 0x297F, "Emerging Technology (Holdings) Ltd." }, - { 0x2980, "CiDELEC" }, - { 0x2981, "Elektron Technology UK Limited" }, - { 0x2982, "Ableton AG" }, - { 0x2983, "Coyote System" }, - { 0x2984, "Glensound Electronics Ltd." }, - { 0x2985, "DUALO" }, - { 0x2986, "Rapt Touch (Ireland) Ltd." }, - { 0x2987, "Lyve Minds, Inc." }, - { 0x2988, "3D Systems Corporation" }, - { 0x2989, "Nanjing Fujitsu Electronics Information Technology Co., Ltd" }, - { 0x298A, "Singeen Electronics Technologies (Dongguan) Co., Ltd." }, - { 0x298B, "Hanil ProTech" }, - { 0x298C, "GL Solutions Inc." }, - { 0x298D, "NEXT Biometrics" }, - { 0x298E, "Delta Controls" }, - { 0x298F, "NIHON DENON CO., LTD." }, - { 0x2990, "SHIGA MEC Company Limited" }, - { 0x2991, "Orbitsound Ltd" }, - { 0x2992, "Lantos Technologies, Inc." }, - { 0x2993, "ADPlaus Technology Limited" }, - { 0x2995, "Resodyn Corporation" }, - { 0x2996, "Delphi Data Connectivity" }, - { 0x2997, "Inogeni Inc." }, - { 0x2998, "EOS S.r.l." }, - { 0x2999, "Fourtec Technologies Ltd." }, - { 0x299A, "Ogi Systems Ltd. by A.A. Lab Systems" }, - { 0x299B, "Ohio Semitronics, Inc." }, - { 0x299C, "WINTOUCH Co., Ltd." }, - { 0x299D, "Horst Platz Beratungs und Vertriebs GmbH" }, - { 0x299E, "TRE INNOVATORER AB" }, - { 0x299F, "MESTEC Technologies" }, - { 0x29A0, "Bang & Olufsen Medicom A/S" }, - { 0x29A1, "Union Electric Plug & Connector Corp." }, - { 0x29A2, "MUTEC GmbH" }, - { 0x29A3, "Cista System Corporation" }, - { 0x29A4, "Source Audio LLC" }, - { 0x29A5, "Harbo Entertainment LLC" }, - { 0x29A6, "Chiyoda Electronics Co., Ltd." }, - { 0x29A7, "Tekinvest Holding Ltd." }, - { 0x29A8, "Lester Electrical" }, - { 0x29A9, "Smartisan Technology Co., Ltd." }, - { 0x29AA, "Zivix, LLC" }, - { 0x29AB, "The Eye Tribe" }, - { 0x29AC, "Cool Control (S.D.) Ltd." }, - { 0x29AD, "Quest Engineering & Development, Inc." }, - { 0x29AE, "Japan Lifeline Co., Ltd." }, - { 0x29AF, "Zhongshan K-Mate General Electronics Co., Ltd." }, - { 0x29B0, "Diebold Financial Equipment Co., Ltd." }, - { 0x29B1, "Dongguan Haitai Precision Electronic Technology Co Ltd" }, - { 0x29B2, "Canova Tech" }, - { 0x29B3, "Dowling Software" }, - { 0x29B4, "Shenzhen Carbetter Technology Co., Ltd." }, - { 0x29B5, "PN Devices Int'l Limited" }, - { 0x29B6, "Gowin Technology International Holdings Limited" }, - { 0x29B7, "X.O.Ware, Inc." }, - { 0x29B8, "Hawk-Owl Systems" }, - { 0x29B9, "S.I.C.E.S. S.r.l." }, - { 0x29BA, "TOPTICA Photonics AG" }, - { 0x29BB, "SMUFS Biometric Solutions" }, - { 0x29BC, "IMBEL - Industria de Material Belico do Brasil" }, - { 0x29BD, "Silicon Works" }, - { 0x29BE, "Mamiya-OP NEQUOS Co., Ltd." }, - { 0x29BF, "BalanceMaster, Inc." }, - { 0x29C0, "Canopy Co." }, - { 0x29C1, "TazTag" }, - { 0x29C2, "Lewitt GmbH" }, - { 0x29C3, "Noviga" }, - { 0x29C4, "SoundHawk Corporation" }, - { 0x29C5, "Peachtree Audio" }, - { 0x29C6, "Shenzhen Jiali Asia Industry Co., Ltd." }, - { 0x29C7, "HANRICO ANFU ELECTRONICS CO., LTD." }, - { 0x29C8, "Samil CTS Co., Ltd." }, - { 0x29C9, "BEEVC-Electronic Systems, LDA" }, - { 0x29CA, "Cross the Road Electronics, LLC" }, - { 0x29CB, "Xima Software" }, - { 0x29CC, "Kodak Alaris" }, - { 0x29CD, "Carotron, Inc." }, - { 0x29CE, "JGR Optics Inc." }, - { 0x29CF, "Richtek Technology Corporation" }, - { 0x29D0, "ShenZhen Synergy Digital Co., Ltd." }, - { 0x29D1, "Binatone Electronics Int. Ltd." }, - { 0x29D2, "Crypto Control Limited" }, - { 0x29D3, "HESS Cash Systems GmbH & Co. KG" }, - { 0x29D4, "Twin Development S.A." }, - { 0x29D5, "Alibaba Cloud Computing Ltd." }, - { 0x29D6, "Ara Hub Design Inc." }, - { 0x29D7, "Suritel" }, - { 0x29D8, "Vigor Electric Corporation" }, - { 0x29D9, "San-Eisha, Ltd." }, - { 0x29DA, "The Modal Shop" }, - { 0x29DB, "Shenzhen iBoard Technology Co., Ltd." }, - { 0x29DC, "TOHO Electronics Inc." }, - { 0x29DD, "Embedded Micro" }, - { 0x29DE, "Korea Electric Terminal Co., Ltd." }, - { 0x29DF, "SMIT(HK) Limited" }, - { 0x29E0, "ARCCRA Technology Co., Ltd." }, - { 0x29E1, "TOSEI ENGINEERING CORP." }, - { 0x29E2, "Huatune Technology (Shanghai) Co., Ltd." }, - { 0x29E3, "Bio-Medical Research" }, - { 0x29E4, "Prestigio Plaza Ltd." }, - { 0x29E5, "Dongguan Kechenda Electronic Technology Co., Ltd." }, - { 0x29E6, "Fengshun Peiying Electro-Acoustic Co., Ltd." }, - { 0x29E7, "Brunel University" }, - { 0x29E8, "4Links Limited" }, - { 0x29E9, "Quanttus, Inc." }, - { 0x29EA, "Kinesis Corporation" }, - { 0x29EB, "Virtuix Inc." }, - { 0x29EC, "R. Stahl" }, - { 0x29ED, "CERA" }, - { 0x29EE, "Pinnacle Response Ltd." }, - { 0x29EF, "GamePop Inc." }, - { 0x29F0, "WirePath Home Systems dba Snap AV" }, - { 0x29F1, "0XF8 Limited" }, - { 0x29F2, "RECO Gesellschaft fur Industriefilterregelung mbH" }, - { 0x29F3, "Resonessence Labs" }, - { 0x29F4, "NeuroSky, Inc." }, - { 0x29F5, "AirNetix, LLC" }, - { 0x29F6, "Evoko Unlimited AB" }, - { 0x29F7, "Matica Technologies AG" }, - { 0x29F8, "MD ELEKTRONIK GmbH" }, - { 0x29F9, "EnerLab, LLC" }, - { 0x29FA, "LogTag Recorders Ltd." }, - { 0x29FB, "JSK Co., Ltd." }, - { 0x29FC, "Namsung Corporation" }, - { 0x29FD, "Bad Elf, LLC" }, - { 0x29FE, "GEO Semiconductor Inc." }, - { 0x29FF, "Thalmic Labs Inc." }, - { 0x2A00, "NTLab" }, - { 0x2A01, "Amuseway Korea Co., Ltd." }, - { 0x2A02, "OJI LTD." }, - { 0x2A03, "dog hunter AG" }, - { 0x2A04, "Microtech Laboratory Inc." }, - { 0x2A05, "EXO LABS INC." }, - { 0x2A06, "HiFiMAN Electronics" }, - { 0x2A07, "ise GmbH" }, - { 0x2A08, "Marshall Amplification PLC" }, - { 0x2A09, "cytonome" }, - { 0x2A0A, "All Star International Trading" }, - { 0x2A0B, "Leopard Imaging Inc." }, - { 0x2A0C, "MultiSoft Systems Ltd." }, - { 0x2A0D, "ADVANCE Co., Ltd." }, - { 0x2A0E, "Shenzhen DreamSource Technology Co., Ltd." }, - { 0x2A0F, "Shenzhen Giec Electronics Co., Ltd." }, - { 0x2A10, "Powerway Electronics Co., Ltd." }, - { 0x2A11, "P3 Ingenieurgesellschaft mbH" }, - { 0x2A12, "Vreo Limited" }, - { 0x2A13, "Grabba International" }, - { 0x2A14, "Kanex" }, - { 0x2A15, "navAero AB" }, - { 0x2A16, "Hella Gutmann Solutions" }, - { 0x2A17, "UDEA Electronic Ltd." }, - { 0x2A18, "King Abdulaziz City for Science and Technology" }, - { 0x2A19, "Numato Systems Pvt. Ltd." }, - { 0x2A1A, "ASCOT GmbH" }, - { 0x2A1B, "DRS Power & Control Technologies, Inc." }, - { 0x2A1C, "ThinkWrite" }, - { 0x2A1D, "Oxford Nanopore Technologies" }, - { 0x2A1E, "Obsidian Technology" }, - { 0x2A1F, "Lucent Trans Electronics Co., Ltd." }, - { 0x2A20, "GUOGUANG GROUP CO., LTD." }, - { 0x2A21, "ROL Ergo AB" }, - { 0x2A22, "CDEX CORP." }, - { 0x2A23, "Artec Design" }, - { 0x2A24, "CNPLUS" }, - { 0x2A25, "Fourstar Group" }, - { 0x2A26, "Tragant International Co., Ltd." }, - { 0x2A27, "DongGuan LianGang Optoelectronic Technology Co., Ltd." }, - { 0x2A28, "Higbie, LLC dba kinetuex" }, - { 0x2A29, "PayPal, Inc." }, - { 0x2A2A, "TARGAMITE LLC" }, - { 0x2A2B, "NooElec Inc." }, - { 0x2A2C, "Bkav Corporation" }, - { 0x2A2D, "Atrust Computer Corp." }, - { 0x2A2E, "VIA Alliance Semiconductor Co., Ltd." }, - { 0x2A2F, "BSUN Electronics Co., Ltd." }, - { 0x2A30, "KORR Medical Technologies" }, - { 0x2A31, "Sandia National Laboratories" }, - { 0x2A32, "Centre for Advanced Transport Engineering and Research" }, - { 0x2A33, "NTT R&D Laboratories" }, - { 0x2A34, "KT System, Inc." }, - { 0x2A35, "Quatius Limited" }, - { 0x2A36, "MOS Co., Ltd." }, - { 0x2A37, "RTD Embedded Technologies, Inc." }, - { 0x2A38, "Electronic Design Inc." }, - { 0x2A39, "RME GmbH" }, - { 0x2A3A, "K'NEX Limited Partnership Group" }, - { 0x2A3B, "Eschenbach Optik GmbH" }, - { 0x2A3C, "TRINAMIC Motion Control GmbH & Co. KG" }, - { 0x2A3D, "FIME" }, - { 0x2A3E, "Atlas Copco" }, - { 0x2A3F, "Yasunaga Corporation" }, - { 0x2A40, "Shenzhen Choseal Industrial Co., Ltd." }, - { 0x2A41, "Canyon Semiconductor" }, - { 0x2A42, "Spectra7 Microsystems Corp." }, - { 0x2A43, "Ekosur S.A." }, - { 0x2A44, "FUEL3D Technologies Limited" }, - { 0x2A45, "Meizu Technology Co., Ltd." }, - { 0x2A46, "Hubei Yingtong Telecommunication Cable Inc." }, - { 0x2A47, "Mundo Reader SL" }, - { 0x2A48, "Pointmobile" }, - { 0x2A49, "UNOWHY" }, - { 0x2A4A, "threeRivers 3D, Inc." }, - { 0x2A4B, "EMULEX Corporation" }, - { 0x2A4C, "Tianjin SharpNow Technology Co., Ltd." }, - { 0x2A4D, "Wilder Technologies" }, - { 0x2A4E, "Henge Docks, LLC" }, - { 0x2A4F, "L-3 Communications Avionics Systems" }, - { 0x2A50, "Akizuki Denshi Tsusho Co., Ltd." }, - { 0x2A51, "Multiclet Corp." }, - { 0x2A52, "L CARD Ltd." }, - { 0x2A53, "x-odos GmbH" }, - { 0x2A54, "Black Diamond Advanced Technology, LLC" }, - { 0x2A56, "eemagine Medical Imaging Solutions GmbH" }, - { 0x2A57, "Bellingham + Stanley Limited" }, - { 0x2A58, "ALIGN Corporation Limited" }, - { 0x2A59, "The Whistler Group" }, - { 0x2A5A, "Kromek Group Plc." }, - { 0x2A5B, "Integrity Applications Ltd." }, - { 0x2A5C, "Dalian Zonewin Electronics Co., Ltd." }, - { 0x2A5D, "Zhejiang Wanli Jo Ju Automation Technonolgy Co., Ltd." }, - { 0x2A5E, "The Chemours Company" }, - { 0x2A5F, "Tencent Technology (Shenzhen) Company Limited" }, - { 0x2A60, "Oscadi SAS" }, - { 0x2A61, "Ellex Medical Pty Ltd." }, - { 0x2A62, "Flymaster Avionics, LDA" }, - { 0x2A63, "Postek Electronics Co., Ltd." }, - { 0x2A64, "Zhejiang Songcheng Electronics Co., Ltd." }, - { 0x2A65, "FreeWave Technologies, Inc." }, - { 0x2A66, "JoyLabz LLC" }, - { 0x2A67, "Chart Industries" }, - { 0x2A68, "CheckSum, LLC" }, - { 0x2A69, "EDIC Systems Inc." }, - { 0x2A6A, "PINTSCH TIEFENBACH GmbH" }, - { 0x2A6B, "VSN Mobil" }, - { 0x2A6C, "Silego Technology" }, - { 0x2A6D, "SAsync, LLC" }, - { 0x2A6E, "Bare Conductive Ltd." }, - { 0x2A6F, "Shenzhen Justtide Tech Co., Ltd." }, - { 0x2A70, "Shenzhen Oneplus Science and Technology Co., Inc." }, - { 0x2A71, "Eyelock, Inc." }, - { 0x2A72, "Omega Engineering" }, - { 0x2A73, "IMAC Co., Ltd." }, - { 0x2A74, "Innoflight Tech., Ltd." }, - { 0x2A75, "Delta Dansk Elektronik, Lys & Akustik" }, - { 0x2A76, "Microsemi Corporation (Phoenix)" }, - { 0x2A77, "American Printing House for the Blind" }, - { 0x2A78, "mySkin, Inc." }, - { 0x2A79, "S.E. Technologies Limited" }, - { 0x2A7A, "Beijing Casue Technology Co., Ltd." }, - { 0x2A7B, "Bellwether Electronic Corp." }, - { 0x2A7C, "Acute Technology Inc." }, - { 0x2A7D, "ParTech, Inc." }, - { 0x2A7E, "VAIO Corporation" }, - { 0x2A7F, "Perixx Computer GmbH" }, - { 0x2A80, "Smart Start Inc." }, - { 0x2A81, "Hale Products, Inc." }, - { 0x2A82, "Printek, Inc." }, - { 0x2A83, "Autodesk Inc." }, - { 0x2A84, "ATE Systems" }, - { 0x2A85, "HANK ELECTRONICS CO., LTD" }, - { 0x2A86, "KITRIS AG" }, - { 0x2A87, "Kummler + Matter AG" }, - { 0x2A88, "DFU Technology Ltd." }, - { 0x2A89, "Robert Bosch Tool Corporation" }, - { 0x2A8A, "Benchmark Drives GmbH & Co. KG" }, - { 0x2A8B, "I.C. Lercher GmbH & Co. KG" }, - { 0x2A8C, "Sonnet Technologies, Inc." }, - { 0x2A8D, "Keysight Technologies Inc." }, - { 0x2A8E, "Starlink Electronics Corp." }, - { 0x2A8F, "Manutronics Vietnam Joint Stock Company" }, - { 0x2A90, "NowComputing, LLC" }, - { 0x2A91, "Seed Industrial Designing Co., Ltd." }, - { 0x2A92, "Woosim Systems Inc." }, - { 0x2A93, "Enblink Co., Ltd." }, - { 0x2A94, "G2 Touch Co., Ltd." }, - { 0x2A95, "Flipkart Internet Pvt. Ltd." }, - { 0x2A96, "Micromax Informatics Ltd" }, - { 0x2A97, "Broadway Semiconductor, Inc." }, - { 0x2A98, "Calix" }, - { 0x2A99, "Humanistic Robotics, Inc." }, - { 0x2A9A, "SRAM, LLC" }, - { 0x2A9B, "Doblet Inc." }, - { 0x2A9C, "Olorin AB" }, - { 0x2A9D, "LawMate International Co., Ltd." }, - { 0x2A9E, "SEIKO SOLUTIONS Inc." }, - { 0x2A9F, "Mobelisk LLC" }, - { 0x2AA0, "Casco Products Corp." }, - { 0x2AA1, "Ivanhoe (DE), Inc." }, - { 0x2AA2, "GTI Spindle Technology, Inc." }, - { 0x2AA3, "Strike Technologies a Division of Penbro Kelnick (Pty) Ltd" }, - { 0x2AA4, "Voim Technologies Inc." }, - { 0x2AA5, "Pen Generations, Inc." }, - { 0x2AA6, "ChengFong International Limited" }, - { 0x2AA7, "MJC Techno Co., Ltd." }, - { 0x2AA8, "Resus Industries NV" }, - { 0x2AA9, "Infrared Cameras Inc." }, - { 0x2AAA, "Virtium Technology, Inc." }, - { 0x2AAB, "Field and Company LLC, dba Leef USA" }, - { 0x2AAC, "Elinchrom S.A." }, - { 0x2AAD, "iCatch Technology, Inc." }, - { 0x2AAE, "Chipone Technology (Beijing) Co., Ltd." }, - { 0x2AAF, "Xiamen Hanin Electronic Technology Co., Ltd." }, - { 0x2AB0, "GM Global Technology Operations LLC" }, - { 0x2AB1, "Tesco Stores Ltd." }, - { 0x2AB2, "Maktar, Inc." }, - { 0x2AB3, "Key Asic Inc." }, - { 0x2AB4, "Line Seiki Co., Ltd." }, - { 0x2AB5, "Micro-Technica Co., Ltd." }, - { 0x2AB6, "T+A Elektroakustik GmbH + Co. KG" }, - { 0x2AB7, "foc.us" }, - { 0x2AB8, "Meggitt (Orange County), Inc." }, - { 0x2AB9, "Monsoon Solutions, Inc." }, - { 0x2ABA, "MagneMotion Inc." }, - { 0x2ABB, "HiDeep Inc." }, - { 0x2ABC, "Beijing Kingrich Medical Technology Co., Ltd." }, - { 0x2ABD, "Meeteasy Technology Limited" }, - { 0x2ABE, "Bluink Ltd" }, - { 0x2ABF, "Revolabs, Inc." }, - { 0x2AC0, "POWA Technologies Ltd." }, - { 0x2AC1, "Lattice Semiconductor Corp" }, - { 0x2AC2, "Toreck Co., Ltd." }, - { 0x2AC3, "Foshan Nanhai Saga Audio Equipment Co., Ltd." }, - { 0x2AC4, "BlackBox Biometrics, Inc." }, - { 0x2AC5, "PhotoFast Co., Ltd." }, - { 0x2AC6, "HAKKO Corporation" }, - { 0x2AC7, "Ultrahaptics Limited" }, - { 0x2AC8, "SimonsVoss Technologies GmbH" }, - { 0x2AC9, "TELPA Telekomunikasyon Tic. A.S. Brand: General Mobile" }, - { 0x2ACA, "Toledo do Brasil Industria de Balancas Ltda." }, - { 0x2ACB, "Pole/Zero Acquisition, Inc." }, - { 0x2ACC, "illunis LLC" }, - { 0x2ACD, "Silergy Corp." }, - { 0x2ACE, "Tonetron Electronic Ltd." }, - { 0x2ACF, "Ruffy Controls Inc." }, - { 0x2AD0, "Holley Performance Products (CANADA) Inc." }, - { 0x2AD1, "Pictronic GmbH" }, - { 0x2AD2, "Allnic Audio" }, - { 0x2AD3, "Shenzhen Hali-Power Industrial Co., Ltd." }, - { 0x2AD4, "L&F Corporation" }, - { 0x2AD5, "Baikal Electronics JSC" }, - { 0x2AD6, "Cozumo, Inc." }, - { 0x2AD7, "RHENAC Systems GmbH" }, - { 0x2AD8, "i2s" }, - { 0x2AD9, "Zound Industries International AB" }, - { 0x2ADA, "McCarthy Music Corp." }, - { 0x2ADB, "I-PEX (Dai-ichi Seiko)" }, - { 0x2ADC, "Absolute USA" }, - { 0x2ADD, "SEE-PLUS INDUSTRIAL LTD." }, - { 0x2ADE, "Orga BV" }, - { 0x2ADF, "Noiseless Security A/S" }, - { 0x2AE0, "Auma Riester GmbH & Co. KG" }, - { 0x2AE1, "EDEC PROGRESS CO., LTD." }, - { 0x2AE2, "VXi Corporation" }, - { 0x2AE3, "Jiuzhou Digital (Hong Kong) Limited" }, - { 0x2AE4, "Next! s.c. Slawomir Piela, Bartlomiej Dryja" }, - { 0x2AE5, "Fairphone B.V." }, - { 0x2AE6, "e-distribuzione Spa" }, - { 0x2AE7, "Advanced Media, Inc." }, - { 0x2AE8, "Quintic Microelectronics (Wuxi) Co., Ltd." }, - { 0x2AE9, "Regal Beloit Canada ULC. dba Thomson Power Systems" }, - { 0x2AEA, "Protonex Technology Corporation" }, - { 0x2AEB, "NovaTech, LLC" }, - { 0x2AEC, "Ambiq Micro, Inc." }, - { 0x2AED, "Technology Launch, LLC" }, - { 0x2AEE, "Adapt-IP Company" }, - { 0x2AEF, "Coronado Electronics, Inc." }, - { 0x2AF0, "Zhejiang Yuesui Electron Stock Co., Ltd." }, - { 0x2AF1, "Innovation Spring Tech, Inc." }, - { 0x2AF2, "CIS Corporation" }, - { 0x2AF3, "Rehan Electronics Ltd." }, - { 0x2AF4, "ROLI Ltd." }, - { 0x2AF5, "Libratone A/S" }, - { 0x2AF6, "Nix Sensor Ltd." }, - { 0x2AF7, "Shenzhen Hazens Automotive Electronics (SZ) Co., Ltd." }, - { 0x2AF8, "Jiangsu Toppower Automotive Electronics Co., Ltd." }, - { 0x2AF9, "Drapho Electronics Technology Co., Ltd." }, - { 0x2AFA, "Yokogawa Digital Computer Corporation" }, - { 0x2AFB, "EMC, Electronic Music Components" }, - { 0x2AFC, "Savox Communications OY AB" }, - { 0x2AFD, "McIntosh Laboratory, Inc." }, - { 0x2AFE, "IntriCon" }, - { 0x2AFF, "ARP Corporation" }, - { 0x2B00, "Novitec Co., Ltd." }, - { 0x2B01, "Zimi Corporation" }, - { 0x2B02, "AMGOO Telecom Co., Ltd." }, - { 0x2B03, "STEREOLABS" }, - { 0x2B04, "Spark Labs, Inc." }, - { 0x2B05, "Warn Industries" }, - { 0x2B06, "TEControl" }, - { 0x2B07, "ESA Elektroschaltanlagen Grimma GmbH" }, - { 0x2B08, "KYOEI ENGINEERING Co., Ltd." }, - { 0x2B09, "Shenzhen Lidacheng Technology Co., Ltd." }, - { 0x2B0A, "AMICCOM Electronics Corporation" }, - { 0x2B0B, "Qtul Enterprises" }, - { 0x2B0C, "Goclever Sp z o.o." }, - { 0x2B0D, "Dongguan Yulian Electronic Industrial Co., Ltd." }, - { 0x2B0E, "Le Shi Zhi Xin Electronic Technology (Tian Jin) Limited" }, - { 0x2B0F, "Best Integration Technology Co., Ltd." }, - { 0x2B10, "Cardiac Insight, Inc." }, - { 0x2B11, "Europe Net Srl" }, - { 0x2B12, "DeepSpar" }, - { 0x2B13, "Lightcomm Technology Co., Ltd." }, - { 0x2B14, "EverPro Technologies Company, Ltd." }, - { 0x2B15, "Rosenberger Hochfrequenztechnik" }, - { 0x2B16, "Spirometrix, Inc." }, - { 0x2B17, "Jaguar Land Rover" }, - { 0x2B18, "ProSign GmbH" }, - { 0x2B19, "JBSignal Co." }, - { 0x2B1A, "Fortune Ship Technology (HK) Limited" }, - { 0x2B1B, "Dongguan City Sanji Electronics Co., Ltd." }, - { 0x2B1C, "Shenzhen Virtual Reality Technology Company Limited" }, - { 0x2B1D, "Lintes Technology Co., Ltd." }, - { 0x2B1E, "NFUZD Technology Inc" }, - { 0x2B1F, "KinnexA, Inc." }, - { 0x2B20, "WaveLynx Technologies Corporation" }, - { 0x2B21, "Project Florida" }, - { 0x2B22, "Metra Electronics Corp." }, - { 0x2B23, "Red Hat, Inc." }, - { 0x2B24, "KeepKey, LLC" }, - { 0x2B25, "Logos Biosystems, Inc." }, - { 0x2B26, "Oltrade LLC" }, - { 0x2B27, "FluxData Incorporated" }, - { 0x2B28, "Enovation Controls, LLC" }, - { 0x2B29, "Lezyne" }, - { 0x2B2A, "BDX" }, - { 0x2B2B, "BITwave PTE LTD." }, - { 0x2B2C, "S1nn GmbH & Co. KG" }, - { 0x2B2D, "AEG Power Solutions GmbH" }, - { 0x2B2E, "pei tel Communications GmbH" }, - { 0x2B2F, "UL TS B.V." }, - { 0x2B30, "Neratec Solutions AG" }, - { 0x2B31, "JVIS USA, LLC" }, - { 0x2B32, "NVS Technologies AG" }, - { 0x2B33, "Commend International GmbH" }, - { 0x2B34, "Seemahale Telecoms" }, - { 0x2B35, "Assem Technology Co., Ltd." }, - { 0x2B36, "Dongguan City Jianghan Electronics Co., Ltd." }, - { 0x2B37, "Huizhou Desay SV Automotive Co., Ltd." }, - { 0x2B38, "Ningbo Rixing Electronics Co., Ltd." }, - { 0x2B39, "KANAI ELECTRONIC APPLIANCE Co., Ltd." }, - { 0x2B3A, "Cirrus Research plc" }, - { 0x2B3B, "ScriptPro, LLC" }, - { 0x2B3C, "Technikos Sports Inc." }, - { 0x2B3D, "GuangDong YuanFeng Automotive Electroics Co., Ltd." }, - { 0x2B3E, "NewAE Technology Inc." }, - { 0x2B3F, "ATL-SD Co., Ltd." }, - { 0x2B40, "Matsumura Engineering Co., Ltd." }, - { 0x2B41, "Image Match Design Inc." }, - { 0x2B42, "NEXO S.A." }, - { 0x2B43, "Doro AB" }, - { 0x2B44, "Wildfire, Inc." }, - { 0x2B45, "PRA Audio Systems, Inc." }, - { 0x2B46, "Centerm Information Co., Ltd." }, - { 0x2B47, "Huizhou Aorora Science & Technology Co., Ltd." }, - { 0x2B48, "Sounding Audio Industrial Limited" }, - { 0x2B49, "GECO Incorporated" }, - { 0x2B4A, "Yueqing Huaxin Electronic Co., Ltd." }, - { 0x2B4B, "China Hualu Group Co., Ltd." }, - { 0x2B4C, "Beijing SHENQI Technology Co., Ltd." }, - { 0x2B4D, "SMC Corporation" }, - { 0x2B4E, "Microcabin Inc." }, - { 0x2B4F, "Aeroscout Ltd. (Stanley Healthcare)" }, - { 0x2B50, "Denchi Power Ltd." }, - { 0x2B51, "Pax Instruments" }, - { 0x2B52, "Dongguan Evermax Electronics Technology Co., Ltd." }, - { 0x2B53, "Shenzhen Supernature Multimedia Co., Ltd." }, - { 0x2B54, "AMPAK Technology Inc." }, - { 0x2B55, "FUJIFILM Imaging Systems Co., Ltd." }, - { 0x2B56, "The Crypto Group" }, - { 0x2B57, "GIROPTIC" }, - { 0x2B58, "DJ Sound Electronics, LLC / BiZi Inc." }, - { 0x2B59, "ESI Motion" }, - { 0x2B5A, "Universal Audio, Inc." }, - { 0x2B5B, "Xiamen Home Meitu Technology Co., Ltd." }, - { 0x2B5C, "B&B Exporting Limited" }, - { 0x2B5D, "GSL Solutions, Inc." }, - { 0x2B5E, "Audio Alchemy" }, - { 0x2B5F, "b-plus GmbH" }, - { 0x2B60, "Viking Technology" }, - { 0x2B61, "Universal Biosensors, Inc." }, - { 0x2B62, "ICP Entwicklungs GmbH" }, - { 0x2B63, "Inora Technologies, Inc." }, - { 0x2B64, "Cyanogen Inc." }, - { 0x2B65, "Atelier Vision Corporation" }, - { 0x2B66, "Clinton Instrument Company" }, - { 0x2B67, "Lifesize, Inc." }, - { 0x2B68, "FLEXIM - Flexible Industriemesstechnik GmbH" }, - { 0x2B69, "Humax Automotive Co., Ltd." }, - { 0x2B6A, "FUJI TECOM INC." }, - { 0x2B6B, "Colorix SA" }, - { 0x2B6C, "Transbit Sp. z o.o." }, - { 0x2B6D, "SATORI ELECTRIC CO., LTD." }, - { 0x2B6E, "Airviz Inc." }, - { 0x2B6F, "Revolution Education Ltd." }, - { 0x2B70, "Micran, Research & Production Company" }, - { 0x2B71, "Zhejiang Flashforge 3D Technology Co., Ltd." }, - { 0x2B72, "RT Corporation" }, - { 0x2B73, "Pioneer DJ Corporation" }, - { 0x2B74, "Embedded Intelligence, Inc." }, - { 0x2B75, "New Matter" }, - { 0x2B76, "Shanghai Wingtech Electronic Technology Co., Ltd." }, - { 0x2B77, "Epiphan Systems Inc." }, - { 0x2B78, "Elyctis" }, - { 0x2B79, "Radio Sound, Inc." }, - { 0x2B7A, "Spin Master Far East Ltd." }, - { 0x2B7B, "Gigaset Digital Technology (Shenzhen) Co., Ltd." }, - { 0x2B7C, "Noveltek Semiconductor Corp." }, - { 0x2B7D, "ZEITEC Semiconductor Co., Ltd." }, - { 0x2B7E, "Shenzhen Kingcome Optoelectronic Co., Ltd." }, - { 0x2B7F, "NanoTS Co., Ltd." }, - { 0x2B80, "Miyuki Giken Co., Ltd." }, - { 0x2B81, "PULAX Corporation" }, - { 0x2B82, "TELE RADIO AB" }, - { 0x2B83, "Silicon Line GmbH" }, - { 0x2B84, "Ever Win International Corp." }, - { 0x2B85, "YICHUN YILIAN PRINT TECH CO., LTD." }, - { 0x2B86, "MITSUBISHI HITACHI POWER SYSTEMS ENGINEERING CO., LTD." }, - { 0x2B87, "ATP Industries Group Ltd." }, - { 0x2B88, "Socionext Inc." }, - { 0x2B89, "Ugreen Group Limited" }, - { 0x2B8A, "Shanghai Pateo Electronic Equipment Mfg. Co., Ltd." }, - { 0x2B8B, "Inner Mongolia Yinan Science & Technology Dev. Co., Ltd" }, - { 0x2B8C, "EDGE I&D" }, - { 0x2B8D, "Dr. Fritz Faulhaber GmbH & Co. KG" }, - { 0x2B8E, "Pentair PLC" }, - { 0x2B8F, "DxO Labs Corp." }, - { 0x2B90, "ACR Braendli & Voegeli AG" }, - { 0x2B91, "The Fredericks Company" }, - { 0x2B92, "i-BLADES, Inc." }, - { 0x2B93, "Altia Systems Inc." }, - { 0x2B94, "ShenZhen Baoyuanda Electronics Co., Ltd." }, - { 0x2B95, "iST - Integrated Service Technology Inc." }, - { 0x2B96, "HYUNDAI MOBIS Co., Ltd." }, - { 0x2B97, "Digen Co., Ltd." }, - { 0x2B98, "Glenair, Inc." }, - { 0x2B99, "360fly, Inc." }, - { 0x2B9A, "HUIZHOU CHENG SHUO HARDWARE PLASTIC CO., LTD." }, - { 0x2B9B, "Zhongshan Aute Electronics Technology Co., Ltd." }, - { 0x2B9C, "Guangdong King Link Industrial Co., Ltd." }, - { 0x2B9D, "HARTING Electric GmbH & Co. KG" }, - { 0x2B9E, "ZPower LLC" }, - { 0x2B9F, "Scietera Technologies, Inc." }, - { 0x2BA0, "InVue Security Products" }, - { 0x2BA1, "I-Sheng Electric Wire & Cable Co., Ltd." }, - { 0x2BA2, "China Daheng Group Inc Beijing Image Vision Tech Branch" }, - { 0x2BA3, "Shenzhen FeiTianXia Technology Ltd." }, - { 0x2BA4, "Shenzhen HengJia New Energy Auto Part Co., Ltd." }, - { 0x2BA5, "Yueguan Network Technology (Shanghai) Co., Ltd." }, - { 0x2BA6, "Cyberith GmbH" }, - { 0x2BA7, "77 Elektronika Kft." }, - { 0x2BA8, "YUDU EASON ELECTRONIC CO., LTD." }, - { 0x2BA9, "YanFeng Visteon Automotive Electronics Co., Ltd." }, - { 0x2BAA, "New World Technologies Inc." }, - { 0x2BAB, "Grandstream Networks, Inc." }, - { 0x2BAC, "Polyera Corporation" }, - { 0x2BAD, "XinJi Technologies Ltd." }, - { 0x2BAE, "Holinail H.K. Limited" }, - { 0x2BAF, "Getac Technology Corp." }, - { 0x2BB0, "ITES Co., Ltd." }, - { 0x2BB1, "Validata LLC" }, - { 0x2BB2, "HIDEX OY" }, - { 0x2BB3, "Elcoa Industria e Comercio Ltda" }, - { 0x2BB4, "PRINK Srl" }, - { 0x2BB5, "Silk ID Systems" }, - { 0x2BB6, "3D Imaging & Simulations Corp. (3DISC)" }, - { 0x2BB7, "Dongguan ChengXiang Industrial Co., Ltd." }, - { 0x2BB8, "OCC (Zhuhai) Electronic Co., Ltd." }, - { 0x2BB9, "ARGUS-SPECTRUM" }, - { 0x2BBA, "Sinseader Electronic Co., Ltd." }, - { 0x2BBB, "DONGGUAN YELLOW KNIFE Industrial Co., Ltd." }, - { 0x2BBC, "Guided Ultrasonics Ltd" }, - { 0x2BBD, "RF Creations Ltd." }, - { 0x2BBE, "Chengyi Semiconductors (Shanghai) Co., Ltd." }, - { 0x2BBF, "Shenzhen Shinning Electronic Co., Ltd." }, - { 0x2BC0, "Shenzhen WFD Electronics Co., Ltd." }, - { 0x2BC1, "Dongguan Sino Syncs Industrial Co., Ltd." }, - { 0x2BC2, "JNTC Co., Ltd." }, - { 0x2BC3, "Nihon Mechatronics Co., Ltd." }, - { 0x2BC4, "SR Research Ltd." }, - { 0x2BC5, "Orbbec 3D Tech. Int'l Inc." }, - { 0x2BC6, "Server Technology, Inc." }, - { 0x2BC7, "Zounds Hearing Inc." }, - { 0x2BC8, "DONGGUAN POLIXIN ELECTRIC CO., LTD." }, - { 0x2BC9, "Tama Electric (Suzhou) Co., Ltd." }, - { 0x2BCA, "Exvision, Inc." }, - { 0x2BCB, "Tanaka Electric Industry Co., Ltd." }, - { 0x2BCC, "InoTec GmbH Organisationssysteme" }, - { 0x2BCD, "Keyprocessor BV" }, - { 0x2BCE, "UV Partners" }, - { 0x2BCF, "Magtrol, Inc." }, - { 0x2BD0, "mophie, LLC" }, - { 0x2BD1, "Spectran LLC" }, - { 0x2BD2, "Nabtesco Corporation" }, - { 0x2BD3, "Dongguan ULT-unite electronic technology co., LTD" }, - { 0x2BD4, "JL Audio, Inc." }, - { 0x2BD5, "Cable Matters Inc." }, - { 0x2BD6, "CoroWare, Inc." }, - { 0x2BD7, "EcuTek International Ltd." }, - { 0x2BD8, "ROPEX Industrie-Elektronik GmbH" }, - { 0x2BD9, "Huddly" }, - { 0x2BDA, "Panono GmbH" }, - { 0x2BDB, "LOVEOX CO., LTD." }, - { 0x2BDC, "Automation Electronics Inc." }, - { 0x2BDD, "Charm Sciences Inc." }, - { 0x2BDE, "Pickering Interfaces Limited" }, - { 0x2BDF, "Hangzhou Hikvision Digital Technology Co., Ltd." }, - { 0x2BE0, "Fullink Technology Co., Ltd" }, - { 0x2BE1, "AutoChips Inc." }, - { 0x2BE2, "Electric Connector Technology Co., Ltd." }, - { 0x2BE3, "Hydac Electronic GmbH" }, - { 0x2BE4, "Cojali S.L. ES-B13210489" }, - { 0x2BE5, "LELTEK" }, - { 0x2BE6, "Dongguan KaiWin Electronics Co., Ltd." }, - { 0x2BE7, "BEFS Co., Ltd." }, - { 0x2BE8, "Archisite, Inc." }, - { 0x2BE9, "Magneti Marelli S.p.A Electr BL" }, - { 0x2BEA, "Inspire Medical Systems" }, - { 0x2BEB, "Gateworks Corporation" }, - { 0x2BEC, "Lumantek Co., Ltd." }, - { 0x2BED, "Econoburn LLC" }, - { 0x2BEE, "Ventev Mobile" }, - { 0x2BEF, "Quanta Storage Inc." }, - { 0x2BF0, "Tech-Top Technology Limited" }, - { 0x2BF1, "Murakami Color Research Laboratory" }, - { 0x2BF2, "ABB India Limited" }, - { 0x2BF3, "Photek Ltd." }, - { 0x2BF4, "Thunderbird International DBA Spectec" }, - { 0x2BF5, "Shenzhen YOOBAO Technology Co., Ltd." }, - { 0x2BF6, "Shenzhen Sinotek Technology Co., Ltd." }, - { 0x2BF7, "KEYW" }, - { 0x2BF8, "Visual Land Inc." }, - { 0x2BF9, "Poynt Co." }, - { 0x2BFA, "High Country Tek" }, - { 0x2BFB, "Strattec Advanced Logic, LLC" }, - { 0x2BFC, "Sulon Technologies Inc." }, - { 0x2BFD, "Kinematics GmbH" }, - { 0x2BFE, "Novexx Solutions GmbH" }, - { 0x2BFF, "Shindengen Electric Mfg. Co., Ltd." }, - { 0x2C00, "MEEM SL Ltd" }, - { 0x2C01, "Dongguan Arin Electronics Technology Co., Ltd." }, - { 0x2C02, "DongGuan City JianNuo Electronics Co., Ltd." }, - { 0x2C03, "Barrett Communications Pty. Ltd." }, - { 0x2C04, "Shenzhen XOX Electronics Co., Ltd." }, - { 0x2C05, "Protop International Inc." }, - { 0x2C06, "Microsemi Semiconductor (US) Inc." }, - { 0x2C07, "Webcloak LLC" }, - { 0x2C08, "INVECAS INC." }, - { 0x2C09, "Prediktor Medical AS" }, - { 0x2C0A, "ATANS Technology Inc." }, - { 0x2C0B, "Triple Win Precision Technology Co., Ltd." }, - { 0x2C0C, "IC Realtech" }, - { 0x2C0D, "Embrava Pty Ltd" }, - { 0x2C0E, "Unity Scientific" }, - { 0x2C0F, "Mantra Softech (India) Pvt Ltd" }, - { 0x2C10, "Sinotronics Co., Ltd." }, - { 0x2C11, "ALLBEST ELECTRONICS TECHNOLOGY CO., LTD." }, - { 0x2C12, "Shenzhen Xin Kai Feng Electronics Factory" }, - { 0x2C13, "MOST WELL Technology Corp." }, - { 0x2C14, "Buffalo Memory Co., Ltd." }, - { 0x2C15, "Xentris Wireless" }, - { 0x2C16, "Priferential Accessories Ltd" }, - { 0x2C17, "SVS-VISTEK GmbH" }, - { 0x2C18, "Euclideon Pty. Ltd." }, - { 0x2C19, "Sunlike Technology Co., Ltd." }, - { 0x2C1A, "Young Fast Optoelectronics Co., Ltd." }, - { 0x2C1B, "ISAW Camera Inc" }, - { 0x2C1C, "Daesung Eltec., Ltd" }, - { 0x2C1D, "Makita Corporation" }, - { 0x2C1E, "Global Fire Equipment S.A." }, - { 0x2C1F, "Cashmaster International Limited" }, - { 0x2C20, "Pulsar Instruments Plc." }, - { 0x2C21, "Prynt Corp." }, - { 0x2C22, "Qanba USA, LLC" }, - { 0x2C23, "Super Micro Computer Inc." }, - { 0x2C24, "SONOTEC Ultraschallsensorik Halle GmbH" }, - { 0x2C25, "Shanghai TAIDU INTELLIGENT TECHNOLOGY CO., LTD." }, - { 0x2C26, "Micromax International Corporation" }, - { 0x2C27, "YAWATA Electric Industrial Co., Ltd." }, - { 0x2C28, "Granite River Labs Japan Ltd." }, - { 0x2C29, "Coagent Enterprise Limited" }, - { 0x2C2A, "LEIA Inc." }, - { 0x2C2B, "NetScout Systems, Inc." }, - { 0x2C2C, "Fortify Technologies, LLC" }, - { 0x2C2D, "Shenzhen Ebull Technology Limited" }, - { 0x2C2E, "Hualun Technology Co., Ltd." }, - { 0x2C2F, "Sensel, Inc." }, - { 0x2C30, "Ariadne's Thread (USA), Inc. dba Immerex" }, - { 0x2C31, "tinnos" }, - { 0x2C32, "MCS Micronic Computer Systeme GmbH" }, - { 0x2C33, "Shinobiya.com Co., Ltd." }, - { 0x2C34, "Xerox Business Services (Switzerland) AG" }, - { 0x2C35, "Decto, Inc." }, - { 0x2C36, "Bonsai Lab, Inc." }, - { 0x2C37, "Shenzhen Adition Audio Science & Technology Co., Ltd." }, - { 0x2C38, "Goldenconn Electronics Technology (Suzhou) Co., Ltd." }, - { 0x2C39, "JIB Electronics Technology Co., Ltd." }, - { 0x2C3A, "Changzhou Shinco Automotive Electronics Co., Ltd." }, - { 0x2C3B, "Shenzhen Hangsheng Electronics Corp., Ltd." }, - { 0x2C3C, "Beartooth Radio, Inc." }, - { 0x2C3D, "Audience, A Knowles Company" }, - { 0x2C3E, "Verizon Telematics, Inc." }, - { 0x2C3F, "Nextbit Systems, Inc." }, - { 0x2C40, "Leadtrend" }, - { 0x2C41, "Adaptertek Technology Co., Ltd." }, - { 0x2C42, "Feature Integration Technology Inc." }, - { 0x2C43, "Avegant Corporation" }, - { 0x2C44, "Digital Design Corporation" }, - { 0x2C45, "Reid Heath Ltd." }, - { 0x2C46, "Soehnle Industrial Solutions GmbH" }, - { 0x2C47, "Chunghsin International Electronics Co., Ltd." }, - { 0x2C48, "Delphi Electrical Centers (Shanghai) Co., Ltd." }, - { 0x2C49, "Chikuma Seiki Co., Ltd." }, - { 0x2C4A, "System Industrie Electronic GmbH" }, - { 0x2C4B, "Huntleigh Healthcare Ltd." }, - { 0x2C4C, "Double Robotics, Inc." }, - { 0x2C4D, "VVETEK DOO" }, - { 0x2C4E, "Mercusys Technologies Co., Limited" }, - { 0x2C4F, "Canon Electronic Business Machines (H.K.) Co., Ltd." }, - { 0x2C50, "Vinghog AS" }, - { 0x2C51, "Lambda Acoustic" }, - { 0x2C52, "Comio Communication Co., Ltd." }, - { 0x2C53, "Huizhou Foryou General Electronics Co., Ltd." }, - { 0x2C54, "LifeWatch Technologies Ltd." }, - { 0x2C55, "Magicleap" }, - { 0x2C56, "Pocket Radar Inc." }, - { 0x2C57, "BMT Messtechnik GmbH" }, - { 0x2C58, "Dyden Corporation" }, - { 0x2C59, "EBARA CORPORATION" }, - { 0x2C5A, "Mobilus Automotive Inc" }, - { 0x2C5B, "Shenglan Technology Co. Ltd" }, - { 0x2C5C, "Neusoft Corporation" }, - { 0x2C5D, "SIP Simya Electronics Technology Co., Ltd." }, - { 0x2C5E, "ELVES Automotive Co., Ltd" }, - { 0x2C5F, "YOODS Co., Ltd." }, - { 0x2C60, "Sirin LABS AG" }, - { 0x2C61, "Jadmam Corporation dba: Boytone" }, - { 0x2C62, "Trice Medical" }, - { 0x2C63, "Electronica Steren, S.A. de C.V." }, - { 0x2C64, "Creaform Inc. (Ametek Ultra Precision Technologies)" }, - { 0x2C65, "Nokia Technologies" }, - { 0x2C66, "EMOTIQ srl" }, - { 0x2C67, "VentureCraft, Ltd." }, - { 0x2C68, "EMRight Technology Co., Ltd." }, - { 0x2C69, "BBPOS Limited" }, - { 0x2C6A, "Joint Stock Company Research Centre Module" }, - { 0x2C6B, "System JD Co., Ltd" }, - { 0x2C6C, "Nano TouchSystems co., Ltd." }, - { 0x2C6D, "Gibson Innovations" }, - { 0x2C6E, "Shen Zhen Xian Shuo Technology Co. Ltd." }, - { 0x2C6F, "PST Eletronica LTDA" }, - { 0x2C70, "PERI, Inc." }, - { 0x2C71, "Bozhou BoTong Information Technology Co., Ltd." }, - { 0x2C72, "BlueberryE GmbH" }, - { 0x2C73, "Qiku Internet Network Scientific (Shenzhen) Co., Ltd." }, - { 0x2C74, "CJSC Nordavind" }, - { 0x2C75, "Net And Print Inc." }, - { 0x2C76, "DATAPATH LTD" }, - { 0x2C77, "Profindustry GmbH" }, - { 0x2C78, "BRAGI GmbH" }, - { 0x2C79, "WAWGD, Inc. (DBA: Foresight Sports)" }, - { 0x2C7A, "AutoNavi Software Co., Ltd." }, - { 0x2C7B, "Beijing ASU Tech Co., Ltd." }, - { 0x2C7C, "Anysmart Technologies Co., Ltd." }, - { 0x2C7D, "Shenzhen Protruly Electronic Co., Ltd." }, - { 0x2C7E, "Dongguan Allpass Electronic Co., Ltd." }, - { 0x2C7F, "SHENZHEN D-VITEC INDUSTRIAL CO., LTD." }, - { 0x2C80, "motomobile AG" }, - { 0x2C81, "Indie Semiconductor" }, - { 0x2C82, "Cloud9 Technologies LLC" }, - { 0x2C83, "LRP electronic GmbH" }, - { 0x2C84, "Innodezign MauRitius Limited" }, - { 0x2C85, "Audientes" }, - { 0x2C86, "Ultraflux" }, - { 0x2C87, "ISKN" }, - { 0x2C88, "K-Tronic SRL" }, - { 0x2C89, "Younes Medical Technologies" }, - { 0x2C8A, "Advanced Casino Electronics" }, - { 0x2C8B, "Huizhou Dehong Technology Co., Ltd." }, - { 0x2C8C, "PowerCenter Technology Limited" }, - { 0x2C8D, "Mizco International, Inc." }, - { 0x2C8E, "Unique Secure Limited" }, - { 0x2C8F, "Regulus Company Ltd." }, - { 0x2C90, "I. AM. PLUS, LLC" }, - { 0x2C91, "Corigine, Inc." }, - { 0x2C92, "Ningbo Yinzhou Shengke Electronics Co., Ltd." }, - { 0x2C93, "SWFL Inc. dba: Filament" }, - { 0x2C94, "HIRATSUKA Engineering Co., Ltd." }, - { 0x2C95, "TOSHIBA MACHINE CO., LTD." }, - { 0x2C96, "KBS Industrieelektronik GmbH" }, - { 0x2C97, "LEDGER" }, - { 0x2C98, "Fosfomatic Technology LLC" }, - { 0x2C99, "Prusa Research s.r.o." }, - { 0x2C9A, "Lawo AG" }, - { 0x2C9B, "SPECIM, Spectral Imaging Ltd." }, - { 0x2C9C, "Vayyar Imaging LTD." }, - { 0x2C9D, "Nod Inc." }, - { 0x2C9E, "Shanghai Linguo Technology Co.,Ltd." }, - { 0x2C9F, "e-Smart Systems Pvt. Ltd." }, - { 0x2CA0, "Leagtech Jiangxi Electronic Co., Ltd." }, - { 0x2CA1, "Veetone Technologies Limited" }, - { 0x2CA2, "GuangZhou MingPing Electronics Technology" }, - { 0x2CA3, "DJI Technology Co., Ltd." }, - { 0x2CA4, "Shenzhen Alex Technology Co., Ltd." }, - { 0x2CA5, "Fussen Technology Co., Ltd." }, - { 0x2CA6, "Dai-ichi Dentsu Ltd." }, - { 0x2CA7, "Heptagon Advanced Micro Optics" }, - { 0x2CA8, "STATSports" }, - { 0x2CA9, "JITS TECHNOLOGY CO., LIMITED" }, - { 0x2CAA, "LIVV Brand llc" }, - { 0x2CAB, "AppWorld S. de R.L. de C.V." }, - { 0x2CAC, "MGF Sviesos Konversija, UAB" }, - { 0x2CAD, "EMS Security Group Ltd." }, - { 0x2CAE, "Clyde Broadcast Products Ltd." }, - { 0x2CAF, "IDS GmbH" }, - { 0x2CB0, "Creative bits Solutions" }, - { 0x2CB1, "Avista Corporation" }, - { 0x2CB2, "NAGANO KEIKI CO., LTD." }, - { 0x2CB3, "Shenzhen Bolin Image Science Technology Co., Ltd." }, - { 0x2CB4, "Ava Enterprises, Inc. dba Boss Audio Systems" }, - { 0x2CB5, "SUS Corp." }, - { 0x2CB6, "Borqs Hong Kong Limited" }, - { 0x2CB7, "Fibocom Wireless Inc." }, - { 0x2CB8, "Shenzhen Sydixon Electronic Technology Co., Ltd." }, - { 0x2CB9, "On-Bright Electronics (Shanghai) Co., Ltd." }, - { 0x2CBA, "Dongguan Puxu Industrial Co., Ltd." }, - { 0x2CBB, "Shenzhen Soling Indusrtial Co., Ltd." }, - { 0x2CBD, "EGGCYTE, INC." }, - { 0x2CBE, "uQontrol" }, - { 0x2CBF, "Donggguan Yuhua Electronic Co., Ltd." }, - { 0x2CC0, "Hangzhou Zero Zero Technology Co., Ltd." }, - { 0x2CC1, "SIGFOX" }, - { 0x2CC2, "Lautsprecher Teufel GmbH" }, - { 0x2CC3, "A-VEKT K.K." }, - { 0x2CC4, "Sanden Advanced Technology Corporation" }, - { 0x2CC5, "Metatronics" }, - { 0x2CC6, "Prodigy Technovations Pvt Ltd" }, - { 0x2CC7, "EmergiTech, Inc" }, - { 0x2CC8, "Hewlett Packard Enterprise" }, - { 0x2CC9, "Monolithic Power Systems Inc." }, - { 0x2CCA, "Amphenol Advanced Sensors" }, - { 0x2CCB, "USB Memory Direct" }, - { 0x2CCC, "Silicon Mitus Inc." }, - { 0x2CCD, "ITOS Inc." }, - { 0x2CCE, "SMARTY Performance King SA" }, - { 0x2CCF, "Hypersecu Information Systems, Inc." }, - { 0x2CD0, "Technics Global Electronics & JCE Co., Ltd." }, - { 0x2CD1, "Tamron Co., Ltd." }, - { 0x2CD2, "Mikrotikls S/A" }, - { 0x2CD3, "Life Robotics Inc." }, - { 0x2CD4, "NGK SPARK PLUG CO., LTD." }, - { 0x2CD5, "Institut Dr. Foerster GmbH & Co. KG" }, - { 0x2CD6, "Immersive Media" }, - { 0x2CD7, "Cosemi Technologies Inc." }, - { 0x2CD8, "Nanoport Technology, Inc." }, - { 0x2CD9, "Cambrionix Ltd" }, - { 0x2CDA, "CXUN Co. Ltd." }, - { 0x2CDB, "China Tsp Inc" }, - { 0x2CDC, "Sea & Sun Technology GmbH" }, - { 0x2CDD, "IAI Corporation" }, - { 0x2CDE, "RTI International" }, - { 0x2CDF, "Tecno Alarm S.R.L." }, - { 0x2CE0, "iClassmate Educational Technologies Co., Ltd." }, - { 0x2CE1, "Gradus Group" }, - { 0x2CE2, "Yanfeng Visteon (Chongqing) Automotive Electronics Co" }, - { 0x2CE3, "Alcorlink Corp." }, - { 0x2CE4, "ISBC Ltd." }, - { 0x2CE5, "InX8 Inc dba AKiTiO" }, - { 0x2CE6, "SDAN Tecchnology Co., Ltd." }, - { 0x2CE7, "Lemobile Information Technology (Beijing) Co., Ltd." }, - { 0x2CE8, "DongGuan Hongweixiang Electronic Technology Co., Ltd." }, - { 0x2CE9, "Suzhu Jingshi Electronic Technology Co., Ltd." }, - { 0x2CEA, "Zhong Shan City Richsound Electronic Industrial Ltd." }, - { 0x2CEB, "Dongguang Kangbang Electronics Co., Ltd." }, - { 0x2CEC, "Ascon Tecnologic" }, - { 0x2CED, "KMC Controls, Inc." }, - { 0x2CEE, "Winpower Qmadix Technology Co., Ltd." }, - { 0x2CEF, "Toptest Technologies Co., Ltd." }, - { 0x2CF0, "Nuand, LLC" }, - { 0x2CF1, "DTS, Inc." }, - { 0x2CF2, "KUNSHAN DLK Electronics Technology Co., Ltd." }, - { 0x2CF3, "Konekt, Inc." }, - { 0x2CF4, "CAM2 Technologies, LLC dba: Czitek" }, - { 0x2CF5, "EBARA REFRIGERATION EQUIPMENT & SYSTEMS CO., LTD." }, - { 0x2CF6, "Eye-Fi, Inc." }, - { 0x2CF7, "PPST, Inc." }, - { 0x2CF8, "Itron" }, - { 0x2CF9, "Terrafix Ltd." }, - { 0x2CFA, "Meta Company" }, - { 0x2CFB, "Nanchang Haozhun Electronics Co., Ltd." }, - { 0x2CFC, "DeLaval International AB" }, - { 0x2CFD, "GoerTek Inc." }, - { 0x2CFE, "Alpha Data Parallel Systems" }, - { 0x2CFF, "ITHAKi" }, - { 0x2D00, "VDO Cyclecomputing, Cycle Parts GmbH" }, - { 0x2D01, "Gopod Group Limited" }, - { 0x2D02, "Zhi Sheng Electronics Technology Co., Ltd." }, - { 0x2D03, "ECCO Safety Group" }, - { 0x2D05, "Technology Solutions (UK) Limited" }, - { 0x2D06, "Jireh Industries Ltd." }, - { 0x2D07, "MSI.TOKYO, Inc." }, - { 0x2D08, "ZIT Ltd." }, - { 0x2D09, "Dongguan Evervictory Electronic Co., Ltd." }, - { 0x2D0A, "Kingsignal Technology Co., Ltd." }, - { 0x2D0B, "IPD CO., LTD" }, - { 0x2D0C, "B & P Automation Dynamics Ltd" }, - { 0x2D0D, "Star Vision Electronics Limited" }, - { 0x2D0E, "Linxee (Beijing) Technology LTD." }, - { 0x2D0F, "M8TRIX TECH LLC" }, - { 0x2D10, "Shenzhen San Guan Si Yuan Technology Limited" }, - { 0x2D11, "Servelec Technologies" }, - { 0x2D12, "SICPA Security Solutions SA" }, - { 0x2D13, "DONG GUAN EBEN ELECTRONIC CO., LTD" }, - { 0x2D14, "Palit Microsystems Ltd" }, - { 0x2D15, "Si-Ware Systems" }, - { 0x2D16, "DONGGUAN WELLINK ELECTRONIC CO., LTD." }, - { 0x2D17, "TECHVIWIN INTERNATIONAL (HONGKONG) LIMITED" }, - { 0x2D18, "Hui Zhou Kai Yue Electronics Co., Ltd" }, - { 0x2D19, "Churchill Navigation" }, - { 0x2D1A, "Phononic" }, - { 0x2D1B, "Suzhou Yourfriend Electronic Co., Ltd." }, - { 0x2D1C, "Club 3D BV" }, - { 0x2D1D, "Design Pool Limited" }, - { 0x2D1E, "Excalibur" }, - { 0x2D1F, "Wacom Taiwan Information Co. Ltd." }, - { 0x2D20, "UL LLC" }, - { 0x2D21, "Koozyt, Inc." }, - { 0x2D22, "SEIKOSHA Co., Ltd." }, - { 0x2D23, "Shenzhen Microtest Automation Co., Ltd." }, - { 0x2D24, "Warwick Audio Technologies Ltd" }, - { 0x2D25, "Kronegger GmbH" }, - { 0x2D26, "Greenfield Technology" }, - { 0x2D27, "Global Optics Limited" }, - { 0x2D28, "Beijing ANTVR Technology Co., LTD" }, - { 0x2D29, "Beijing Baofengmojing Technologies Co. Ltd" }, - { 0x2D2A, "Shenzhen ZDT Technology Co., LTD" }, - { 0x2D2B, "STYL Solutions Pte Ltd" }, - { 0x2D2C, "Tankya Developing Co., Limited" }, - { 0x2D2D, "Guangzhou Botao Information Technology Co., Ltd" }, - { 0x2D2E, "Hieyoung International (Hong Kong) Limited" }, - { 0x2D2F, "PT Phototechnics AG" }, - { 0x2D30, "Addasound Denmark A/S" }, - { 0x2D31, "Synox Tech Co., Ltd." }, - { 0x2D32, "JR Technik Co., Ltd." }, - { 0x2D33, "Elysia-raytest GmbH" }, - { 0x2D34, "Nureva Inc." }, - { 0x2D35, "SIGMA TECH. CO., LTD" }, - { 0x2D36, "Blu5 View Pte. Ltd." }, - { 0x2D37, "Xprinter Co., Ltd" }, - { 0x2D38, "Shanghai OXi Technology Co., Ltd" }, - { 0x2D39, "Roofer Technology (Shenzhen) Co. Ltd" }, - { 0x2D3A, "Le Touch (Shenzhen) Electronics Co., Ltd." }, - { 0x2D3B, "Lencheng Electronics Co., Ltd" }, - { 0x2D3C, "FOVE, Inc." }, - { 0x2D3D, "Battlespace Simulations, Inc." }, - { 0x2D3E, "Technica Del Arte BV" }, - { 0x2D3F, "ViCentra B.V." }, - { 0x2D40, "Beijing Pico Technology Co., Ltd." }, - { 0x2D41, "Dongguan Mankind Plastic Electronics Co., Ltd" }, - { 0x2D42, "Protech Electronics & Technology Limited" }, - { 0x2D43, "OSSIC Corporation" }, - { 0x2D44, "FAMAR FUEGUINA S.A." }, - { 0x2D45, "JSC TION SMART MICROCLIMATE" }, - { 0x2D46, "JSC Yukon Advanced Optics Worldwide" }, - { 0x2D47, "INVENCO GROUP LIMITED" }, - { 0x2D48, "StarBridge, Inc." }, - { 0x2D49, "Shanghai Deepoon Technology Co., Ltd." }, - { 0x2D4A, "Helioway Enterprises Co., Ltd" }, - { 0x2D4B, "Dongguan Hongwei Electronics Co.,Ltd" }, - { 0x2D4C, "Ixtra Tech Inc" }, - { 0x2D4D, "Razer Inc" }, - { 0x2D4E, "Electronic Equipment BV" }, - { 0x2D4F, "Dongguan Hanker Electronic Technology Co., Ltd." }, - { 0x2D50, "CryLaS - Crystal Laser Systems GmbH" }, - { 0x2D51, "NITTA Corporation" }, - { 0x2D52, "YiQin Electronics Co.,Ltd" }, - { 0x2D53, "OWOW Products B.V." }, - { 0x2D54, "C-Smartlink Information Technology Co., Ltd." }, - { 0x2D55, "Nagravision SA" }, - { 0x2D56, "DongGuan Kelta Electro Mechanical Products CO, LTD" }, - { 0x2D58, "Lyra Semiconductor Incorporated" }, - { 0x2D59, "Sunyking Technology Co., Ltd" }, - { 0x2D5A, "Shenzhen YAAN Precision Connector Co., Ltd." }, - { 0x2D5B, "SunTo Technology (Shen Zhen) Corporation Limited" }, - { 0x2D5C, "Daiwoo Electronics Lo., LTD" }, - { 0x2D5D, "Loctek Ergonomic Technology Corp." }, - { 0x2D5E, "Sky UK Limited" }, - { 0x2D5F, "Shanghai Yuewen information technology Co., Ltd." }, - { 0x2D60, "Comarch S.A." }, - { 0x2D61, "Shenzhen Hongjixin Plastic & Electronics Co., Ltd" }, - { 0x2D62, "Weifang Genius Electronics Co.,Ltd." }, - { 0x2D63, "Cable Technology Corp." }, - { 0x2D64, "H.D.T. S.R.L" }, - { 0x2D65, "DPA Microphones" }, - { 0x2D66, "Oley Company Limited" }, - { 0x2D67, "Fengfan (Suzhou) Audio Technology Co., Ltd." }, - { 0x2D68, "Lumulabs d.o.o." }, - { 0x2D6A, "AIPHONE Co., LTD" }, - { 0x2D6B, "NetUP Inc." }, - { 0x2D6C, "Sphericam Inc." }, - { 0x2D6D, "Shenzhen HaiWei Technology Co., LTD" }, - { 0x2D6E, "Jiangsu Jing Lian Electronic Technology Co., Ltd" }, - { 0x2D6F, "Tobii Dynavox" }, - { 0x2D70, "Zhongshan Winner Electronic Technology CO., LTD" }, - { 0x2D71, "OVERKIZ" }, - { 0x2D72, "DOGAWIST - Investment GmbH" }, - { 0x2D73, "XtremeMac Sarl" }, - { 0x2D74, "CMO America; dba ZipKord Solutions" }, - { 0x2D75, "Shenzhen Taiji Electronics Co., Ltd." }, - { 0x2D76, "SiliConch Systems Private Limited" }, - { 0x2D77, "SweDeltaco AB" }, - { 0x2D78, "Dental Imaging Technology Corporation" }, - { 0x2D79, "Shenzhen Legendary Technologies Co., LTD." }, - { 0x2D7A, "Dongguan JingFeng Electronics Technology Co., Ltd" }, - { 0x2D7B, "Panasonic Lighting Americas, Inc." }, - { 0x2D7C, "Dongguan City Qingda Electronic Co., Ltd." }, - { 0x2D7D, "Televes S.A." }, - { 0x2D7E, "NISSIN ELECTRIC Corporation" }, - { 0x2D7F, "Sinar Photography AG" }, - { 0x2D80, "Pendo Technology China Corporation" }, - { 0x2D81, "Evollve Inc." }, - { 0x2D82, "boud" }, - { 0x2D84, "Zhuhai J-Speed Technology Co., Ltd." }, - { 0x2D85, "Asahi Electronics Laboratory" }, - { 0x2D86, "Dongguan Team Force Electronic Co., Ltd" }, - { 0x2D87, "Zhuhai Spark Electronic Equipment Co., Ltd" }, - { 0x2D88, "Prinics Co., Ltd." }, - { 0x2D89, "Ekahau" }, - { 0x2D8A, "I-O Conn (GuangDong) Technologies Co., Ltd" }, - { 0x2D8B, "Eclatkey Semiconductor Technology Company Limited" }, - { 0x2D8C, "Hongrida Electronic Technology Co. LTD" }, - { 0x2D8D, "MISUMI Corporation" }, - { 0x2D8E, "Color Sentinel Systems, LLC" }, - { 0x2D8F, "Shenzhen Bing Chuang Wei Technology Co., Ltd." }, - { 0x2D90, "Humanplus" }, - { 0x2D91, "SDI Technologies Inc." }, - { 0x2D92, "Shanghai Fengtian Electronic Co., LTD." }, - { 0x2D93, "STK TECHNOLOGY CO., LTD." }, - { 0x2D94, "TokenWorks Inc." }, - { 0x2D95, "Vivo Mobile Communication Co., Ltd." }, - { 0x2D96, "SHENZHEN WAMAXLINK ELECTRONIC TECHNOLOGY CO., LTD" }, - { 0x2D97, "Dong Guan JingHe Electronics Technology Co., Ltd" }, - { 0x2D98, "Shenzhen Ruiming Technology Co., Ltd." }, - { 0x2D99, "Edifier International Limited" }, - { 0x2D9A, "Jiangsu GuoGuang Electronic Information Technology Co.," }, - { 0x2D9B, "iStorage Limited" }, - { 0x2D9C, "Global Connector Technology" }, - { 0x2D9D, "Dongguan Suntes Electronics Technology Co., Ltd." }, - { 0x2D9E, "Sivantos GmbH" }, - { 0x2D9F, "SABRENT" }, - { 0x2DA0, "IN-VISION Digital Imaging Optics GmbH" }, - { 0x2DA1, "Koden Electronics Co., Ltd" }, - { 0x2DA2, "CIMA SPA con socio unico" }, - { 0x2DA3, "Superior Communications" }, - { 0x2DA4, "GE Multilin" }, - { 0x2DA5, "Tokai Rika Create Corporation" }, - { 0x2DA6, "SiChuan Rui Thai Electronic Technology Co., Ltd." }, - { 0x2DA7, "Topland Corporation" }, - { 0x2DA8, "Harmonic Drive Systems Inc." }, - { 0x2DA9, "ELECTRONIC ASSEMBLY GmbH" }, - { 0x2DAA, "Shenzhen Jing Tuo Jin Electronics Co., Ltd." }, - { 0x2DAB, "CYD Electronics (Shenzhen) Co., Ltd." }, - { 0x2DAC, "Shenzhen YZB Electronics Technology Co., Ltd" }, - { 0x2DAD, "GoerTek Dynaudio Co., Ltd" }, - { 0x2DAE, "Hex Technology Limited" }, - { 0x2DAF, "IF Link Electronics Co Limited" }, - { 0x2DB0, "Shenzhen Welltech Cable Co., Ltd" }, - { 0x2DB1, "DongGuan Greatek Electronics Technology Co., LTD" }, - { 0x2DB2, "Imperx, Inc" }, - { 0x2DB3, "i Digital Galaxy Ltd." }, - { 0x2DB4, "Dongguan Changtuo Hardware Technology Co., Ltd." }, - { 0x2DB5, "Fuji Ceramics Corporation" }, - { 0x2DB6, "Kunshan 3e Electronics Co., Ltd." }, - { 0x2DB7, "Premium Sound Solutions Sdn. Bhd." }, - { 0x2DB8, "Foshan Yami Electric Ltd." }, - { 0x2DB9, "Danelec Marine A/S" }, - { 0x2DBA, "Houwa System Design, k.k" }, - { 0x2DBB, "Huajie IMI Technology Co., Ltd." }, - { 0x2DBC, "Mikroelektronika d.o.o" }, - { 0x2DBD, "Shanghai Xiaoyi Technology Co., Ltd" }, - { 0x2DBE, "MA Lighting Technology GmbH" }, - { 0x2DBF, "Tul Corporation" }, - { 0x2DC0, "Chipsea Technologies (Shenzhen) Corp" }, - { 0x2DC1, "littleBits" }, - { 0x2DC2, "MintWave Co., Ltd." }, - { 0x2DC3, "Action Industries (M) SDN BHD" }, - { 0x2DC4, "Six 15 Technologies" }, - { 0x2DC5, "Cytek Biosciences, Inc." }, - { 0x2DC6, "Dongguan Kingtron Electronics Technology Co., Ltd." }, - { 0x2DC7, "Lacroix Sofrel" }, - { 0x2DC8, "8BITDO TECHNOLOGY HK LIMITED" }, - { 0x2DC9, "3T B.V." }, - { 0x2DCA, "OEM Systems Co., Ltd." }, - { 0x2DCB, "i-Money Technology Co., Ltd." }, - { 0x2DCC, "Suzhou Keda Technology Co., Ltd." }, - { 0x2DCD, "Yeonho Electronics" }, - { 0x2DCE, "Shen Zhen Farmer Technology Co., Limited" }, - { 0x2DCF, "Dialog Semiconductor (UK) Ltd" }, - { 0x2DD0, "iBaby Labs, Inc" }, - { 0x2DD1, "Empathy Co., Ltd." }, - { 0x2DD2, "HARNICS Co., LTD." }, - { 0x2DD3, "Viscell, LLC" }, - { 0x2DD5, "Gingy Technology Inc." }, - { 0x2DD6, "Suzhou SuperMax Smart System Co., Ltd." }, - { 0x2DD7, "enRoute Co., Ltd." }, - { 0x2DD8, "Perception Sensors and Instrumentation Ltd" }, - { 0x2DD9, "Dong Guan Fei Tai Electronics CO., LTD." }, - { 0x2DDA, "Miura Systems Ltd" }, - { 0x2DDB, "Shenzhen DAK Technology Co., Ltd" }, - { 0x2DDC, "Audiolink Co., Ltd" }, - { 0x2DDD, "Princeton Infrared Technologies, Inc." }, - { 0x2DDE, "The Chamberlain Group, Inc." }, - { 0x2DDF, "BOMTECH ELECTRONICS CO., LTD." }, - { 0x2DE0, "Active-semi, Inc" }, - { 0x2DE1, "Jiang Su Denseting Precision Technology Co., Ltd." }, - { 0x2DE2, "PathPartner Technology Pvt. Ltd" }, - { 0x2DE3, "Shanghai Yitu Technology Co., Ltd." }, - { 0x2DE4, "Best Case and Accessories, Inc." }, - { 0x2DE5, "KaiJet Technology International Limited, Inc. dba j5create" }, - { 0x2DE6, "Amazon Fulfillment Services, Inc." }, - { 0x2DE7, "The LightCo, Inc." }, - { 0x2DE8, "Shenzhen City Xiaoduan Electrical Co., LTD." }, - { 0x2DE9, "CAR MATE MFG. CO., LTD." }, - { 0x2DEA, "LightFactor" }, - { 0x2DEB, "Hold-Key Electric Wire & Cable Co Ltd" }, - { 0x2DEC, "ZNi Technology Co., Ltd" }, - { 0x2DED, "Aquil Star Precision Industrial (Shenzhen) Co., Ltd" }, - { 0x2DEE, "Shenzhen MeiG Smart Technology Co., Ltd" }, - { 0x2DEF, "Kirale Technologies SL" }, - { 0x2DF0, "CANVASBIO CO., LTD" }, - { 0x2DF1, "Inovonics Corp" }, - { 0x2DF2, "LIPS Corporation" }, - { 0x2DF3, "LongSung Technology (Shanghai) Co., Ltd." }, - { 0x2DF4, "Jumplux Technology Co., Ltd." }, - { 0x2DF5, "Helium Systems Inc." }, - { 0x2DF6, "Greektown Casino-Hotel, LLC" }, - { 0x2DF7, "Fastwel Group Ltd." }, - { 0x2DF8, "ITEST" }, - { 0x2DF9, "EZQuest, Inc." }, - { 0x2DFA, "3DRUDDER" }, - { 0x2DFB, "Bren-Tronics, Inc." }, - { 0x2DFC, "Graphic Products" }, - { 0x2DFD, "Ubisoft Entertainment SA" }, - { 0x2DFE, "Next Thing Co." }, - { 0x2DFF, "Unicept GmbH" }, - { 0x2E00, "CIB Security Inc" }, - { 0x2E01, "Symetrix, Inc." }, - { 0x2E02, "Softiron" }, - { 0x2E03, "Zhejiang Dahua Technology Co., Ltd." }, - { 0x2E04, "HMD Global Oy" }, - { 0x2E05, "CKD Corporation" }, - { 0x2E06, "Shenzhen Junlan Electronic Ltd" }, - { 0x2E07, "Lafayette Instrument Company" }, - { 0x2E08, "Zhongshan Dumei Weite Electronics Co., Ltd" }, - { 0x2E09, "Beijing LLVision Technology Co. LTD" }, - { 0x2E0A, "Dytran Instruments" }, - { 0x2E0B, "Datafield Industries (HK) Ltd" }, - { 0x2E0C, "Shenzhen Mek Intellisys PTE Ltd" }, - { 0x2E0D, "Suzhou FanglinTechnology Co., Ltd" }, - { 0x2E0E, "Hatteland Display AS" }, - { 0x2E0F, "Institute for Defense Analyses / Center for Computing Sciences" }, - { 0x2E10, "LinkMTech Inc." }, - { 0x2E11, "ShenZhen ShenTai WeiXiang Electronics Co., Ltd" }, - { 0x2E12, "Hongkong Chenyang Electronic Co., Limited" }, - { 0x2E13, "Intelligent Automation (Zhuhai) Co., Ltd" }, - { 0x2E14, "Expressive" }, - { 0x2E15, "Now Technologies" }, - { 0x2E16, "Glosys Inc." }, - { 0x2E17, "Essential Products, Inc." }, - { 0x2E18, "NorthStar Battery Company, LLC" }, - { 0x2E19, "Additel Corporation" }, - { 0x2E1A, "Shenzhen Arashi Vision Company Limited" }, - { 0x2E1B, "BeiJie Electronics Technology Co., Ltd" }, - { 0x2E1C, "Shenzhen Auto-Link World Information Technology Co., Ltd." }, - { 0x2E1D, "Clarion (Malaysia) Sdn. Bhd." }, - { 0x2E1E, "Sound Technology (C.Q.) Co., Ltd" }, - { 0x2E1F, "BrainScope Company, Inc." }, - { 0x2E20, "Guangzhou Long Do Co.,Ltd" }, - { 0x2E21, "DOSCH&AMAND Research GmbH&CoKG" }, - { 0x2E22, "DongGuan LinSong precision electronics CO., LTD" }, - { 0x2E23, "Shenzhen Baojia Battery Technology Co., Ltd." }, - { 0x2E24, "Hyperkin Inc." }, - { 0x2E25, "Gold Cable (Zhongshan) Electronic Co., Ltd." }, - { 0x2E26, "Monoprice, Inc." }, - { 0x2E27, "Lion Semiconductor" }, - { 0x2E28, "VOLTRONIC POWER TECHNOLOGY CORP." }, - { 0x2E29, "Clas Ohlson AB" }, - { 0x2E2B, "Shenzhen Qinps Technology Co Limited" }, - { 0x2E2C, "Dashine Electronics Co, Ltd" }, - { 0x2E2D, "Anaren Inc." }, - { 0x2E2E, "First Design System Inc." }, - { 0x2E2F, "Gulden Ophthalmics, Inc." }, - { 0x2E30, "Andon Health Co., Ltd." }, - { 0x2E31, "Thine Electronics, Inc." }, - { 0x2E32, "Shenzhen Red Star Electronics Co., Ltd." }, - { 0x2E33, "Squarehead Technology" }, - { 0x2E34, "ALLDATA LLC" }, - { 0x2E35, "Shenzhen PYS Industrial Co., LTD" }, - { 0x2E36, "Depo Electronics Limited" }, - { 0x2E37, "IRISO ELECTRONICS CO., LTD" }, - { 0x2E38, "OHM ELECTRONIC INC." }, - { 0x2E39, "Epic Tech, LLC" }, - { 0x2E3A, "Nanaboshi Electric Mfg. Co., Ltd." }, - { 0x2E3B, "uSens Inc" }, - { 0x2E3C, "ARTERY Technology Co., Ltd." }, - { 0x2E3D, "ASWAN ELEC. SALES CO., LTD." }, - { 0x2E3E, "Karma Automotive" }, - { 0x2E3F, "Poly-Planar Group LLC" }, - { 0x2E40, "Mobile Technologies Inc" }, - { 0x2E41, "DONGGUAN RONGDEKANG ELECTRONIC TECHNOLOGY CO., LTD." }, - { 0x2E42, "Hunan Ronghe Microelectronics Co., Ltd." }, - { 0x2E43, "Owl Labs, Inc" }, - { 0x2E44, "Idealens Technology (Chengdu) Co., Ltd." }, - { 0x2E45, "Widex A/S" }, - { 0x2E46, "Mobileconn Technology Co., Ltd." }, - { 0x2E47, "X-Media Tech, Inc." }, - { 0x2E48, "Andromium Inc." }, - { 0x2E49, "A&T Corporation" }, - { 0x2E4A, "Xiamen Jinhaode Electronic Co., Ltd" }, - { 0x2E4B, "ART SPA" }, - { 0x2E4C, "Carter Duncan Corp." }, - { 0x2E4D, "Vinpower, Inc." }, - { 0x2E4E, "METER Group, Inc" }, - { 0x2E4F, "Audiotec Fischer GmbH" }, - { 0x2E50, "beyerdynamic GmbH & Co. KG" }, - { 0x2E51, "EVER Sp. Z.o.o." }, - { 0x2E52, "Toughbuilt Industries Inc" }, - { 0x2E53, "Shenzhen East-Toptech Electronic Technology Co., Ltd" }, - { 0x2E54, "Yin Run Precise Metal Products CO., LTD." }, - { 0x2E55, "FIP Formatura Iniezione Polimeri an Aliaxis Company" }, - { 0x2E56, "Juchin Technology (JIANGXI) Co., Ltd" }, - { 0x2E57, "MEGWARE Computer Vertrieb und Service GmbH" }, - { 0x2E58, "GONGNIU GROUP CO., LTD." }, - { 0x2E59, "Maui Imaging, Inc." }, - { 0x2E5A, "Mysher Technology Co., Ltd." }, - { 0x2E5B, "Fitipower Integrated Technology Inc." }, - { 0x2E5C, "Y.H.S. Co., Ltd" }, - { 0x2E5D, "Dong Guan LM-Link Precise Electronic Co., Ltd." }, - { 0x2E5E, "Mei Shun He Electronic Limited" }, - { 0x2E5F, "Shenzhen BTC Technology Co., Ltd." }, - { 0x2E60, "castAR, Inc." }, - { 0x2E61, "NetBurner, Inc." }, - { 0x2E62, "Will Semiconductor Co., LTD" }, - { 0x2E63, "Polaris-Labs Shenzhen Co., Ltd" }, - { 0x2E64, "Shenzhen Kaibao Technology Co., Ltd." }, - { 0x2E65, "Kunshan Xintaili Precision Components Co., Ltd." }, - { 0x2E66, "SALICRU, S.A." }, - { 0x2E67, "Elevation Lab, Inc." }, - { 0x2E68, "Tessonics Inc." }, - { 0x2E69, "Swift Navigation Inc" }, - { 0x2E6A, "Wilderness Labs Inc." }, - { 0x2E6B, "DMX, LLC dba Mood Media" }, - { 0x2E6C, "Uwatec AG" }, - { 0x2E6D, "Laser Argentina S.A." }, - { 0x2E6E, "E4D Technologies LLC" }, - { 0x2E6F, "Areca Technology Corporation" }, - { 0x2E70, "Revision Electronics & Power Systems Inc." }, - { 0x2E71, "Futurepath Electronics Technology (Dongguan) Co., Ltd." }, - { 0x2E72, "DongGuan YongHao Electronics Co., LTD" }, - { 0x2E73, "Backyard Brains" }, - { 0x2E74, "Magenta Labs Inc." }, - { 0x2E75, "Shanghai Hinge Electronic Technologies Co., Ltd." }, - { 0x2E76, "Guangdong Jinrun Electronics Co., Ltd." }, - { 0x2E77, "LOGICDATA Electronics & Software Entwicklungs GmbH" }, - { 0x2E78, "ES Gear Ltd." }, - { 0x2E79, "NP System Development Co., Ltd." }, - { 0x2E7A, "Jiangsu BDSTAR Navigation Electronic Co., Ltd." }, - { 0x2E7B, "Terrada Music Score CO., Ltd." }, - { 0x2E7C, "Pyramid Solutions" }, - { 0x2E7D, "Shenzhen Xin Yong Yang Technology Co., Ltd." }, - { 0x2E7E, "ValueHD Corporation" }, - { 0x2E7F, "Aries Manufacturing - a division of Boss Tech Products Inc." }, - { 0x2E80, "Join Tek Corporation Co., Ltd." }, - { 0x2E81, "Zodiac Inflight Innovations" }, - { 0x2E82, "Sapphire Technology Limited" }, - { 0x2E83, "Ocean Tek Enterprise Co., Ltd." }, - { 0x2E84, "Sheng San Electronics (Shen Zhen) Co., Ltd." }, - { 0x2E85, "Verizon" }, - { 0x2E86, "SBO HEARING A/S" }, - { 0x2E87, "Shenzhen Injoinic Technology Co., Ltd." }, - { 0x2E88, "Huada Semiconductor Corporation Limited" }, - { 0x2E89, "Group Dekko, Inc." }, - { 0x2E8A, "Raspberry Pi (Trading) Limited" }, - { 0x2E8B, "Asia Optical International Ltd." }, - { 0x2E8C, "Aisino Wincor Manufacturing (Shanghai) Co., Ltd." }, - { 0x2E8D, "YSC Science Technique Electron (Yi Chun) Co., Ltd" }, - { 0x2E8E, "Bitatek CO., LTD" }, - { 0x2E8F, "Shenzhen Weiduli Technology Co., Ltd." }, - { 0x2E90, "Wireless Media Tech CO., Limited" }, - { 0x2E91, "Shenzhen Suprint Smart Technology Co., Ltd." }, - { 0x2E92, "bioMerieux, Inc." }, - { 0x2E93, "Shenzhen Huikeyuan Electronic Technology Co., Ltd." }, - { 0x2E94, "Graviton Inc." }, - { 0x2E95, "Scuf Gaming International, LLC" }, - { 0x2E96, "Aspect Microsystems Corp." }, - { 0x2E97, "Aerocool Advanced Technologies Corporation" }, - { 0x2E98, "Nekteck, Inc." }, - { 0x2E99, "Hynetek Semiconductor Co., Ltd" }, - { 0x2E9A, "MS Solutions Co., Ltd." }, - { 0x2E9B, "New Imaging Technologies" }, - { 0x2E9C, "Shenzhen Silkway Technology Co., Ltd." }, - { 0x2E9D, "Resolved Instruments Inc." }, - { 0x2E9E, "SoundAI Technology Co., Ltd." }, - { 0x2E9F, "EyeTech Digital Systems, Inc." }, - { 0x2EA0, "Magnescale Co., Ltd." }, - { 0x2EA1, "DASANELECTRON CO., LTD" }, - { 0x2EA2, "Ningbo Kangda Electronic Co., Ltd." }, - { 0x2EA3, "POSLAB Technology Corporation" }, - { 0x2EA4, "Hubbell Incorporated (Delaware), Wiring Device Kellems Division" }, - { 0x2EA5, "Dongguanshi Qitaiprecision Moulds Co., Ltd." }, - { 0x2EA6, "Foreign Trade Corporation dba. Technocel" }, - { 0x2EA7, "Muhanbit" }, - { 0x2EA8, "Changsha JingJia Microelectronics Co., LTD." }, - { 0x2EA9, "Yuneec International (China) Co., Ltd." }, - { 0x2EAA, "TSUME S.A." }, - { 0x2EAB, "Zong Cable Technology Co., Ltd." }, - { 0x2EAC, "Jia Yang Electronics (Dongguan) Co., Ltd." }, - { 0x2EAD, "Align Technology Inc." }, - { 0x2EAE, "Shenzhen TOMTOP Technology Co., Ltd." }, - { 0x2EAF, "microsonic co., ltd." }, - { 0x2EB0, "Commtech, Inc." }, - { 0x2EB1, "Samsung SmartThings" }, - { 0x2EB2, "Markus Klotz GmbH" }, - { 0x2EB3, "Shenzhen Tokwa Precision Technology Co., Ltd." }, - { 0x2EB4, "Beijer Automotive BV" }, - { 0x2EB5, "Dongguan HengYue Communication Technology Co., Ltd." }, - { 0x2EB6, "The Vehicle Group LTD" }, - { 0x2EB7, "Digital Divide Systems Ltd." }, - { 0x2EB8, "Yueqing Nuode Electronic Technology Co., Ltd." }, - { 0x2EB9, "SSI Computer Corp." }, - { 0x2EBA, "Shenzhen E&C Smart Link Technology Co., Ltd." }, - { 0x2EBB, "Shanghai Tuzheng Information Technology Co., Ltd." }, - { 0x2EBC, "RAIDON Technology Inc." }, - { 0x2EBD, "Netstor Technology Co., Ltd." }, - { 0x2EBE, "Delphi Automotive Systems, LLC" }, - { 0x2EBF, "Shenzhen D&D Technology Co., Ltd" }, - { 0x2EC0, "GuideTech" }, - { 0x2EC1, "Avid Identification Systems, Inc." }, - { 0x2EC2, "Loupedeck Oy" }, - { 0x2EC3, "Shenzhen Huntkey Electric Co., Ltd." }, - { 0x2EC4, "tetralux S.a.r.l." }, - { 0x2EC5, "Ariba Technology Co., LTD." }, - { 0x2EC6, "Facebook, Inc." }, - { 0x2EC7, "ITECH Electronic Co., Ltd." }, - { 0x2EC8, "Ningbo Prime Electronic Co., Ltd." }, - { 0x2EC9, "Shenzhou Rongan Technology (Beijing) Limited" }, - { 0x2ECA, "AQuantia Corp" }, - { 0x2ECB, "Zhejiang Quzhou Gelinte Wire and Cable Co., Ltd." }, - { 0x2ECC, "ASR Microelectronics (Shanghai) Co., Ltd." }, - { 0x2ECD, "EUROICC" }, - { 0x2ECE, "E-Lead Electronic Co., Ltd." }, - { 0x2ECF, "Fluo Technology Ltd." }, - { 0x2ED0, "Mind Alive Inc." }, - { 0x2ED1, "QBit Semiconductor LTD" }, - { 0x2ED2, "APOLLO GIKEN Co., Ltd." }, - { 0x2ED3, "Shenzhen Xinhongya Electronics Corporation" }, - { 0x2ED4, "Butterfly Network Inc." }, - { 0x2ED5, "QSAN Technology, Inc." }, - { 0x2ED6, "Shenzhen Xinliyang Co., Ltd." }, - { 0x2ED7, "Libratel Inc" }, - { 0x2ED8, "Dongguan Lontion Industrial Co., Ltd." }, - { 0x2ED9, "Microscopes International, LLC" }, - { 0x2EDA, "Wenzhou Haitong Communication Electronics Co., Ltd." }, - { 0x2EDB, "NeuroHabilitation Corporation" }, - { 0x2EDC, "Nippon Techno Lab., Inc." }, - { 0x2EDD, "reMarkable AS" }, - { 0x2EDE, "Technik Industrial Company Limited" }, - { 0x2EDF, "Huizhou Wealth Metal Micro Control Limited" }, - { 0x2EE0, "Pogotec Inc." }, - { 0x2EE1, "Safetrust Inc" }, - { 0x2EE2, "Kashimura Co., Ltd." }, - { 0x2EE3, "Kin Keung Electrical Mfg. Ltd." }, - { 0x2EE4, "Osprey Video, Inc." }, - { 0x2EE6, "NEURODIGITAL TECHNOLOGIES, S.L." }, - { 0x2EE7, "GOOGFIT TECH LIMITED" }, - { 0x2EE8, "Zunidata Systems, Inc." }, - { 0x2EE9, "Adigal LLC" }, - { 0x2EEA, "Loma Systems" }, - { 0x2EEB, "Jianduan Technology (Shenzhen) Co., Ltd." }, - { 0x2EEC, "Sensor Industries Limited" }, - { 0x2EED, "Shenzhen Panhui Technologies Co., Ltd." }, - { 0x2EEE, "Beijing Qunli Tiancheng Network Technology Company" }, - { 0x2EEF, "Booz Allen Hamilton" }, - { 0x2EF0, "Zhongshan Auxus Electronic Technology Co., Ltd." }, - { 0x2EF1, "Tatvik Biosystems Private Limited" }, - { 0x2EF2, "Shenzhen Goodwin Technology Co., Ltd." }, - { 0x2FB2, "Fujitsu Limited" }, - { 0x3176, "WHANAM ELECTRONICS CO., Ltd. MS division" }, - { 0x3552, "BD Consumer Healthcare" }, - { 0x3636, "INVIBRO" }, - { 0x3884, "Nicolet Biomedical Inc., a Viasys Healthcare Co." }, - { 0x3923, "National Instruments" }, - { 0x4102, "iRiver" }, - { 0x413C, "Dell Inc." }, - { 0x4234, "Powervar Inc. (UPS Products)" }, - { 0x4242, "USB Design By Example" }, - { 0x4317, "Broadcom WLAN" }, - { 0x4426, "TANITA Corporation" }, - { 0x4745, "Beijing Tiertime Technology Co., Ltd." }, - { 0x4791, "Western Digital, G-Tech" }, - { 0x4909, "GE Healthcare Bio-Sciences AB" }, - { 0x4971, "HITACHI GLOBAL STORAGE TECHNOLOGIES" }, - { 0x4B53, "Key Soft Service" }, - { 0x4C46, "DSPecialists GmbH" }, - { 0x4DDC, "Data Device Corporation" }, - { 0x5058, "ProXense, LLC" }, - { 0x5245, "RESPIRONICS, INC." }, - { 0x544D, "Transmeta Corporation" }, - { 0x5543, "UC-Logic Technology Corp." }, - { 0x5555, "Number Five, Software" }, - { 0x55AA, "OnSpec Electronic Inc." }, - { 0x5986, "BISON ELECTRONICS INC." }, - { 0x6000, "TRIDENT MICROSYSTEMS (Far East) Ltd." }, - { 0x630F, "Leapfrog Schoolhouse" }, - { 0x636C, "CoreLogic, Inc." }, - { 0x6400, "Springer Design, Inc." }, - { 0x6A75, "Shanghai Jujo Electronics Co., Ltd." }, - { 0x735F, "Beijing Techshino Technology Co., Ltd." }, - { 0x8020, "Trinity, Inc." }, - { 0x8086, "Intel Corporation" }, - { 0x8087, "Intel" }, - { 0x8829, "Beijing Daming Wuzhou Science & Technology Co., Ltd." }, - { 0x8873, "Dengineer Co., Ltd." }, - { 0x9696, "Digital Arts, Inc." }, - { 0x9710, "Moschip Semiconductor Technology" }, - { 0xA600, "ASIX s.r.o." }, - { 0xA625, "Wuhan Tianyu Information Industry Co., Ltd." }, - { 0xBEE5, "BEE SYSTEMS LLC" }, - { 0xC0B8, "Corbett Life Science" }, - { 0xC10C, "Given Imaging" }, - { 0xCACE, "CACE Technologies" }, - { 0xCC42, "Cardio Control NV" }, - { 0xEA01, "Eagle Technology" }, - { 0xEB1A, "Empia Technology, Inc." }, - { 0xFF01, "DisplayPort (VESA)" }, - { 0xFF02, "MHL, LLC" }, - { 0xFF03, "MIPI Debug" }, - { 0xFF04, "HDMI" }, - { 0x0000, "Vendor ID not listed with USB.org" } -}; - -#endif /* __VNDRLIST_H__ */ - diff --git a/tests/projects/winsdk/usbview/xmake.lua b/tests/projects/winsdk/usbview/xmake.lua deleted file mode 100644 index 5d5639429..000000000 --- a/tests/projects/winsdk/usbview/xmake.lua +++ /dev/null @@ -1,13 +0,0 @@ --- add rules -add_rules("mode.debug", "mode.release") - --- define target -target("usbview") - - -- windows application - add_rules("win.sdk.application") - - -- add files - add_files("*.c", "*.rc") - add_files("xmlhelper.cpp", {rule = "win.sdk.dotnet"}) - diff --git a/tests/projects/winsdk/usbview/xmlhelper.cpp b/tests/projects/winsdk/usbview/xmlhelper.cpp deleted file mode 100644 index bac7d797b..000000000 --- a/tests/projects/winsdk/usbview/xmlhelper.cpp +++ /dev/null @@ -1,3235 +0,0 @@ -/*++ - - Copyright (c) 1997-2011 Microsoft Corporation - - Module Name: - - XMLHELPER.CPP - -Abstract: - -This source file contains helper APIs for reading writing XML - -Environment: - -user mode - -Revision History: - -05-05-11 : created - ---*/ - -/***************************************************************************** - I N C L U D E S - *****************************************************************************/ -#include "uvcview.h" -#include "h264.h" -#include "xmlhelper.h" - -// usbschema.hpp is autogenerated from schema during build PASS0 -#include "usbschema.hpp" - -// Include code analysis suppressions -#include "codeanalysis.h" - -/***************************************************************************** - D E F I N E S - *****************************************************************************/ -#define COBJMACROS - -#define PACHAR_TO_STRING(X) ((X != NULL)? gcnew String(Marshal::PtrToStringAnsi((IntPtr) X )):nullptr) -#define PWCHAR_TO_STRING(X) ((X != NULL)? gcnew String(Marshal::PtrToStringUni((IntPtr) X )):nullptr) - -#define MAX_STRING_DESCRIPTOR_LENGTH 512 -#define STRING_DESCRIPTOR_EN_LANGUAGE_ID 0x0409 -#define DEVICE_DESCRIPTOR_LENGTH 18 - -#define SERVICE_EHCI "usbehci" -#define SERVICE_XHCI "usbxhci" -#define SERVICE_OHCI "usbohci" -#define SERVICE_UHCI "usbuhci" - -#define USB_1_1 "USB 1.1" -#define USB_2_0 "USB 2.0" -#define USB_3_0 "USB 3.0" -#define USB_GENERIC "USB GENERIC (UNKNOWN)" - -/***************************************************************************** - N A M E S P A C E S - *****************************************************************************/ - -using namespace System; -using namespace System::IO; -using namespace System::Runtime::InteropServices; -using namespace System::Collections; -using namespace Microsoft::Kits::Samples::Usb; - - -/***************************************************************************** - G L O B A L S - *****************************************************************************/ - -namespace Microsoft -{ - namespace Kits - { - namespace Samples - { - namespace Usb - { - public ref class XmlGlobal sealed - { - private: - static XmlGlobal ^ pInstance = gcnew XmlGlobal(); - - // Empty private constructor - XmlGlobal() - { - } - - public: - // - // Globals for XML view - // - property UvcViewAll ^ ViewAll; - property bool XmlViewInitialized; - - // - // Stack of parents of a given node. This is used for finding - // where a given object should be added - // - -#if CODE_ANALYSIS - // ParentStack need not be constant since we will only have one instance of this object - [SuppressMessage("Microsoft.Usage", "CA2211:NonConstantFieldsShouldNotBeVisible")] -#endif - static Stack ^ ParentStack = gcnew Stack(); - - static XmlGlobal ^ Instance() - { - return pInstance; - } - }; - }; - }; - }; -}; - -#define gXmlView ((XmlGlobal::Instance())->ViewAll->UvcView) -#define gXmlViewInitialized ((XmlGlobal::Instance())->XmlViewInitialized) -#define gXmlStack ((XmlGlobal::Instance())->ParentStack) - -/***************************************************************************** - D E C L A R A T I O N S - *****************************************************************************/ - -String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly); -void XmlAddHostControllerPowerMapping( UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo); -String ^ XmlGetDeviceClassString(UCHAR deviceClass); -void XmlAddHostControllerPowerMapping(UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo); -void XmlAddHub30Descriptor(Hub30DescriptorType ^hub30Desc, PUSB_30_HUB_DESCRIPTOR hub30Descriptor); -void XmlAddHubDescriptor(HubDescriptorType ^hubDesc, PUSB_HUB_DESCRIPTOR hubDescriptor); -void XmlAddPortConnectorProps(PortConnectorType ^portXmlProps, PUSB_PORT_CONNECTOR_PROPERTIES portProps); -void XmlAddHubCharacteristics(HubInformationType ^hubI, WORD hubChar); -HRESULT XmlAddHubNodeInformation(HubNodeInformationType ^ni, PUSB_NODE_INFORMATION nodeInfo); -HRESULT XmlAddHubInformationEx(HubInformationExType ^ex, PUSB_HUB_INFORMATION_EX hubInfoEx); -HRESULT XmlAddHubCapabilitiesEx(HubCapabilitiesExType ^ex, USB_HUB_CAPABILITIES_EX hubCapEx); -ExternalHubType ^ AddExternalHub(Object ^parent); -NoDeviceType ^ AddDisconnectedPort(Object ^parent); -UsbDeviceType ^ AddUsbDevice(Object ^parent); -void XmlAddEndpointDescriptor( - EndpointDescriptorType ^usbXmlEndpointDescriptor, - PUSB_ENDPOINT_DESCRIPTOR endPointDescriptor, - UCHAR connectionSpeed); -void XmlAddPipeInformation( - array< UsbPipeInfoType ^> ^ usbXmlPipeInfoList, - PUSB_PIPE_INFO pipeInfo, - ULONG numPipes, - UCHAR connectionSpeed); -void XmlAddUsbDeviceDescriptor( - UsbDeviceDescriptorType ^usbXmlDeviceDescriptor, - PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor); -void XmlAddConfigurationDescriptor( - UsbConfigurationDescriptorType ^ confXmlDesc, - PUSBDEVICEINFO deviceInfo, - PUSB_CONFIGURATION_DESCRIPTOR configDesc, - PSTRING_DESCRIPTOR_NODE stringDesc); -void XmlAddDeviceQualDescriptor( - UsbDeviceQualifierDescriptorType ^ qualXmlDesc, - PUSB_DEVICE_QUALIFIER_DESCRIPTOR qualDesc); -void XmlAddDeviceConfiguration( - UsbDeviceConfigurationType ^ confXmlDesc, - PUSBDEVICEINFO deviceInfo, - PUSB_CONFIGURATION_DESCRIPTOR configDesc, - PSTRING_DESCRIPTOR_NODE stringDesc, - int numInterfaces); -void XmlAddConnectionInfoSt( - NodeConnectionInfoExStructType ^xmlConnectionInfoSt, - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, - PDEVICE_INFO_NODE pNode); -String ^ XmlGetLangIdString(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc); -String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly); -String ^ XmlGetDeviceClassString(UCHAR deviceClass); -bool XmlAddDeviceClassDetails( - UsbDeviceClassDetailsType ^ deviceDetails, - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, - PUSBDEVICEINFO deviceInfo); -void XmlAddConnectionInfo( - NodeConnectionInfoExType ^xmlConnectionInfo, - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, - PUSBDEVICEINFO deviceInfo, - PSTRING_DESCRIPTOR_NODE stringDesc, - PDEVICE_INFO_NODE pNode); -void XmlAddHidDescriptor( - UsbDeviceHidDescriptorType ^ hidXmlDesc, - PUSB_HID_DESCRIPTOR hidDesc); -void XmlAddDeviceInterfaceDescriptor( - UsbDeviceInterfaceDescriptorType ^ ifXmlDesc, - PUSB_INTERFACE_DESCRIPTOR ifDesc, - PSTRING_DESCRIPTOR_NODE stringDesc); -void XmlAddOTGDescriptor( - UsbDeviceOTGDescriptorType ^ otgXmlDesc, - PUSB_OTG_DESCRIPTOR otgDesc); -void XmlAddIADDescriptor( - UsbDeviceIADDescriptorType ^ iadXmlDesc, - PUSB_IAD_DESCRIPTOR iadDesc, - PSTRING_DESCRIPTOR_NODE stringDesc, - int nInterfaces); -array < UsbDeviceConfigurationType ^> ^ XmlGetConfigDescriptors( - PUSBDEVICEINFO deviceInfo, - PUSB_CONFIGURATION_DESCRIPTOR configDescs, - PSTRING_DESCRIPTOR_NODE stringDesc); -UsbBosDescriptorType ^ XmlGetBosDescriptor( - PUSB_BOS_DESCRIPTOR bosDesc, - PSTRING_DESCRIPTOR_NODE stringDesc - ); -UsbDeviceClassType ^ XmlGetDeviceClass(UCHAR deviceClass, UCHAR deviceSubClass, UCHAR deviceProtocol); -UsbDeviceUnknownDescriptorType ^ XmlGetUnknownDescriptor( - PUSB_COMMON_DESCRIPTOR unknownDesc - ); -UsbUsb20ExtensionDescriptorType ^ XmlGetUsb20CapabilityExtensionDescriptor( - PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR capDesc - ); -UsbSuperSpeedExtensionDescriptorType ^ XmlGetSuperSpeedCapabilityExtensionDescriptor( - PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR capDesc - ); -UsbDispContIdCapExtDescriptorType ^ XmlGetContainerIdCapabilityExtensionDescriptor( - PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR capDesc - ); -UsbBillboardCapabilityDescriptorType ^ XmlGetBillboardCapabilityDescriptor( - PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR capDesc, - PSTRING_DESCRIPTOR_NODE stringDesc - ); - -/***************************************************************************** - D E F I N I T I O N S - *****************************************************************************/ - -/***************************************************************************** - XmlNotifyEndOfNodeList - - This function is called back by WalkTreeTopDown() function to notify us - that there are no more children to add for the current parent - - *****************************************************************************/ -VOID XmlNotifyEndOfNodeList(PVOID pContext) -{ - UNREFERENCED_PARAMETER(pContext); - - if (gXmlStack != nullptr && gXmlStack->Count > 0) - { - // Remove the last parent on the stack - gXmlStack->Pop(); - } -} - -/***************************************************************************** - - XmlAddHostControllerPowerMapping() - - add power info to xml structure - *****************************************************************************/ -void XmlAddHostControllerPowerMapping(UsbHCPowerStateMappingType ^xmlPwrInfo, PUSB_POWER_INFO usbHCPowerInfo) -{ - int i, powerState; - PUSB_POWER_INFO pUPI = usbHCPowerInfo; - UsbHCPowerStateType ^ pwrState = nullptr; - - xmlPwrInfo->PowerMap = gcnew array (WdmUsbPowerSystemShutdown); - - for(i = 0, powerState = WdmUsbPowerSystemWorking; powerState < WdmUsbPowerSystemShutdown; i++, powerState++, pUPI++) - { - xmlPwrInfo->PowerMap[i] = gcnew UsbHCPowerStateType(); - pwrState = xmlPwrInfo->PowerMap[i]; - pwrState->SystemState = PACHAR_TO_STRING(GetPowerStateString(pUPI->SystemState)); - pwrState->HostControllerState = PACHAR_TO_STRING(GetPowerStateString(pUPI->HcDevicePowerState)); - pwrState->HubState = PACHAR_TO_STRING(GetPowerStateString(pUPI->RhDevicePowerState)); - pwrState->CanWakeUp = pUPI->CanWakeup? true:false; - pwrState->IsPowered = pUPI->IsPowered? true:false; - } - - xmlPwrInfo->LastSleepState = PACHAR_TO_STRING(GetPowerStateString(pUPI->LastSystemSleepState)); - return; -} - -/***************************************************************************** - - XmlAddHostController() - - Add an host controller to XML view - *****************************************************************************/ - -HRESULT XmlAddHostController(PSTR hcName, PUSBHOSTCONTROLLERINFO hcInfo) -{ - HRESULT hr = S_OK; - - UNREFERENCED_PARAMETER(hcName); - - HostControllerType ^ hc = nullptr; - // - // Check if the USB Tree array has been initialized - // It would have been great if XSD had a way of generating a list instead of array, but it does not - // So we have to do array.Resize everytime - // - if (gXmlView->UsbTree == nullptr) - { - // This is the first time we are being called, initialize the array with 1 element - gXmlView->UsbTree = gcnew array(1); - gXmlView->UsbTree[0] = gcnew HostControllerType(); - hc = gXmlView->UsbTree[0]; - } - else - { - // Create a new array every time as Array.Resize does not seem to work in our case (CLI) - // We do this using ArrayList. - ArrayList ^hcList = gcnew ArrayList; - hcList->AddRange(gXmlView->UsbTree); - hc = gcnew HostControllerType(); - hcList->Add(hc); - gXmlView->UsbTree = reinterpret_cast^> (hcList->ToArray(HostControllerType::typeid)); - } - - if (hc != nullptr) - { - ULONG debugPort = 0; - - UsbHCDeviceInfoType ^ ci = nullptr; - UsbHCPowerStateMappingType ^ pm = nullptr; - - if (NULL != hcInfo->UsbDeviceProperties) - { - hc->HwId = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->HwId); - hc->DeviceId = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceId); - hc->ServiceName = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->Service); - hc->DeviceName = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceDesc); - hc->DeviceClass = PACHAR_TO_STRING(hcInfo->UsbDeviceProperties->DeviceClass); - - bool foundUsbProtocol = false; - if (hcInfo->UsbDeviceProperties->Service != NULL) - { - foundUsbProtocol = true; - - if (_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_OHCI) == 0) - { - hc->UsbProtocol = gcnew String(USB_1_1); - } - else if(_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_EHCI) == 0 || - _stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_UHCI) == 0) - { - hc->UsbProtocol = gcnew String(USB_2_0); - } - else if (_stricmp(hcInfo->UsbDeviceProperties->Service, SERVICE_XHCI) == 0) - { - hc->UsbProtocol = gcnew String(USB_3_0); - } - else - { - foundUsbProtocol = false; - } - } - - if (!foundUsbProtocol) - { - // If protocol lookup failed based on service name, try Controller flavor - if(NULL != hcInfo->ControllerInfo) - { - USB_CONTROLLER_FLAVOR flavor = hcInfo->ControllerInfo->ControllerFlavor; - - if(flavor == USB_HcGeneric) - { - hc->UsbProtocol = gcnew String(USB_GENERIC); - } - else if(flavor >= OHCI_Generic && flavor < UHCI_Generic) - { - hc->UsbProtocol = gcnew String(USB_1_1); - } - else if(flavor >= UHCI_Generic && flavor <= EHCI_Generic) - { - hc->UsbProtocol = gcnew String(USB_2_0); - } - else if(flavor > EHCI_Generic) - { - hc->UsbProtocol = gcnew String(USB_3_0); - } - } - } - } - - hc->ControllerInfo = gcnew UsbHCDeviceInfoType(); - hc->PowerMapping = gcnew UsbHCPowerStateMappingType(); - ci = hc->ControllerInfo; - pm = hc->PowerMapping; - - ci->VendorId = hcInfo->VendorID; - ci->DeviceId = hcInfo->DeviceID; - ci->DriverKey = PACHAR_TO_STRING(hcInfo->DriverKey); - ci->SubSysId = hcInfo->SubSysID; - ci->Revision = hcInfo->Revision; - - if(NULL != hcInfo->ControllerInfo) - { - ci->NumberOfRootPorts = hcInfo->ControllerInfo->NumberOfRootPorts; - ci->ControllerFlavor = hcInfo->ControllerInfo->ControllerFlavor; - ci->PortSwitchingEnabled = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_FLAG_PORT_POWER_SWITCHING)? true: false; - ci->SelectiveSuspendEnabled = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_FLAG_SEL_SUSPEND)? true: false; - ci->LegacyBios = (hcInfo->ControllerInfo->HcFeatureFlags & USB_HC_FEATURE_LEGACY_BIOS)? true: false; - ci->ControllerFlavorString = PACHAR_TO_STRING(GetControllerFlavorString(hcInfo->ControllerInfo->ControllerFlavor)); - } - - // Add power mappings - XmlAddHostControllerPowerMapping(pm, (PUSB_POWER_INFO) (&(hcInfo->USBPowerInfo[0]))); - - // Add debug port - debugPort = GetEhciDebugPort(hcInfo->VendorID, hcInfo->DeviceID); - if (debugPort > 0) - { - ci->DebugPort = debugPort; - } - - gXmlStack->Push(hc); - - } - else - { - hr = E_FAIL; - } - - return hr; -} - -/***************************************************************************** - - XmlAddHub30Descriptor() - - Adds the hub 3.0 descriptor to the given hub object - *****************************************************************************/ -void XmlAddHub30Descriptor(Hub30DescriptorType ^hub30Desc, PUSB_30_HUB_DESCRIPTOR hub30Descriptor) -{ - - if (nullptr != hub30Desc && NULL != hub30Descriptor) - { - hub30Desc->Length = hub30Descriptor->bLength; - hub30Desc->DescriptorType = hub30Descriptor->bDescriptorType; - hub30Desc->NumberOfPorts = hub30Descriptor->bNumberOfPorts; - hub30Desc->HubCharacteristics = hub30Descriptor->wHubCharacteristics; - hub30Desc->PowerOntoPowerGood = hub30Descriptor->bPowerOnToPowerGood; - hub30Desc->HubControlCurrent = hub30Descriptor->bHubControlCurrent; - hub30Desc->HubHdrDecLat = hub30Descriptor->bHubHdrDecLat; - hub30Desc->DeviceRemovable = hub30Descriptor->DeviceRemovable; - } -} - -/***************************************************************************** - - XmlAddHubDescriptor() - - Adds the hub descriptor to the given hub object - *****************************************************************************/ -void XmlAddHubDescriptor(HubDescriptorType ^hubDesc, PUSB_HUB_DESCRIPTOR hubDescriptor) -{ - if (nullptr != hubDesc && NULL != hubDescriptor) - { - hubDesc->DescriptorLength = hubDescriptor->bDescriptorLength; - hubDesc->DescriptorType = hubDescriptor->bDescriptorType; - hubDesc->NumberOfPorts = hubDescriptor->bNumberOfPorts; - hubDesc->PowerOntoPowerGood = hubDescriptor->bPowerOnToPowerGood; - hubDesc->HubControlCurrent = hubDescriptor->bHubControlCurrent; - } -} - -/***************************************************************************** - - XmlAddPortConnectorProps() - - Adds the port connector properties to XML file - *****************************************************************************/ -void XmlAddPortConnectorProps(PortConnectorType ^portXmlProps, PUSB_PORT_CONNECTOR_PROPERTIES portProps) -{ - if (NULL != portProps) - { - portXmlProps->UsbPortProperties = gcnew UsbPortPropertiesType(); - - portXmlProps->ConnectionIndex = portProps->ConnectionIndex; - portXmlProps->ActualLength = portProps->ActualLength; - portXmlProps->CompanionIndex = portProps->CompanionIndex; - portXmlProps->CompanionPortNumber = portProps->CompanionPortNumber; - portXmlProps->CompanionHubSymbolicLinkName = PWCHAR_TO_STRING(portProps->CompanionHubSymbolicLinkName); - - portXmlProps->UsbPortProperties->PortIsUserConnectable = portProps->UsbPortProperties.PortIsUserConnectable? true:false; - portXmlProps->UsbPortProperties->PortIsDebugCapable = portProps->UsbPortProperties.PortIsDebugCapable? true:false; - } - return; -} - -/***************************************************************************** - - XmlAddConnectionInfoV2() - - Adds the V2 connection info structure - *****************************************************************************/ -void XmlAddConnectionInfoV2(NodeConnectionInfoExV2Type ^ connectionXmlInfo, PUSB_NODE_CONNECTION_INFORMATION_EX_V2 connectionInfo) -{ - if (NULL != connectionInfo) - { - connectionXmlInfo->ConnectionIndex = connectionInfo->ConnectionIndex; - connectionXmlInfo->Length = connectionInfo->Length; - - connectionXmlInfo->Usb110Supported = connectionInfo->SupportedUsbProtocols.Usb110? true:false; - connectionXmlInfo->Usb200Supported = connectionInfo->SupportedUsbProtocols.Usb200? true:false; - connectionXmlInfo->Usb300Supported = connectionInfo->SupportedUsbProtocols.Usb300? true:false; - - connectionXmlInfo->DeviceIsOperatingAtSuperSpeedOrHigher = - connectionInfo->Flags.DeviceIsOperatingAtSuperSpeedOrHigher; - - connectionXmlInfo->DeviceIsSuperSpeedCapableOrHigher = - connectionInfo->Flags.DeviceIsSuperSpeedCapableOrHigher; - - connectionXmlInfo->DeviceIsOperatingAtSuperSpeedPlusOrHigher = - connectionInfo->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher; - - connectionXmlInfo->DeviceIsSuperSpeedPlusCapableOrHigher = - connectionInfo->Flags.DeviceIsSuperSpeedPlusCapableOrHigher; - - } - return; -} - -/***************************************************************************** - - XmlAddHubCharacteristics() - - Adds the hub characteristics to the given hub object - *****************************************************************************/ -void XmlAddHubCharacteristics(HubInformationType ^hubI, WORD hubChar) -{ - HubCharacteristicsType ^hubC = nullptr; - - hubI->HubCharacteristics = gcnew HubCharacteristicsType(); - hubC = hubI->HubCharacteristics; - hubC->HubCharacteristicsValue = hubChar; - switch(hubChar & 0x3) - { - case 0x0: - hubC->PowerSwitching = gcnew String("Ganged"); - break; - case 0x1: - hubC->PowerSwitching = gcnew String("Individual"); - break; - case 0x2: - case 0x3: - hubC->PowerSwitching = gcnew String("None"); - break; - default: - hubC->PowerSwitching = gcnew String("Unknown"); - } - - hubC->CompoundDevice = (hubChar & 0x4)? true:false; - - switch(hubChar & 0x18) - { - case 0x0: - hubC->OverCurrentProtection = gcnew String("Global"); - break; - case 0x8: - hubC->OverCurrentProtection = gcnew String("Individual"); - break; - case 0x10: - case 0x18: - hubC->OverCurrentProtection = gcnew String("No protection, bus power only"); - break; - default: - hubC->OverCurrentProtection = gcnew String("Unknown"); - } -} - -/***************************************************************************** - - XmlAddHubNodeInformation() - - Adds the node information to the hub object - *****************************************************************************/ -HRESULT XmlAddHubNodeInformation(HubNodeInformationType ^ni, PUSB_NODE_INFORMATION nodeInfo) -{ - PUSB_HUB_INFORMATION hubInfo = NULL; - - if (NULL == nodeInfo) - { - return E_FAIL; - } - - hubInfo = &(nodeInfo->u.HubInformation); - ni->HubNode = static_cast (nodeInfo->NodeType); - - ni->HubInformation = gcnew HubInformationType(); - ni->HubInformation->IsRootHub = true; - ni->HubInformation->IsBusPowered = hubInfo->HubIsBusPowered? true:false; - - // Add hub characteristics - XmlAddHubCharacteristics(ni->HubInformation, hubInfo->HubDescriptor.wHubCharacteristics); - // Add descriptor - ni->HubInformation->HubDescriptor = gcnew HubDescriptorType(); - XmlAddHubDescriptor(ni->HubInformation->HubDescriptor, &(hubInfo->HubDescriptor)); - - return S_OK; -} - -/***************************************************************************** - - XmlAddHubInformation() - - Adds the node information to the hub object - *****************************************************************************/ -HRESULT XmlAddHubInformationEx(HubInformationExType ^ex, PUSB_HUB_INFORMATION_EX hubInfoEx) -{ - HubDescriptorType ^hubDesc = nullptr; - Hub30DescriptorType ^hub30Desc = nullptr; - - if (NULL == hubInfoEx) - { - return E_FAIL; - } - - ex->HubType = static_cast (hubInfoEx->HubType); - ex->HighestPortNumber = hubInfoEx->HighestPortNumber; - switch(hubInfoEx->HubType) - { - case UsbRootHub: - case Usb20Hub: - ex->HubDescriptor = hubDesc = gcnew HubDescriptorType(); - XmlAddHubDescriptor(hubDesc, &(hubInfoEx->u.UsbHubDescriptor)); - break; - case Usb30Hub: - ex->Hub30Descriptor = hub30Desc = gcnew Hub30DescriptorType(); - XmlAddHub30Descriptor(hub30Desc, &(hubInfoEx->u.Usb30HubDescriptor)); - break; - } - return S_OK; -} - -/***************************************************************************** - - XmlAddHubCapabilitiesEx() - - Adds the hub capabilities information to the hub object - *****************************************************************************/ -HRESULT XmlAddHubCapabilitiesEx(HubCapabilitiesExType ^ex, PUSB_HUB_CAPABILITIES_EX hubCapEx) -{ - if(NULL != hubCapEx) - { - ex->HubIsHighSpeedCapable = hubCapEx->CapabilityFlags.HubIsHighSpeedCapable?true:false; - ex->HubIsHighSpeed = hubCapEx->CapabilityFlags.HubIsHighSpeed?true:false; - ex->HubIsMultiTtCapable = hubCapEx->CapabilityFlags.HubIsMultiTtCapable?true:false; - ex->HubIsMultiTt = hubCapEx->CapabilityFlags.HubIsMultiTt?true:false; - ex->HubIsRoot = hubCapEx->CapabilityFlags.HubIsRoot?true:false; - ex->HubIsArmedWakeOnConnect = hubCapEx->CapabilityFlags.HubIsArmedWakeOnConnect?true:false; - ex->HubIsBusPowered = hubCapEx->CapabilityFlags.HubIsBusPowered?true:false; - } - return S_OK; -} - -/***************************************************************************** - - ExternalHubType ^ AddExternalHub(Object ^parent) - - This routine finds the type of the parent and adds an external hub object to the - parent's list of external hubs. The newly created object is returned - We are using arrays insted of better types of collections becaused the code generated - by xsd.exe does not support other types. - *****************************************************************************/ -ExternalHubType ^ AddExternalHub(Object ^parent) -{ - RootHubType ^ rhParent = nullptr; - ExternalHubType ^ ehParent = nullptr; - array ^ exHubArray = nullptr; - ExternalHubType ^ exHub = nullptr; - boolean arrayCreated = false; - - // An external hub can be connected to a Root Hub or another External Hub - // We need to determine the type of the object. - - // Try root hub first - - rhParent = dynamic_cast (parent); - if (rhParent == nullptr) - { - // RootHub cast was not successfult, try external hub - ehParent = dynamic_cast (parent); - if (ehParent != nullptr) - { - // External hub parent - if (ehParent->ExternalHub == nullptr) - { - // First hub in the list of external hubs - ehParent->ExternalHub = gcnew array (1); - arrayCreated = true; - } - exHubArray = ehParent->ExternalHub; - } - - } - else - { - // Parent is a root hub - if (rhParent->ExternalHub == nullptr) - { - // First hub in root hub list - rhParent->ExternalHub = gcnew array(1); - arrayCreated = true; - } - exHubArray = rhParent->ExternalHub; - } - - if (exHubArray != nullptr) - { - if (arrayCreated) - { - // We created the array in this function, so we use offset 0 - exHubArray[0] = gcnew ExternalHubType(); - exHub = exHubArray[0]; - } - else - { - // The array was already present, we need to do elaborate things - // as array.resize does not work. - ArrayList ^exList = gcnew ArrayList(); - exList->AddRange(exHubArray); - exHub = gcnew ExternalHubType(); - exList->Add(exHub); - - if (rhParent != nullptr) - { - rhParent->ExternalHub = reinterpret_cast^> (exList->ToArray(ExternalHubType::typeid)); - } - else - { - ehParent->ExternalHub = reinterpret_cast^> (exList->ToArray(ExternalHubType::typeid)); - } - } - } - return exHub; -} -/***************************************************************************** - - NoDeviceType ^ AddDisconnectedPort(Object ^parent) - - This routine finds the type of the parent and adds a empty port connection object to the - parent's list of devices. The newly created object is returned - We are using arrays insted of better types of collections becaused the code generated - by xsd.exe does not support other types. - *****************************************************************************/ -NoDeviceType ^ AddDisconnectedPort(Object ^parent) -{ - RootHubType ^ rhParent = nullptr; - ExternalHubType ^ ehParent = nullptr; - array ^ devicesArray = nullptr; - NoDeviceType ^ noD = nullptr; - boolean arrayCreated = false; - - // An external hub can be connected to a Root Hub or another External Hub - // We need to determine the type of the object. - - // Try RH first - - rhParent = dynamic_cast (parent); - if (rhParent == nullptr) - { - // RootHub cast was not successfult, try external hub - ehParent = dynamic_cast (parent); - if (ehParent != nullptr) - { - // External hub parent - if (ehParent->NoDevice == nullptr) - { - // First hub in the list of external hubs - ehParent->NoDevice = gcnew array (1); - arrayCreated = true; - } - devicesArray = ehParent->NoDevice; - } - - } - else - { - // Parent is a root hub - if (rhParent->NoDevice == nullptr) - { - // First hub in root hub list - rhParent->NoDevice = gcnew array(1); - arrayCreated = true; - } - devicesArray = rhParent->NoDevice; - } - - if (devicesArray != nullptr) - { - if (arrayCreated) - { - // We created the array in this function, so we use offset 0 - devicesArray[0] = gcnew NoDeviceType(); - noD = devicesArray[0]; - } - else - { - // The array was already present, we need to do elaborate things - // as array.resize does not work. - ArrayList ^exList = gcnew ArrayList(); - exList->AddRange(devicesArray); - noD = gcnew NoDeviceType(); - exList->Add(noD); - - if (rhParent != nullptr) - { - rhParent->NoDevice = reinterpret_cast^> (exList->ToArray(NoDeviceType::typeid)); - } - else - { - ehParent->NoDevice = reinterpret_cast^> (exList->ToArray(NoDeviceType::typeid)); - } - } - } - return noD; -} - -/***************************************************************************** - - UsbDeviceType ^ AddUsbDevice(Object ^parent) - - This routine finds the type of the parent and adds a port connection object to the - parent's list of port connectors. The newly created object is returned - We are using arrays insted of better types of collections becaused the code generated - by xsd.exe does not support other types. - *****************************************************************************/ -UsbDeviceType ^ AddUsbDevice(Object ^parent) -{ - RootHubType ^ rhParent = nullptr; - ExternalHubType ^ ehParent = nullptr; - array ^ devicesArray = nullptr; - UsbDeviceType ^ usbD = nullptr; - boolean arrayCreated = false; - - // An external hub can be connected to a Root Hub or another External Hub - // We need to determine the type of the object. - - // Try RH first - - rhParent = dynamic_cast (parent); - if (rhParent == nullptr) - { - // RootHub cast was not successfult, try external hub - ehParent = dynamic_cast (parent); - if (ehParent != nullptr) - { - // External hub parent - if (ehParent->UsbDevice == nullptr) - { - // First hub in the list of external hubs - ehParent->UsbDevice = gcnew array (1); - arrayCreated = true; - } - devicesArray = ehParent->UsbDevice; - } - - } - else - { - // Parent is a root hub - if (rhParent->UsbDevice == nullptr) - { - // First hub in root hub list - rhParent->UsbDevice = gcnew array(1); - arrayCreated = true; - } - devicesArray = rhParent->UsbDevice; - } - - if (devicesArray != nullptr) - { - if (arrayCreated) - { - // We created the array in this function, so we use offset 0 - devicesArray[0] = gcnew UsbDeviceType(); - usbD = devicesArray[0]; - } - else - { - // The array was already present, we need to do elaborate things - // as array.resize does not work. - ArrayList ^exList = gcnew ArrayList(); - exList->AddRange(devicesArray); - usbD = gcnew UsbDeviceType(); - exList->Add(usbD); - - if (rhParent != nullptr) - { - rhParent->UsbDevice = reinterpret_cast^> (exList->ToArray(UsbDeviceType::typeid)); - } - else - { - ehParent->UsbDevice = reinterpret_cast^> (exList->ToArray(UsbDeviceType::typeid)); - } - } - } - return usbD; -} - -/***************************************************************************** - - XmlAddIADDescriptor() - - This routine adds usb IAD descriptor - *****************************************************************************/ -void XmlAddIADDescriptor( - UsbDeviceIADDescriptorType ^ iadXmlDesc, - PUSB_IAD_DESCRIPTOR iadDesc, - PSTRING_DESCRIPTOR_NODE stringDesc, - int nInterfaces) -{ - if (NULL == iadDesc || NULL == stringDesc) - { - return; - } - - // Update structure fields - iadXmlDesc->BLength = iadDesc->bLength; - iadXmlDesc->BDescriptorType = iadDesc->bDescriptorType; - iadXmlDesc->BFirstInterface = iadDesc->bFirstInterface; - iadXmlDesc->BInterfaceCount = iadDesc->bInterfaceCount; - iadXmlDesc->BFunctionClass = iadDesc->bFunctionClass; - iadXmlDesc->BFunctionSubclass = iadDesc->bFunctionSubClass; - iadXmlDesc->BFunctionProtocol = iadDesc->bFunctionProtocol; - iadXmlDesc->IFunction = iadDesc->iFunction; - - // Validate fields - if (iadDesc->bInterfaceCount == 1) - { - iadXmlDesc->InterfaceError = gcnew String("ERROR: bInterfaceCount must be greater than 1"); - } - if (nInterfaces < iadDesc->bFirstInterface + iadDesc->bInterfaceCount) - { - iadXmlDesc->InterfaceError = gcnew String("ERROR: The total number of interfaces"); - iadXmlDesc->InterfaceError += nInterfaces; - iadXmlDesc->InterfaceError += " must be greater than or equal to the highest linked interface number (base "; - iadXmlDesc->InterfaceError += iadDesc->bFirstInterface; - iadXmlDesc->InterfaceError += " + count "; - iadXmlDesc->InterfaceError += iadDesc->bInterfaceCount; - iadXmlDesc->InterfaceError += " = "; - iadXmlDesc->InterfaceError += (iadDesc->bFirstInterface + iadDesc->bInterfaceCount); - iadXmlDesc->InterfaceError += " )"; - } - if (iadDesc->bFunctionClass == 0) - { - iadXmlDesc->FunctionClassError = gcnew String("ERROR: bFunctionClass contains an illegal value 0"); - } - - iadXmlDesc->FunctionDetails = XmlGetDeviceClass( - iadDesc->bFunctionClass, - iadDesc->bFunctionSubClass, - iadDesc->bFunctionProtocol); - - // Protocol check - if (iadDesc->bFunctionClass == USB_DEVICE_CLASS_VIDEO) - { - if (iadDesc->bFunctionProtocol != PC_PROTOCOL_UNDEFINED) - { - iadXmlDesc->Protocol= gcnew String("WARNING: Protocol must be set to PC_PROTOCOL_UNDEFINED"); - iadXmlDesc->Protocol+= " for this class but is set to: "; - iadXmlDesc->Protocol+= iadDesc->bFunctionProtocol; - } - else - { - iadXmlDesc->Protocol = gcnew String("PC_PROTOCOL_UNDEFINED protocol"); - } - } - - if (iadDesc->iFunction) - { - // Add String descriptor - iadXmlDesc->StringDesc = XmlGetStringDescriptor( - iadDesc->iFunction, - stringDesc, - false); - } - - return; -} - -/***************************************************************************** - - XmlAddOTGDescriptor() - - This routine adds usb OTG descriptor - *****************************************************************************/ -void XmlAddOTGDescriptor( - UsbDeviceOTGDescriptorType ^ otgXmlDesc, - PUSB_OTG_DESCRIPTOR otgDesc) -{ - if (NULL == otgDesc) - { - return; - } - - otgXmlDesc->BLength = otgDesc->bLength; - otgXmlDesc->BDescriptorType = otgDesc->bDescriptorType; - otgXmlDesc->BmAttributes = otgDesc->bmAttributes; - - // Add descriptive fields - switch (otgDesc->bmAttributes) - { - case 0: - break; - case 1: - otgXmlDesc->AttributesString = gcnew String("SRP support"); - break; - case 2: - otgXmlDesc->AttributesString = gcnew String("HNP support"); - break; - case 3: - otgXmlDesc->AttributesString = gcnew String("SRP and HNP support"); - break; - default: - otgXmlDesc->AttributesString = gcnew String("ERROR: bmAttributes bits 2-7 are reserved should be 0)"); - break; - } - return; -} - -/***************************************************************************** - - XmlAddHidDescriptor() - - This routine adds usb HID descriptor - *****************************************************************************/ -void XmlAddHidDescriptor( - UsbDeviceHidDescriptorType ^ hidXmlDesc, - PUSB_HID_DESCRIPTOR hidDesc - ) -{ - int i = 0; - - if (NULL == hidDesc) - { - return; - } - - hidXmlDesc->BLength = hidDesc->bLength; - hidXmlDesc->BDescriptorType = hidDesc->bDescriptorType; - hidXmlDesc->BcdHID = hidDesc->bcdHID; - hidXmlDesc->BCountryCode = hidDesc->bCountryCode; - hidXmlDesc->BNumDescriptors = hidDesc->bNumDescriptors; - - // Add optional descriptors - if (hidDesc->bNumDescriptors > 0) - { - hidXmlDesc->OptionalDescriptor = gcnew array (hidDesc->bNumDescriptors); - for(i=0; i < hidDesc->bNumDescriptors; i++) - { - hidXmlDesc->OptionalDescriptor[i] = gcnew UsbDeviceHidOptionalDescriptorsType(); - hidXmlDesc->OptionalDescriptor[i]->BDescriptorType = hidDesc->OptionalDescriptors[i].bDescriptorType; - hidXmlDesc->OptionalDescriptor[i]->WDescriptorLength = hidDesc->OptionalDescriptors[i].wDescriptorLength; - } - } - return; -} - -/***************************************************************************** - - XmlGetUnknownDescriptor() - - This routine gets a usb unknown descriptor object form unknown descriptor - *****************************************************************************/ -UsbDeviceUnknownDescriptorType ^ XmlGetUnknownDescriptor( - PUSB_COMMON_DESCRIPTOR unknownDesc - ) -{ - int i = 0; - UsbDeviceUnknownDescriptorType ^ unknownXmlDesc = nullptr; - - if (NULL == unknownDesc) - { - return nullptr; - } - - unknownXmlDesc = gcnew UsbDeviceUnknownDescriptorType(); - unknownXmlDesc->BLength = unknownDesc->bLength; - unknownXmlDesc->BDescriptorType = unknownDesc->bDescriptorType; - - // Add optional descriptors - if (unknownDesc->bLength > 0) - { - unknownXmlDesc->UnknownDescriptor = gcnew String("Unknown descriptor->"); - for(i=0; i < unknownDesc->bLength; i++) - { - unknownXmlDesc->UnknownDescriptor += String::Format("0x{0:X} ", ((PUCHAR) unknownDesc)[i]); - } - } - return unknownXmlDesc; -} - -/***************************************************************************** - - XmlAddEndpointDescriptor() - - This routine adds usb endpoint descriptor and verbose fields - *****************************************************************************/ -void XmlAddEndpointDescriptor( - EndpointDescriptorType ^usbXmlEndpointDescriptor, - PUSB_ENDPOINT_DESCRIPTOR endPointDescriptor, - UCHAR connectionSpeed - ) -{ - EndpointDescriptorType ^ue = usbXmlEndpointDescriptor; - ULONG maxBytes = endPointDescriptor->wMaxPacketSize & 0x7FF; - - // Add structure values - ue->Length = endPointDescriptor->bLength; - ue->DescriptorType = endPointDescriptor->bDescriptorType; - ue->EndpointAddress = endPointDescriptor->bEndpointAddress; - ue->Attributes = endPointDescriptor->bmAttributes; - ue->MaxPacketSize = endPointDescriptor->wMaxPacketSize; - - // Add verbose fields - ue->EndpointId = endPointDescriptor->bEndpointAddress & 0x0F; - - // Add endpoint direction - if (USB_ENDPOINT_DIRECTION_OUT(endPointDescriptor->bEndpointAddress)) - { - ue->EndpointDirection = gcnew String("Out"); - } - else if (USB_ENDPOINT_DIRECTION_IN(endPointDescriptor->bEndpointAddress)) - { - ue->EndpointDirection = gcnew String("In"); - } - - // Add endpoint type - switch (endPointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) - { - case USB_ENDPOINT_TYPE_CONTROL: - ue->EndpointType = gcnew String("Control Transfer Type"); - break; - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - switch (endPointDescriptor->bmAttributes & 0x0C) - { - case 0x00: - ue->EndpointType = gcnew String("Ischronous Transfer Type - No Synchronization"); - break; - - case 0x04: - ue->EndpointType = gcnew String("Ischronous Transfer Type - Asynchronous"); - break; - - case 0x08: - ue->EndpointType = gcnew String("Ischronous Transfer Type - Adaptive"); - break; - - case 0x0C: - ue->EndpointType = gcnew String("Ischronous Transfer Type - Synchronous"); - break; - } - break; - case USB_ENDPOINT_TYPE_BULK: - ue->EndpointType = gcnew String("Bulk Transfer Type"); - break; - - case USB_ENDPOINT_TYPE_INTERRUPT: - ue->EndpointType = gcnew String("Interrupt Transfer Type"); - break; - } - - // Add packet info - switch (connectionSpeed) - { - case UsbHighSpeed: - if (endPointDescriptor->bmAttributes & 1) { - ULONG transactions = ((endPointDescriptor->wMaxPacketSize & 0x1800) >> 11) + 1; - // Isoc or Interrupt endpoint - ue->EndpointPacketInfo = gcnew String( - transactions + " transactions per microframe, " + - maxBytes + " max bytes"); - } - else - { - // Bulk endpoint - ue->EndpointPacketInfo = gcnew String(maxBytes + " max bytes"); - } - break; - case UsbFullSpeed: - ue->EndpointPacketInfo = gcnew String(maxBytes + " max bytes"); - break; - default: - // Low or Invalid speed - ue->EndpointPacketInfo = gcnew String("Invalid bus speed"); - break; - } - - // Add validation - if (endPointDescriptor->wMaxPacketSize & 0xE000) - { - ue->EndpointPacketSizeValidation = gcnew String("ERROR: wMaxPacketSize bits 15-13 should be 0"); - } else if (connectionSpeed==UsbHighSpeed) - { - USHORT hsMux; - - hsMux = (endPointDescriptor->wMaxPacketSize >> 11) & 0x03; - - switch (endPointDescriptor->bmAttributes & USB_ENDPOINT_TYPE_MASK) - { - case USB_ENDPOINT_TYPE_ISOCHRONOUS: - case USB_ENDPOINT_TYPE_INTERRUPT: - switch (hsMux) { - case 0: - if ((maxBytes < 1) || (maxBytes > 1024)) - { - ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 1 and 1024"); - } - break; - - case 1: - if ((maxBytes < 513) || (maxBytes > 1024)) - { - ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 513 and 1024"); - } - break; - - case 2: - if ((maxBytes < 683) || (maxBytes > 1024)) - { - ue->EndpointPacketSizeValidation = gcnew String("ERROR: Invalid maximum packet size, should be between 683 and 1024"); - } - break; - - case 3: - ue->EndpointPacketSizeValidation = gcnew String("ERROR: Bits 12-11 set to reserved value\r\n"); - break; - } - } - } - - // Add interval - if (endPointDescriptor->bLength == sizeof(USB_ENDPOINT_DESCRIPTOR)) - { - ue->Interval = endPointDescriptor->bInterval; - } - else - { - PUSB_ENDPOINT_DESCRIPTOR2 endpointDesc2 = (PUSB_ENDPOINT_DESCRIPTOR2) endPointDescriptor; - ue->WInterval = endpointDesc2->wInterval; - ue->SyncAddress = endpointDesc2->bSyncAddress; - } - return; -} - -/***************************************************************************** - - XmlAddPipeInformation() - - This routine adds all the pipe information for device - *****************************************************************************/ -void XmlAddPipeInformation( - array< UsbPipeInfoType ^> ^ usbXmlPipeInfoList, - PUSB_PIPE_INFO pipeInfo, - ULONG numPipes, - UCHAR connectionSpeed - ) -{ - ULONG i = 0; - - for(i = 0; i< numPipes; i++) - { - // Add all pipe in the list - usbXmlPipeInfoList[i] = gcnew UsbPipeInfoType(); - usbXmlPipeInfoList[i]->EndpointDescriptor = gcnew EndpointDescriptorType(); - XmlAddEndpointDescriptor( - usbXmlPipeInfoList[i]->EndpointDescriptor, - &pipeInfo[i].EndpointDescriptor, - connectionSpeed); - usbXmlPipeInfoList[i]->ScheduleOffset = pipeInfo->ScheduleOffset; - } - return; -} - -/***************************************************************************** - - XmlAddUsbDeviceDescriptor() - - This routine adds usb device descriptor - *****************************************************************************/ -void XmlAddUsbDeviceDescriptor( - UsbDeviceDescriptorType ^usbXmlDeviceDescriptor, - PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor) -{ - UsbDeviceDescriptorType ^ud = usbXmlDeviceDescriptor; - - // Map all fields explicitly - - ud->Length = usbDeviceDescriptor->bLength; - ud->DescriptorType = usbDeviceDescriptor->bDescriptorType; - ud->CdUSB= usbDeviceDescriptor->bcdUSB; - ud->DeviceClass = usbDeviceDescriptor->bDeviceClass; - ud->DeviceSubclass = usbDeviceDescriptor->bDeviceSubClass; - ud->DeviceProtocol = usbDeviceDescriptor->bDeviceProtocol; - ud->MaxPacketSize0 = usbDeviceDescriptor->bMaxPacketSize0; - ud->IdVendor = usbDeviceDescriptor->idVendor; - ud->IdProduct = usbDeviceDescriptor->idProduct ; - ud->CdDevice = usbDeviceDescriptor->bcdDevice; - ud->IManufacturer = usbDeviceDescriptor->iManufacturer; - ud->IProduct = usbDeviceDescriptor->iProduct; - ud->ISerialNumber = usbDeviceDescriptor->iSerialNumber; - ud->NumConfigurations = usbDeviceDescriptor->bNumConfigurations; - return; -} - -/***************************************************************************** - - XmlAddConfigurationDescriptor() - - This routine adds the configuration descriptor - *****************************************************************************/ -void XmlAddConfigurationDescriptor( - UsbConfigurationDescriptorType ^ confXmlDesc, - PUSBDEVICEINFO deviceInfo, - PUSB_CONFIGURATION_DESCRIPTOR configDesc, - PSTRING_DESCRIPTOR_NODE stringDesc - ) - -{ - UINT uCount = 0; - BOOL isSuperSpeed = FALSE; - - if (NULL == configDesc || NULL == deviceInfo) - { - return; - } - - if(deviceInfo->ConnectionInfoV2 && - (deviceInfo->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedOrHigher || - deviceInfo->ConnectionInfoV2->Flags.DeviceIsOperatingAtSuperSpeedPlusOrHigher)) - { - isSuperSpeed = TRUE; - } - - confXmlDesc->BLength = configDesc->bLength; - confXmlDesc->BDescriptorType = configDesc->bDescriptorType; - confXmlDesc->WTotalLength = configDesc->wTotalLength; - confXmlDesc->BNumInterfaces = configDesc->bNumInterfaces; - confXmlDesc->BConfigurationValue = configDesc->bConfigurationValue; - confXmlDesc->IConfiguration = configDesc->iConfiguration; - confXmlDesc->BmAttributes = configDesc->bmAttributes; - confXmlDesc->MaxPower = configDesc->MaxPower; - - uCount = GetConfigurationSize(deviceInfo); - - if (uCount != configDesc->wTotalLength) - { - confXmlDesc->ConfigDescError = gcnew String("ERROR: Invalid total configuration size " + - configDesc->wTotalLength + ", should be " + uCount); - } - - if (configDesc->bConfigurationValue != 1) - { - confXmlDesc->ConfValueError = gcnew String("CAUTION: Most host controllers will only work with one configuration per speed"); - } - - if (configDesc->iConfiguration) - { - confXmlDesc->ConfStringDesc = XmlGetStringDescriptor( - configDesc->iConfiguration, - stringDesc, - false); - } - - if (configDesc->bmAttributes & USB_CONFIG_BUS_POWERED) - { - confXmlDesc->AttributesStr = gcnew String("Bus Powered"); - } - else if (configDesc->bmAttributes & USB_CONFIG_SELF_POWERED) - { - confXmlDesc->AttributesStr = gcnew String("Self Powered"); - } - else if (configDesc->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) - { - confXmlDesc->AttributesStr = gcnew String("Remote Wakeup"); - } - else - { - confXmlDesc->AttributesStr = gcnew String("WARNING: bmAttributes is using reserved space"); - } - - confXmlDesc->MaxCurrent = gcnew String(""); - confXmlDesc->MaxCurrent += (isSuperSpeed?configDesc->MaxPower * 8:configDesc->MaxPower * 2); - confXmlDesc->MaxCurrent += " mA"; - - return; -} - -/***************************************************************************** - - XmlGetDeviceClass() - - This routine returns the interface class and subclass for given interface descriptor - *****************************************************************************/ -UsbDeviceClassType ^ XmlGetDeviceClass(UCHAR bInterfaceClass, UCHAR bInterfaceSubclass, UCHAR bInterfaceProtocol) -{ - String ^ deviceClass = nullptr; - String ^ deviceSubclass = nullptr; - UsbDeviceClassType ^ deviceDetails = gcnew UsbDeviceClassType(); - - switch (bInterfaceClass) - { - case USB_DEVICE_CLASS_AUDIO: - deviceClass = gcnew String("Audio Interface"); - - switch (bInterfaceSubclass) - { - case USB_AUDIO_SUBCLASS_AUDIOCONTROL: - deviceSubclass = gcnew String("Audio Control Interface"); - break; - - case USB_AUDIO_SUBCLASS_AUDIOSTREAMING: - deviceSubclass = gcnew String("Audio Streaming Interface"); - break; - - case USB_AUDIO_SUBCLASS_MIDISTREAMING: - deviceSubclass = gcnew String("MIDI Streaming Interface"); - break; - - default: - deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : "); - deviceSubclass += bInterfaceSubclass; - break; - } - break; - - case USB_DEVICE_CLASS_VIDEO: - deviceClass = gcnew String("Video Interface"); - - switch(bInterfaceSubclass) - { - case VIDEO_SUBCLASS_CONTROL: - deviceSubclass = gcnew String("Video Control"); - break; - - case VIDEO_SUBCLASS_STREAMING: - deviceSubclass = gcnew String("Video Streaming"); - break; - - default: - deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : "); - deviceSubclass += bInterfaceSubclass; - break; - } - break; - - case USB_DEVICE_CLASS_VENDOR_SPECIFIC: - deviceClass = gcnew String("Vendor Specific Device"); - break; - - case USB_DEVICE_CLASS_HUMAN_INTERFACE: - - deviceClass = gcnew String("HID Interface"); - break; - - case USB_DEVICE_CLASS_HUB: - deviceClass = gcnew String("HUB Interface"); - break; - - case USB_DEVICE_CLASS_RESERVED: - deviceClass = gcnew String("CAUTION: Reserved USB Device Interface Class"); - break; - - case USB_DEVICE_CLASS_COMMUNICATIONS: - deviceClass = gcnew String("Communications (CDC Control) USB Device\r\n"); - break; - - case USB_DEVICE_CLASS_MONITOR: - deviceClass = gcnew String("Monitor USB Device Interface Class*** (This may be obsolete)"); - break; - - case USB_DEVICE_CLASS_PHYSICAL_INTERFACE: - deviceClass = gcnew String("Physical Interface USB Device"); - break; - - case USB_DEVICE_CLASS_POWER: - if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1) - { - deviceClass = gcnew String("Image USB Device"); - } - else - { - deviceClass = gcnew String("Power USB Device (This may be obsolete)"); - } - break; - - case USB_DEVICE_CLASS_PRINTER: - deviceClass = gcnew String("Printer USB Device"); - break; - - case USB_DEVICE_CLASS_STORAGE: - deviceClass = gcnew String("Mass Storage USB Device"); - break; - - case USB_CDC_DATA_INTERFACE: - deviceClass = gcnew String("CDC Data USB Device"); - break; - - case USB_CHIP_SMART_CARD_INTERFACE: - deviceClass = gcnew String("Chip/Smart Card USB Device"); - break; - - case USB_CONTENT_SECURITY_INTERFACE: - deviceClass = gcnew String("Content Security USB Device"); - break; - - case USB_DIAGNOSTIC_DEVICE_INTERFACE: - if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1) - { - deviceClass = gcnew String("Reprogrammable USB2 Compliance Diagnostic Device USB Device"); - } - else - { - deviceClass = gcnew String("CAUTION: This appears to be an invalid device class: "); - deviceClass += bInterfaceClass; - } - break; - - case USB_WIRELESS_CONTROLLER_INTERFACE: - if (bInterfaceSubclass == 1 && bInterfaceProtocol == 1) - { - deviceClass = gcnew String("Wireless RF Controller USB Device Interface Class with Bluetooth Programming Interface"); - } - else - { - deviceClass = gcnew String("CAUTION: This appears to be an invalid device class: "); - deviceClass += bInterfaceClass; - } - break; - - case USB_APPLICATION_SPECIFIC_INTERFACE: - deviceClass = gcnew String("Application Specific USB Device"); - - switch(bInterfaceSubclass) - { - case 1: - deviceSubclass = gcnew String("Device Firmware Application Specific USB Device"); - break; - case 2: - deviceSubclass = gcnew String("IrDA Bridge Application Specific USB Device"); - break; - case 3: - deviceSubclass = gcnew String("Test & Measurement Class (USBTMC) Application Specific USB Device"); - break; - default: - deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubclass : "); - deviceSubclass += bInterfaceSubclass; - } - break; - case USB_DEVICE_CLASS_BILLBOARD: - deviceClass = gcnew String("Billboard Class"); - switch (bInterfaceSubclass) - { - case 0: - deviceSubclass = gcnew String("Billboard Subclass"); - break; - default: - deviceSubclass = gcnew String("CAUTION: This appears to be an invalid bInterfaceSubClass"); - break; - } - break; - default: - - deviceClass = gcnew String("Interface Class unknown : "); - deviceClass += bInterfaceClass; - break; - } - - // Return class and subclass - - deviceDetails->DeviceClass = deviceClass; - deviceDetails->DeviceSubclass = deviceSubclass; - - return deviceDetails; -} - -/***************************************************************************** - - XmlAddInterfaceDescriptor() - - This routine adds the device interface descriptor - *****************************************************************************/ -void XmlAddDeviceInterfaceDescriptor( - UsbDeviceInterfaceDescriptorType ^ ifXmlDesc, - PUSB_INTERFACE_DESCRIPTOR ifDesc, - PSTRING_DESCRIPTOR_NODE stringDesc) -{ - if (NULL == ifDesc || NULL == stringDesc) - { - return; - } - - // Update structure fields - ifXmlDesc->BLength = ifDesc->bLength; - ifXmlDesc->BDescriptorType = ifDesc->bDescriptorType; - ifXmlDesc->BInterfaceNumber = ifDesc->bInterfaceNumber; - ifXmlDesc->BAlternateSetting = ifDesc->bAlternateSetting; - ifXmlDesc->BNumEndpoints = ifDesc->bNumEndpoints; - ifXmlDesc->BInterfaceClass = ifDesc->bInterfaceClass; - ifXmlDesc->BInterfaceSubclass = ifDesc->bInterfaceSubClass; - ifXmlDesc->BInterfaceProtocol = ifDesc->bInterfaceProtocol; - ifXmlDesc->IInterface = ifDesc->iInterface; - - // Update class and sub class - ifXmlDesc->InterfaceDetails = XmlGetDeviceClass( - ifDesc->bInterfaceClass, - ifDesc->bInterfaceSubClass, - ifDesc->bInterfaceProtocol); - - //This is basically the check for PC_PROTOCOL_UNDEFINED - if ((ifDesc->bInterfaceClass == USB_DEVICE_CLASS_VIDEO) || - (ifDesc->bInterfaceClass == USB_DEVICE_CLASS_AUDIO)) - { - if (ifDesc->bInterfaceProtocol != PC_PROTOCOL_UNDEFINED) - { - ifXmlDesc->ProtocolError = gcnew String("WARNING: Protocol must be set to PC_PROTOCOL_UNDEFINED"); - ifXmlDesc->ProtocolError += " for this class but is set to: "; - ifXmlDesc->ProtocolError += ifDesc->bInterfaceProtocol; - } - } - - if (ifDesc->iInterface) - { - // Add String descriptor - ifXmlDesc->StringDesc = XmlGetStringDescriptor( - ifDesc->iInterface, - stringDesc, - false); - } - - if (ifDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR2)) - { - PUSB_INTERFACE_DESCRIPTOR2 interfaceDesc2; - - interfaceDesc2 = (PUSB_INTERFACE_DESCRIPTOR2)ifDesc; - - ifXmlDesc->WNumClasses = interfaceDesc2->wNumClasses; - } - return; -} - -/***************************************************************************** - - XmlAddDeviceQualDescriptor() - - This routine adds the device qualifier descriptor - *****************************************************************************/ - -void XmlAddDeviceQualDescriptor( - UsbDeviceQualifierDescriptorType ^ qualXmlDesc, - PUSB_DEVICE_QUALIFIER_DESCRIPTOR qualDesc) -{ - if (NULL == qualDesc) - { - return; - } - - // Add structure fields - qualXmlDesc->BLength = qualDesc->bLength; - qualXmlDesc->BDescriptorType = qualDesc->bDescriptorType; - qualXmlDesc->BcdUSB = qualDesc->bcdUSB; - qualXmlDesc->BDeviceClass = qualDesc->bDeviceClass; - qualXmlDesc->BDeviceSubclass = qualDesc->bDeviceSubClass; - qualXmlDesc->BDeviceProtocol = qualDesc->bDeviceProtocol; - qualXmlDesc->BMaxPacketSize0 = qualDesc->bMaxPacketSize0; - qualXmlDesc->NumConfigurations = qualDesc->bNumConfigurations; - - // Get device class string - qualXmlDesc->DeviceClass = XmlGetDeviceClassString(qualDesc->bDeviceClass); - - if (qualDesc->bDeviceSubClass > 0x00 && qualDesc->bDeviceSubClass < 0xFF) - { - qualXmlDesc->DeviceSubclassError = gcnew String("ERROR: bDeviceSubClass is invalid : "); - qualXmlDesc->DeviceSubclassError += qualDesc->bDeviceSubClass; - } - - if (qualDesc->bDeviceProtocol > 0x00 && qualDesc->bDeviceProtocol < 0xFF) - { - qualXmlDesc->DeviceProtocolError = gcnew String("ERROR: bDeviceProtocol is invalid : "); - qualXmlDesc->DeviceProtocolError += qualDesc->bDeviceProtocol; - } - - qualXmlDesc->MaxPacketSizeInBytes = qualDesc->bMaxPacketSize0; - - if (qualDesc->bNumConfigurations != 1) - { - qualXmlDesc->DeviceNumConfigError = gcnew String( - "CAUTION: Most host controllers will only work with one configuration per speed"); - } - - if (qualDesc->bReserved != 0) - { - qualXmlDesc->ReservedError = gcnew String("WARNING: bReserved needs to be set to 0 to be valid - " + - qualDesc->bReserved); - } - - return; -} - -/***************************************************************************** - - XmlAddAddConfigDescriptors() - - This routine adds the all the config descriptors - *****************************************************************************/ -array < UsbDeviceConfigurationType ^> ^ XmlGetConfigDescriptors( - PUSBDEVICEINFO deviceInfo, - PUSB_CONFIGURATION_DESCRIPTOR configDescs, - PSTRING_DESCRIPTOR_NODE stringDesc - ) -{ - array < UsbDeviceConfigurationType ^> ^ confXmlDescs = nullptr; - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - PUCHAR descEnd = NULL; - ArrayList ^confList = gcnew ArrayList; - UsbDeviceConfigurationType ^ deviceConf = nullptr; - - commonDesc = (PUSB_COMMON_DESCRIPTOR) configDescs; - descEnd = (PUCHAR) configDescs + configDescs->wTotalLength; - - while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd && - (PUCHAR)commonDesc + commonDesc->bLength <= descEnd) - { - // Add the config descriptor - deviceConf = gcnew UsbDeviceConfigurationType(); - - XmlAddDeviceConfiguration( - deviceConf, - deviceInfo, - (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc, - stringDesc, - configDescs->bNumInterfaces - ); - - confList->Add(deviceConf); - commonDesc = (PUSB_COMMON_DESCRIPTOR) ((PUCHAR) commonDesc + commonDesc->bLength); - } - - confXmlDescs = reinterpret_cast^> (confList->ToArray(UsbDeviceConfigurationType::typeid)); - return confXmlDescs; -} - -/***************************************************************************** - - XmlAddDeviceConfiguration() - - This routine adds the device configuration - *****************************************************************************/ -void XmlAddDeviceConfiguration( - UsbDeviceConfigurationType ^ confXmlDesc, - PUSBDEVICEINFO deviceInfo, - PUSB_CONFIGURATION_DESCRIPTOR configDesc, - PSTRING_DESCRIPTOR_NODE stringDesc, - int numInterfaces - ) -{ - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - UCHAR bInterfaceClass = 0; - UCHAR bInterfaceSubclass = 0; - UCHAR bInterfaceProtocol = 0; - BOOL displayUnknown = FALSE; - - if (NULL == deviceInfo || NULL == configDesc || NULL == stringDesc) - { - return; - } - - commonDesc = (PUSB_COMMON_DESCRIPTOR)configDesc; - displayUnknown = FALSE; - - switch (commonDesc->bDescriptorType) - { - case USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)) - { - // Validate descriptor - confXmlDesc->DeviceQualifierError = String::Format( - "ERROR: Device Qualifier bLength value incorrect Obtained: {0} Expected {1}", - commonDesc->bLength, - sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR)); - displayUnknown = TRUE; - break; - } - // Add device Qual descriptor - confXmlDesc->DeviceQualifierDescriptor = gcnew UsbDeviceQualifierDescriptorType(); - - XmlAddDeviceQualDescriptor( - confXmlDesc->DeviceQualifierDescriptor, - (PUSB_DEVICE_QUALIFIER_DESCRIPTOR) commonDesc); - break; - - case USB_OTHER_SPEED_CONFIGURATION_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - // Validate descriptor - confXmlDesc->SpeedConfigurationError = String::Format( - "ERROR: Other speed configuration bLength value incorrect Obtained: {0} Expected {1}", - commonDesc->bLength, - sizeof(USB_CONFIGURATION_DESCRIPTOR)); - displayUnknown = TRUE; - } - - // Add configuration desc - confXmlDesc->ConfigurationDescriptor = gcnew UsbConfigurationDescriptorType(); - - XmlAddConfigurationDescriptor( - confXmlDesc->ConfigurationDescriptor, - deviceInfo, - (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc, - stringDesc); - break; - - case USB_CONFIGURATION_DESCRIPTOR_TYPE: - if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR)) - { - // Validate descriptor - confXmlDesc->SpeedConfigurationError = String::Format( - "ERROR: Configuration bLength value incorrect Obtained: {0} Expected {1}", - commonDesc->bLength, - sizeof(USB_CONFIGURATION_DESCRIPTOR)); - displayUnknown = TRUE; - break; - } - - // Add configuration desc - confXmlDesc->ConfigurationDescriptor = gcnew UsbConfigurationDescriptorType(); - XmlAddConfigurationDescriptor( - confXmlDesc->ConfigurationDescriptor, - deviceInfo, - (PUSB_CONFIGURATION_DESCRIPTOR) commonDesc, - stringDesc); - break; - - case USB_INTERFACE_DESCRIPTOR_TYPE: - if ((commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR)) && - (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))) - { - // Validate descriptor - confXmlDesc->InterfaceError = String::Format( - "ERROR: Interface bLength value incorrect Obtained: {0} Expected: {1} or {2}", - commonDesc->bLength, - sizeof(USB_INTERFACE_DESCRIPTOR), - sizeof(USB_INTERFACE_DESCRIPTOR2)); - displayUnknown = TRUE; - break; - } - - // Add interface descriptor - bInterfaceClass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceClass; - bInterfaceSubclass = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceSubClass; - bInterfaceProtocol = ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->bInterfaceProtocol; - - confXmlDesc->InterfaceDescriptor = gcnew UsbDeviceInterfaceDescriptorType(); - XmlAddDeviceInterfaceDescriptor( - confXmlDesc->InterfaceDescriptor, - (PUSB_INTERFACE_DESCRIPTOR) commonDesc, - stringDesc - ); - - case USB_ENDPOINT_DESCRIPTOR_TYPE: - if ((commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR)) && - (commonDesc->bLength != sizeof(USB_ENDPOINT_DESCRIPTOR2))) - { - // Validate endpoint descriptor - confXmlDesc->EndpointError = String::Format( - "ERROR: Endpoint bLength value incorrect Obtained: {0} Expected: {1} or {2}", - commonDesc->bLength, - sizeof(USB_ENDPOINT_DESCRIPTOR), - sizeof(USB_ENDPOINT_DESCRIPTOR2)); - displayUnknown = TRUE; - break; - } - - confXmlDesc->EndpointDescriptor = gcnew EndpointDescriptorType(); - - if (NULL != deviceInfo->ConnectionInfo) - { - // Add endpoint descriptor - XmlAddEndpointDescriptor( - confXmlDesc->EndpointDescriptor, - (PUSB_ENDPOINT_DESCRIPTOR) commonDesc, - deviceInfo->ConnectionInfo->Speed); - } - - break; - - case USB_HID_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_HID_DESCRIPTOR)) - { - // Validate HID - confXmlDesc->HidError = String::Format( - "ERROR: HID bLength value incorrect Obtained: {0} Expected: {1}", - commonDesc->bLength, - sizeof(USB_HID_DESCRIPTOR)); - displayUnknown = TRUE; - break; - } - - // Add HID descriptor - confXmlDesc->HidDescriptor = gcnew UsbDeviceHidDescriptorType(); - XmlAddHidDescriptor( - confXmlDesc->HidDescriptor, - (PUSB_HID_DESCRIPTOR) commonDesc - ); - break; - - case USB_OTG_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_OTG_DESCRIPTOR)) - { - // Validate length - confXmlDesc->HidError = String::Format( - "ERROR: OTG bLength value incorrect Obtained: {0} Expected: {1}", - commonDesc->bLength, - sizeof(USB_OTG_DESCRIPTOR)); - displayUnknown = TRUE; - break; - } - - // Add OTG descriptor - confXmlDesc->OtgDescriptor = gcnew UsbDeviceOTGDescriptorType(); - XmlAddOTGDescriptor( - confXmlDesc->OtgDescriptor, - (PUSB_OTG_DESCRIPTOR) commonDesc - ); - break; - - case USB_IAD_DESCRIPTOR_TYPE: - if (commonDesc->bLength < sizeof(USB_IAD_DESCRIPTOR)) - { - // Validate length - confXmlDesc->IadError = String::Format( - "ERROR: IAD bLength value incorrect", - commonDesc->bLength, - sizeof(USB_OTG_DESCRIPTOR)); - displayUnknown = TRUE; - } - - // Add IAD descriptor - confXmlDesc->IadDescriptor = gcnew UsbDeviceIADDescriptorType(); - XmlAddIADDescriptor( - confXmlDesc->IadDescriptor, - (PUSB_IAD_DESCRIPTOR) commonDesc, - stringDesc, - numInterfaces - ); - break; - - default: - // Interface class device (?) - confXmlDesc->DeviceDetails = XmlGetDeviceClass( - ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceClass, - ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceSubClass, - ((PUSB_INTERFACE_DESCRIPTOR) commonDesc)->bInterfaceProtocol - ); - break; - } - - if (displayUnknown) - { - // Add unknown descriptor - confXmlDesc->UnknownDescriptor = XmlGetUnknownDescriptor(commonDesc); - } - return; -} - -/***************************************************************************** - - XmlAddConnectionInfoSt() - - This routine adds connection information structures for the device - *****************************************************************************/ -void XmlAddConnectionInfoSt( - NodeConnectionInfoExStructType ^xmlConnectionInfoSt, - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, - PDEVICE_INFO_NODE pNode) -{ - NodeConnectionInfoExStructType ^nS = xmlConnectionInfoSt; - - nS->ConnectionIndex = connectionInfo->ConnectionIndex; - - nS->DeviceDescriptor = gcnew UsbDeviceDescriptorType(); - - XmlAddUsbDeviceDescriptor(nS->DeviceDescriptor, &(connectionInfo->DeviceDescriptor)); - - nS->CurrentConfigurationValue = connectionInfo->CurrentConfigurationValue; - nS->Speed = connectionInfo->Speed; - nS->SpeedStr = static_cast (connectionInfo->Speed); - nS->DeviceIsHub = connectionInfo->DeviceIsHub? true: false; - nS->NumOfOpenPipes = connectionInfo->NumberOfOpenPipes; - nS->UsbConnectionStatus = static_cast (connectionInfo->ConnectionStatus); - - if(NULL != pNode) - { - nS->DevicePowerState = static_cast(pNode->LatestDevicePowerState); - } - else - { - nS->DevicePowerState = static_cast(PowerDeviceUnspecified); - } - - // Add the pipe list - if (connectionInfo->NumberOfOpenPipes > 0) - { - nS->Pipe = gcnew array (connectionInfo->NumberOfOpenPipes); - XmlAddPipeInformation( - nS->Pipe, - connectionInfo->PipeList, - connectionInfo->NumberOfOpenPipes, - connectionInfo->Speed - ); - } - - return; -} - -/***************************************************************************** - - XmlGetLangIdString() - - Obtains the language string for given string descriptor index - *****************************************************************************/ -String ^ XmlGetLangIdString(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc) -{ - String ^langIdStr = nullptr; - bool foundDescriptor = false; - - while(stringDesc) - { - if (stringDesc->DescriptorIndex == index) - { - langIdStr = PACHAR_TO_STRING(GetLangIDString(stringDesc->LanguageID)); - - if (langIdStr == nullptr) - { - langIdStr = gcnew String("WARNING: Invalid language ID: " + stringDesc->LanguageID); - } - foundDescriptor = true; - break; - } - stringDesc = stringDesc->Next; - } - - if (foundDescriptor == false) - { - // If no descriptor was found, return error message in field - langIdStr = gcnew String("ERROR: No String descriptor for index " + index); - } - - return langIdStr; -} - -/***************************************************************************** - - XmlGetStringDescriptor() - - Obtains the string descriptor for given string descriptor index - *****************************************************************************/ - -String ^ XmlGetStringDescriptor(UCHAR index, PSTRING_DESCRIPTOR_NODE stringDesc, bool enOnly) -{ - ULONG nBytes = 0; - - CHAR pString[MAX_STRING_DESCRIPTOR_LENGTH]; - String ^desc = nullptr; - bool foundDescriptor = false; - bool foundNonEnglishDescriptor = false; - - ZeroMemory(pString, MAX_STRING_DESCRIPTOR_LENGTH); - - while(stringDesc) - { - if (stringDesc->DescriptorIndex == index) - { - if (enOnly && stringDesc->LanguageID != STRING_DESCRIPTOR_EN_LANGUAGE_ID) - { - // If we are required to return only english descriptor, continue - foundNonEnglishDescriptor = true; - continue; - } - - nBytes = WideCharToMultiByte( - CP_ACP, - WC_NO_BEST_FIT_CHARS, - stringDesc->StringDescriptor->bString, - (stringDesc->StringDescriptor->bLength -2)/2, - pString, - MAX_STRING_DESCRIPTOR_LENGTH, - NULL, - NULL - ); - - if (nBytes) - { - foundDescriptor = true; - desc = PACHAR_TO_STRING(pString); - } - break; - } - stringDesc = stringDesc->Next; - } - - if ((foundDescriptor == false) && (foundNonEnglishDescriptor == false)) - { - // If no descriptor was found, return error message in field - desc = gcnew String("ERROR: No String descriptor for index " + - index); - } - else if ((foundDescriptor == false) && (foundNonEnglishDescriptor == true) && (enOnly)) - { - desc = gcnew String("ERROR: The index " + index + " does not support English(US)"); - } - - return desc; -} - -/***************************************************************************** - - XmlGetDeviceClassString() - - Returns the device class string for given device class ID - *****************************************************************************/ - -String ^ XmlGetDeviceClassString(UCHAR deviceClass) -{ - String ^ deviceClassStr = nullptr; - - // Not an IAD device - switch (deviceClass) - { - case USB_INTERFACE_CLASS_DEVICE: - deviceClassStr = gcnew String("Interface Class Defined Device"); - break; - - case USB_COMMUNICATION_DEVICE: - deviceClassStr = gcnew String("Communication Device"); - break; - - case USB_HUB_DEVICE: - deviceClassStr = gcnew String("Hub Device"); - break; - - case USB_DIAGNOSTIC_DEVICE: - deviceClassStr = gcnew String("Diagnostic Device"); - break; - - case USB_WIRELESS_CONTROLLER_DEVICE: - deviceClassStr = gcnew String("Wireless Controller(Bluetooth) Device"); - break; - - case USB_VENDOR_SPECIFIC_DEVICE: - deviceClassStr = gcnew String("Vendor specific device"); - break; - - case USB_DEVICE_CLASS_BILLBOARD: - deviceClassStr = gcnew String("Billboard class device"); - break; - - default: - deviceClassStr= gcnew String("ERROR: unknown bDeviceClass" + deviceClass); - break; - } - return deviceClassStr; -} - - -/***************************************************************************** - - XmlAddDeviceClassDetails() - - This routine adds device class details - *****************************************************************************/ -bool XmlAddDeviceClassDetails( - UsbDeviceClassDetailsType ^ deviceDetails, - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, - PUSBDEVICEINFO deviceInfo) -{ - UINT uIADcount = 0; - bool tog = true; - - uIADcount = IsIADDevice((PUSBDEVICEINFO) deviceInfo); - - if (uIADcount) - { - // IAD device, check validity of device class - if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE) - { - tog = false; - deviceDetails->DeviceType = gcnew String("Multi-interface Function Code Device"); - } - else { - deviceDetails->DeviceTypeError = gcnew String("ERROR: device class should be Multi-interface Function " + - USB_MISCELLANEOUS_DEVICE + - "is used"); - } - deviceDetails->UvcVersion = IsUVCDevice((PUSBDEVICEINFO) deviceInfo); - - // This device configuration has 1 or more IAD descriptors - if (connectionInfo->DeviceDescriptor.bDeviceSubClass == USB_COMMON_SUB_CLASS) - { - deviceDetails->SubclassType = gcnew String("Common Class Sub Class"); - } - else - { - deviceDetails->SubclassTypeError = gcnew String("ERROR: device SubClass should be USB Common Sub Class" + - USB_COMMON_SUB_CLASS + - " when IAD descriptor is used"); - } - - // Check device protocol - if (connectionInfo->DeviceDescriptor.bDeviceProtocol == USB_IAD_PROTOCOL) - { - deviceDetails->DeviceProtocol = gcnew String("Interface Association Descriptor protocol"); - } - else - { - deviceDetails->DeviceProtocolError = gcnew String("ERROR: device Protocol should be USB IAD Protocol " + - USB_IAD_PROTOCOL + - " when IAD descriptor is used"); - } - - } - else - { - deviceDetails->DeviceType = XmlGetDeviceClassString(connectionInfo->DeviceDescriptor.bDeviceClass); - - if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_DEVICE_CLASS_BILLBOARD && - (connectionInfo->DeviceDescriptor.bDeviceSubClass != 0x0 || - connectionInfo->DeviceDescriptor.bDeviceProtocol != 0x0)) - { - deviceDetails->DeviceTypeError = gcnew String("ERROR: Billboard device has invalid bDeviceSubclass/bDeviceProtocol"); - } - - if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE) - { - deviceDetails->DeviceTypeError = gcnew String("ERROR: Multi-interface Function code " + - connectionInfo->DeviceDescriptor.bDeviceClass + - " used for device with no IAD descriptors"); - } - - if (connectionInfo->DeviceDescriptor.bDeviceClass == USB_COMMUNICATION_DEVICE || - connectionInfo->DeviceDescriptor.bDeviceClass == USB_HUB_DEVICE || - connectionInfo->DeviceDescriptor.bDeviceClass == USB_DIAGNOSTIC_DEVICE || - connectionInfo->DeviceDescriptor.bDeviceClass == USB_WIRELESS_CONTROLLER_DEVICE || - connectionInfo->DeviceDescriptor.bDeviceClass == USB_MISCELLANEOUS_DEVICE || - connectionInfo->DeviceDescriptor.bDeviceClass == USB_VENDOR_SPECIFIC_DEVICE) - { - tog = false; - } - - // Not an IAD device, so all subclass values are invalid - if (connectionInfo->DeviceDescriptor.bDeviceSubClass > 0x00 && - connectionInfo->DeviceDescriptor.bDeviceSubClass < 0xFF) - { - deviceDetails->SubclassTypeError = gcnew String("ERROR: bDeviceSubClass is invalid - " + - connectionInfo->DeviceDescriptor.bDeviceSubClass); - } - - // Not an IAD device, so all subclass values are invalid, check protocol - if (connectionInfo->DeviceDescriptor.bDeviceProtocol > 0x00 && - connectionInfo->DeviceDescriptor.bDeviceProtocol < 0xFF && tog==1) - { - deviceDetails->DeviceProtocolError = gcnew String("ERROR: bDeviceProtocol is invalid - " + - connectionInfo->DeviceDescriptor.bDeviceProtocol); - } - } - - return tog; -} - -/***************************************************************************** - - XmlAddConnectionInfo() - - This routine adds connection information for the device - *****************************************************************************/ -void XmlAddConnectionInfo( - NodeConnectionInfoExType ^xmlConnectionInfo, - PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo, - PUSBDEVICEINFO deviceInfo, - PSTRING_DESCRIPTOR_NODE stringDesc, - PDEVICE_INFO_NODE pNode) -{ - NodeConnectionInfoExType ^ nc = xmlConnectionInfo; - bool tog = true; - nc->ConnectionInfoStruct = gcnew NodeConnectionInfoExStructType(); - - // Update the structure - XmlAddConnectionInfoSt(nc->ConnectionInfoStruct, connectionInfo, pNode); - - // Add verbose fields - if (connectionInfo->ConnectionStatus == NoDeviceConnected) - { - // No device connected, nothing to do - return; - } - - if (connectionInfo->DeviceDescriptor.iProduct) - { - // Add EN version of string descriptor - - nc->IProductStringDescEn = XmlGetStringDescriptor( - connectionInfo->DeviceDescriptor.iProduct, - stringDesc, - true); - } - - // Check open pipes count - if (connectionInfo->NumberOfOpenPipes == 0) - { - nc->PipeInfoError = gcnew String("ERROR: No open pipes"); - } - - // Check device descriptor length - if (connectionInfo->DeviceDescriptor.bLength != DEVICE_DESCRIPTOR_LENGTH) - { - nc->LengthError = gcnew String("ERROR: bLength " + - connectionInfo->DeviceDescriptor.bLength + - " incorrect, should be " + - DEVICE_DESCRIPTOR_LENGTH - ); - } - - // Check for device error - if ((connectionInfo->ConnectionStatus == DeviceFailedEnumeration) || - (connectionInfo->ConnectionStatus == DeviceGeneralFailure)) - { - nc->DeviceError = gcnew String("ERROR: Device enumeration failure"); - } - else - { - nc->DeviceClassDetails = gcnew UsbDeviceClassDetailsType(); - - // Add device class details - tog = XmlAddDeviceClassDetails( - nc->DeviceClassDetails, - connectionInfo, - deviceInfo); - - nc->MaxPacketSizeInBytes = connectionInfo->DeviceDescriptor.bMaxPacketSize0; - - // Validate speed - switch (connectionInfo->Speed) - { - case UsbLowSpeed: - if (connectionInfo->DeviceDescriptor.bMaxPacketSize0 != 8) - { - nc->PacketSizeError = gcnew String("ERROR: Low Speed Devices require bMaxPacketSize0 = 8"); - } - break; - case UsbFullSpeed: - if (!(connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 8 || - connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 16 || - connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 32 || - connectionInfo->DeviceDescriptor.bMaxPacketSize0 == 64)) - { - nc->PacketSizeError = gcnew String("ERROR: Full Speed Devices require bMaxPacketSize0 = 8, 16, 32, or 64"); - } - break; - case UsbHighSpeed: - if (connectionInfo->DeviceDescriptor.bMaxPacketSize0 != 64) - { - nc->PacketSizeError = gcnew String("ERROR: High Speed Devices require bMaxPacketSize0 = 64"); - } - break; - } - - // Get string descriptors - nc->VendorString = PACHAR_TO_STRING(GetVendorString(connectionInfo->DeviceDescriptor.idVendor)); - - nc->ManufacturerString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iManufacturer, stringDesc, false); - nc->ProductString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iProduct, stringDesc, false); - nc->LangIdString = XmlGetLangIdString(connectionInfo->DeviceDescriptor.iProduct, stringDesc); - nc->SerialString = XmlGetStringDescriptor(connectionInfo->DeviceDescriptor.iSerialNumber, stringDesc, false); - - // Validate configuration - if (connectionInfo->DeviceDescriptor.bNumConfigurations != 1) - { - nc->ConfigurationCountError = gcnew String("WARNING: Most host controllers will only work with "\ - "one configuration per speed"); - } - } - return; -} - - -/***************************************************************************** - - XmlAddExternalHub() - - Add a external to the parent Host Controller or hub. This is determined by the - last object pushed on the stack - *****************************************************************************/ -HRESULT XmlAddExternalHub(PSTR ehName, PUSBEXTERNALHUBINFO ehInfo) -{ - HRESULT hr = S_OK; - Object ^ parent = gXmlStack->Peek(); - ExternalHubType ^exHub = nullptr; - - UNREFERENCED_PARAMETER(ehName); - - if (NULL == ehInfo) - { - return E_FAIL; - } - - exHub = AddExternalHub(parent); - - if (exHub != nullptr) - { - exHub->HubName = PACHAR_TO_STRING(ehInfo->HubName); - - if (NULL != ehInfo->UsbDeviceProperties) - { - exHub->HwId = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->HwId); - exHub->DeviceId = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceId); - exHub->ServiceName = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->Service); - exHub->DeviceName = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceDesc); - exHub->DeviceClass = PACHAR_TO_STRING(ehInfo->UsbDeviceProperties->DeviceClass); - } - - exHub->HubNodeInformation = gcnew HubNodeInformationType(); - XmlAddHubNodeInformation(exHub->HubNodeInformation, ehInfo->HubInfo); - - exHub->HubInformationEx = gcnew HubInformationExType(); - XmlAddHubInformationEx(exHub->HubInformationEx, ehInfo->HubInfoEx); - - exHub->HubCapabilityEx = gcnew HubCapabilitiesExType(); - XmlAddHubCapabilitiesEx(exHub->HubCapabilityEx, ehInfo->HubCapabilityEx); - - exHub->ConnectionInfo = gcnew NodeConnectionInfoExType(); - - // Update protocol - if (NULL != ehInfo->ConnectionInfo) - { - switch(ehInfo->ConnectionInfo->Speed) - { - case UsbLowSpeed: - case UsbFullSpeed: - exHub->UsbProtocol = gcnew String(USB_1_1); - break; - case UsbHighSpeed: - exHub->UsbProtocol = gcnew String(USB_2_0); - break; - case UsbSuperSpeed: - exHub->UsbProtocol = gcnew String(USB_3_0); - break; - } - } - - // Add connection info - XmlAddConnectionInfo( - exHub->ConnectionInfo, - ehInfo->ConnectionInfo, - (PUSBDEVICEINFO) ehInfo, - ehInfo->StringDescs, - ehInfo->DeviceInfoNode - ); - - // Add port connectors - if (NULL != ehInfo->PortConnectorProps) - { - exHub->PortConnector = gcnew PortConnectorType(); - - XmlAddPortConnectorProps( - exHub->PortConnector, - ehInfo->PortConnectorProps - ); - } - // Add connection info V2 - exHub->ConnectionInfoV2 = gcnew NodeConnectionInfoExV2Type(); - - XmlAddConnectionInfoV2( - exHub->ConnectionInfoV2, - ehInfo->ConnectionInfoV2 - ); - - // Add configuration descriptor - if (NULL != ehInfo->ConfigDesc) - { - exHub->DeviceConfiguration = XmlGetConfigDescriptors( - (PUSBDEVICEINFO) ehInfo, - (PUSB_CONFIGURATION_DESCRIPTOR) (ehInfo->ConfigDesc + 1), - ehInfo->StringDescs - ); - } - - // Add BOS descriptor - if (NULL != ehInfo->BosDesc) - { - exHub->BosDescriptor = XmlGetBosDescriptor((PUSB_BOS_DESCRIPTOR) (ehInfo->BosDesc + 1), ehInfo->StringDescs); - } - - gXmlStack->Push(exHub); - } - else - { - hr = E_FAIL; - } - return hr; -} - -/***************************************************************************** - - XmlGetBosDescriptor() - - Gets the Bos descriptor object for given BOS descriptor - *****************************************************************************/ -UsbBosDescriptorType ^ XmlGetBosDescriptor( - PUSB_BOS_DESCRIPTOR bosDesc, - PSTRING_DESCRIPTOR_NODE stringDesc - ) -{ - PUSB_COMMON_DESCRIPTOR commonDesc = NULL; - PUSB_DEVICE_CAPABILITY_DESCRIPTOR capDesc = NULL; - UsbBosDescriptorType ^ bosXmlDesc = nullptr; - ArrayList ^usb20CapExtDescList = gcnew ArrayList(); - ArrayList ^usbSuperSpeedExtDescList = gcnew ArrayList(); - ArrayList ^usbContIdCapExtDescList = gcnew ArrayList(); - ArrayList ^usbUnknownDescList = gcnew ArrayList(); - ArrayList ^usbBillboardDescList = gcnew ArrayList(); - - if(NULL == bosDesc) - { - return nullptr; - } - - // Initialize attributes - bosXmlDesc = gcnew UsbBosDescriptorType(); - bosXmlDesc->BLength = bosDesc->bLength; - bosXmlDesc->BDescriptorType = bosDesc->bDescriptorType; - bosXmlDesc->WTotalLength = bosDesc->wTotalLength; - bosXmlDesc->BNumDeviceCaps = bosDesc->bNumDeviceCaps; - - commonDesc = (PUSB_COMMON_DESCRIPTOR) bosDesc; - - while ((commonDesc = GetNextDescriptor((PUSB_COMMON_DESCRIPTOR) bosDesc, - bosDesc->wTotalLength, - commonDesc, - -1)) != NULL) - { - switch (commonDesc->bDescriptorType) - { - case USB_DEVICE_CAPABILITY_DESCRIPTOR_TYPE: - capDesc = (PUSB_DEVICE_CAPABILITY_DESCRIPTOR)commonDesc; - switch (capDesc->bDevCapabilityType) - { - case USB_DEVICE_CAPABILITY_USB20_EXTENSION: - usb20CapExtDescList->Add( - XmlGetUsb20CapabilityExtensionDescriptor( - (PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR)capDesc - ) - ); - break; - case USB_DEVICE_CAPABILITY_SUPERSPEED_USB: - usbSuperSpeedExtDescList->Add( - XmlGetSuperSpeedCapabilityExtensionDescriptor( - (PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR)capDesc - ) - ); - break; - case USB_DEVICE_CAPABILITY_CONTAINER_ID: - usbContIdCapExtDescList->Add( - XmlGetContainerIdCapabilityExtensionDescriptor( - (PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR)capDesc - ) - ); - break; - case USB_DEVICE_CAPABILITY_BILLBOARD: - usbBillboardDescList->Add( - XmlGetBillboardCapabilityDescriptor( - (PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) capDesc, - stringDesc - ) - ); - break; - default: - usbUnknownDescList->Add( - XmlGetUnknownDescriptor( - (PUSB_COMMON_DESCRIPTOR) capDesc - ) - ); - break; - } - break; - default: - usbUnknownDescList->Add(XmlGetUnknownDescriptor(commonDesc)); - break; - } - } - - // Convert lists to arrays for and add to Bos Descriptor - bosXmlDesc->UnknownDescriptor = reinterpret_cast^> ( - usbUnknownDescList->ToArray(UsbDeviceUnknownDescriptorType::typeid) - ); - bosXmlDesc->UsbSuperSpeedExtensionDescriptor = reinterpret_cast^> ( - usbSuperSpeedExtDescList->ToArray(UsbSuperSpeedExtensionDescriptorType::typeid) - ); - bosXmlDesc->UsbUsb20ExtensionDescriptor = reinterpret_cast^> ( - usb20CapExtDescList->ToArray(UsbUsb20ExtensionDescriptorType::typeid) - ); - bosXmlDesc->UsbDispContIdCapExtDescriptor = reinterpret_cast^> ( - usbContIdCapExtDescList->ToArray(UsbDispContIdCapExtDescriptorType::typeid) - ); - bosXmlDesc->UsbBillboardCapabilityDescriptor = reinterpret_cast^> ( - usbBillboardDescList->ToArray(UsbBillboardCapabilityDescriptorType::typeid) - ); - - return bosXmlDesc; -} - - -/***************************************************************************** - - XmlGetUsb20CapabilityExtensionDescriptor() - - Gets a Usb20Capability extension descriptor object from the given descriptor - *****************************************************************************/ -UsbUsb20ExtensionDescriptorType ^ XmlGetUsb20CapabilityExtensionDescriptor( - PUSB_DEVICE_CAPABILITY_USB20_EXTENSION_DESCRIPTOR capDesc - ) -{ - UsbUsb20ExtensionDescriptorType ^ capXmlDesc = nullptr; - - if(NULL == capDesc) - { - return nullptr; - } - - capXmlDesc = gcnew UsbUsb20ExtensionDescriptorType(); - - capXmlDesc->BLength = capDesc->bLength; - capXmlDesc->BDescriptorType = capDesc->bDescriptorType; - capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; - capXmlDesc->BmAttributes = capDesc->bmAttributes.AsUlong; - - if (capDesc->bmAttributes.AsUlong & USB_DEVICE_CAPABILITY_USB20_EXTENSION_BMATTRIBUTES_RESERVED_MASK) - { - capXmlDesc->ReservedBitError = gcnew String("ERROR: bits 31..2 and bit 0 are reserved and must be 0"); - } - if (capDesc->bmAttributes.LPMCapable == 1) - { - capXmlDesc->SupportsLinkPowerManagement = true; - } - - return capXmlDesc; -} - -/***************************************************************************** - - XmlGetSuperSpeedCapabilityExtensionDescriptor() - - Gets a Super speed capability extension descriptor object from the given descriptor - *****************************************************************************/ -UsbSuperSpeedExtensionDescriptorType ^ XmlGetSuperSpeedCapabilityExtensionDescriptor( - PUSB_DEVICE_CAPABILITY_SUPERSPEED_USB_DESCRIPTOR capDesc - ) -{ - UsbSuperSpeedExtensionDescriptorType ^ capXmlDesc = nullptr; - - if(NULL == capDesc) - { - return nullptr; - } - - capXmlDesc = gcnew UsbSuperSpeedExtensionDescriptorType(); - - capXmlDesc->BLength = capDesc->bLength; - capXmlDesc->BDescriptorType = capDesc->bDescriptorType; - capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; - capXmlDesc->BmAttributes = capDesc->bmAttributes; - capXmlDesc->BU1DevExitLat = capDesc->bU1DevExitLat; - capXmlDesc->WSpeedsSupported = capDesc->wSpeedsSupported; - capXmlDesc->WU2DevExitLat = capDesc->wU2DevExitLat; - capXmlDesc->BFunctionalitySupport = capDesc->bFunctionalitySupport; - - // Add descriptive fields - if (capDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_RESERVED_MASK) - { - capXmlDesc->ReservedAttributesBitError = gcnew String("ERROR: bits 7:2 and bit 0 are reserved"); - } - if (capDesc->bmAttributes & USB_DEVICE_CAPABILITY_SUPERSPEED_BMATTRIBUTES_LTM_CAPABLE) - { - capXmlDesc->LatencyToleranceMsgCapable = true; - } - if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_LOW) - { - capXmlDesc->SupportsLowSpeed = true; - } - if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_FULL) - { - capXmlDesc->SupportsFullSpeed = true; - } - if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_HIGH) - { - capXmlDesc->SupportsHighSpeed = true; - } - if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_SUPER) - { - capXmlDesc->SupportsSuperSpeed = true; - } - if (capDesc->wSpeedsSupported & USB_DEVICE_CAPABILITY_SUPERSPEED_SPEEDS_SUPPORTED_RESERVED_MASK) - { - capXmlDesc->ReservedSpeedError = gcnew String("ERROR: bits 15:4 are reserved"); - } - - - switch (capDesc->bFunctionalitySupport) - { - case UsbLowSpeed: - capXmlDesc->LowestSpeed = gcnew String("low-speed"); - break; - case UsbFullSpeed: - capXmlDesc->LowestSpeed = gcnew String("full-speed"); - break; - case UsbHighSpeed: - capXmlDesc->LowestSpeed = gcnew String("high-speed"); - break; - case UsbSuperSpeed: - capXmlDesc->LowestSpeed = gcnew String("SuperSpeed"); - break; - default: - capXmlDesc->LowestSpeed = gcnew String("ERROR: Invalid value"); - break; - } - - if (capDesc->bU1DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U1_DEVICE_EXIT_MAX_VALUE) - { - capXmlDesc->U1DevExitLatencyString = String::Format("Less than {0} micro-seconds", capDesc->bU1DevExitLat); - } - else - { - capXmlDesc->U1DevExitLatencyString = gcnew String("ERROR: Invalid value"); - } - - if (capDesc->wU2DevExitLat <= USB_DEVICE_CAPABILITY_SUPERSPEED_U2_DEVICE_EXIT_MAX_VALUE) - { - capXmlDesc->U2DevExitLatencyString = String::Format("Less than {0} micro-seconds", capDesc->wU2DevExitLat); - } - else - { - capXmlDesc->U2DevExitLatencyString = gcnew String("ERROR: Invalid value"); - } - - return capXmlDesc; -} - -/***************************************************************************** - - XmlGetContainerIdCapabilityExtensionDescriptor() - - Gets a Usb20Capability extension descriptor object from the given descriptor - *****************************************************************************/ -UsbDispContIdCapExtDescriptorType ^ XmlGetContainerIdCapabilityExtensionDescriptor( - PUSB_DEVICE_CAPABILITY_CONTAINER_ID_DESCRIPTOR capDesc - ) -{ - UsbDispContIdCapExtDescriptorType ^ capXmlDesc = nullptr; - LPGUID pGuid = NULL; - - if(NULL == capDesc) - { - return nullptr; - } - - capXmlDesc = gcnew UsbDispContIdCapExtDescriptorType(); - - capXmlDesc->BLength = capDesc->bLength; - capXmlDesc->BDescriptorType = capDesc->bDescriptorType; - capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; - capXmlDesc->BReserved = capDesc->bReserved; - - if (capDesc->bReserved != 0) - { - capXmlDesc->ReservedBitError = gcnew String("ERROR: field is reserved and should be zero"); - } - - pGuid = (LPGUID) capDesc->ContainerID; - - capXmlDesc->ContainerIdStr = String::Format("{0:X}-{1:X}-{2:X}-{3:X}{4:X}-{5:X}{6:X}{7:X}{8:X}{9:X}{10:X}", - pGuid->Data1, - pGuid->Data2, - pGuid->Data3, - pGuid->Data4[0], - pGuid->Data4[1], - pGuid->Data4[2], - pGuid->Data4[3], - pGuid->Data4[4], - pGuid->Data4[5], - pGuid->Data4[6], - pGuid->Data4[7]); - - return capXmlDesc; -} - - -/***************************************************************************** - -XmlGetBillboardCapabilityDescriptor() - -Gets a billboard capability descriptor from a given descriptor -*****************************************************************************/ -UsbBillboardCapabilityDescriptorType ^ XmlGetBillboardCapabilityDescriptor( - PUSB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR capDesc, - PSTRING_DESCRIPTOR_NODE stringDesc - ) -{ - UCHAR i = 0; - UCHAR bNumAlternateModes = 0; - UCHAR alternateModeConfiguration = 0; - UsbBillboardCapabilityDescriptorType ^ capXmlDesc = nullptr; - UsbBillboardSVIDType ^ svidXmlDesc = nullptr; - ArrayList ^ usbSVIDDescList = gcnew ArrayList(); - - - if (NULL == capDesc) - { - return nullptr; - } - - capXmlDesc = gcnew UsbBillboardCapabilityDescriptorType(); - - - capXmlDesc->BLength = capDesc->bLength; - capXmlDesc->BDescriptorType = capDesc->bDescriptorType; - capXmlDesc->BDevCapabilityType = capDesc->bDevCapabilityType; - capXmlDesc->IAddtionalInfoURL = capDesc->iAddtionalInfoURL; - capXmlDesc->BNumberOfAlternateModes = capDesc->bNumberOfAlternateModes; - capXmlDesc->BPreferredAlternateMode = capDesc->bPreferredAlternateMode; - capXmlDesc->CalculatedBLength = sizeof(USB_DEVICE_CAPABILITY_BILLBOARD_DESCRIPTOR) + - sizeof(capDesc->AlternateMode[0]) * (capDesc->bNumberOfAlternateModes - 1); - capXmlDesc->BillboardDescriptorErrors = gcnew String(""); - capXmlDesc->AddtionalInfoURL = XmlGetStringDescriptor( - capDesc->iAddtionalInfoURL, - stringDesc, - false - ); - - if (capDesc->VconnPower.NoVconnPowerRequired) - { - capXmlDesc->VConnPower = gcnew String("The adapter does not require Vconn Power. Bits 2..0 ignored"); - } - else - { - switch (capDesc->VconnPower.VConnPowerNeededForFullFunctionality) - { - case 0: - capXmlDesc->VConnPower = gcnew String("1W needed by adapter for full functionality"); - break; - case 1: - capXmlDesc->VConnPower = gcnew String("1.5W needed by adapter for full functionality"); - break; - case 7: - capXmlDesc->BillboardDescriptorErrors += "ERROR: VConnPowerNeededForFullFunctionality - Reserved value being used"; - break; - default: - capXmlDesc->VConnPower = gcnew String(String::Format("{0} W needed by adapter for full functionality", capDesc->VconnPower.VConnPowerNeededForFullFunctionality)); - } - } - - if (capDesc->bNumberOfAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) - { - capXmlDesc->BillboardDescriptorErrors += "ERROR: Invalid bNumberofAlternateModes; "; - } - if (capDesc->VconnPower.Reserved) - { - capXmlDesc->BillboardDescriptorErrors += "ERROR: Reserved bits in VCONN Power being used; "; - } - if (capDesc->bReserved) - { - capXmlDesc->BillboardDescriptorErrors += "ERROR: bReserved being used; "; - } - - bNumAlternateModes = capDesc->bNumberOfAlternateModes; - if (bNumAlternateModes > BILLBOARD_MAX_NUM_ALT_MODE) - { - bNumAlternateModes = BILLBOARD_MAX_NUM_ALT_MODE; - } - for (i = 0; i < bNumAlternateModes; i++) - { - svidXmlDesc = gcnew UsbBillboardSVIDType(); - alternateModeConfiguration = ((capDesc->bmConfigured[i / 4]) >> ((i % 4) * 2)) & 0x3; - svidXmlDesc->WSVID = capDesc->AlternateMode[i].wSVID; - svidXmlDesc->BAlternateMode = capDesc->AlternateMode[i].bAlternateMode; - svidXmlDesc->IAlternateModeString = capDesc->AlternateMode[i].iAlternateModeSetting; - svidXmlDesc->AlternateModeString = XmlGetStringDescriptor( - capDesc->AlternateMode[i].iAlternateModeSetting, - stringDesc, - false - ); - - switch (alternateModeConfiguration) - { - case 0: - svidXmlDesc->Description = gcnew String("Unspecified Error"); - break; - case 1: - svidXmlDesc->Description = gcnew String("Alternate Mode configuration not attempted"); - break; - case 2: - svidXmlDesc->Description = gcnew String("Alternate Mode configuration attempted but unsuccessful"); - break; - case 3: - svidXmlDesc->Description = gcnew String("Alternate Mode configuration successful"); - break; - } - usbSVIDDescList->Add(svidXmlDesc); - } - capXmlDesc->UsbBillboardSVID = reinterpret_cast^> ( - usbSVIDDescList->ToArray(UsbBillboardSVIDType::typeid)); - - return capXmlDesc; -} - -/***************************************************************************** - - XmlAddUsbDevice() - - Add a external to the parent Host Controller or hub. This is determined by the - last object pushed on the stack - *****************************************************************************/ -HRESULT XmlAddUsbDevice(PSTR devName, PUSBDEVICEINFO deviceInfo) -{ - HRESULT hr = S_OK; - Object ^ parent = gXmlStack->Peek(); - UsbDeviceType ^usbDevice = nullptr; - NoDeviceType ^noDevice = nullptr; - - if (NULL == deviceInfo) - { - return E_FAIL; - } - - if (deviceInfo->ConfigDesc == NULL) - { - // There is no USB device on this port, add a NoDevice type here instead of USB device - noDevice = AddDisconnectedPort(parent); - - if (nullptr != noDevice) - { - noDevice->UsbPortNumber = gcnew String(""); - noDevice->UsbPortNumber += deviceInfo->ConnectionInfo->ConnectionIndex; - noDevice->Name = PACHAR_TO_STRING(devName); - } - else - { - hr = E_FAIL; - } - } - - else - { - usbDevice = AddUsbDevice(parent); - - if (nullptr != usbDevice) - { - // Update device information - if (NULL != deviceInfo->UsbDeviceProperties) - { - usbDevice->HwId = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->HwId); - usbDevice->DeviceId = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceId); - usbDevice->ServiceName = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->Service); - usbDevice->DeviceName = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceDesc); - usbDevice->DeviceClass = PACHAR_TO_STRING(deviceInfo->UsbDeviceProperties->DeviceClass); - } - - // Update port number - usbDevice->UsbPortNumber = gcnew String(""); - usbDevice->UsbPortNumber += deviceInfo->ConnectionInfo->ConnectionIndex; - usbDevice->ConnectionInfo = gcnew NodeConnectionInfoExType(); - - // Update protocol - if (NULL != deviceInfo->ConnectionInfo) - { - switch(deviceInfo->ConnectionInfo->Speed) - { - case UsbLowSpeed: - case UsbFullSpeed: - usbDevice->UsbProtocol = gcnew String(USB_1_1); - break; - case UsbHighSpeed: - usbDevice->UsbProtocol = gcnew String(USB_2_0); - break; - case UsbSuperSpeed: - usbDevice->UsbProtocol = gcnew String(USB_3_0); - break; - } - } - - // Add connection info - XmlAddConnectionInfo( - usbDevice->ConnectionInfo, - deviceInfo->ConnectionInfo, - (PUSBDEVICEINFO) deviceInfo, - deviceInfo->StringDescs, - deviceInfo->DeviceInfoNode - ); - - // Add port connector - if (NULL != deviceInfo->PortConnectorProps) - { - usbDevice->PortConnector = gcnew PortConnectorType(); - - XmlAddPortConnectorProps( - usbDevice->PortConnector, - deviceInfo->PortConnectorProps - ); - } - - // Add connectiontion info V2 - if (NULL != deviceInfo->ConnectionInfoV2) - { - usbDevice->ConnectionInfoV2 = gcnew NodeConnectionInfoExV2Type(); - XmlAddConnectionInfoV2( - usbDevice->ConnectionInfoV2, - deviceInfo->ConnectionInfoV2 - ); - } - - // Add configuration descriptor - if (NULL != deviceInfo->ConfigDesc) - { - // The device configuration is allocated by XmlGetConfigDescriptors() - usbDevice->DeviceConfiguration = XmlGetConfigDescriptors( - (PUSBDEVICEINFO) deviceInfo, - (PUSB_CONFIGURATION_DESCRIPTOR) (deviceInfo->ConfigDesc + 1), - deviceInfo->StringDescs - ); - } - - // Add BOS descriptor - if (NULL != deviceInfo->BosDesc) - { - usbDevice->BosDescriptor = XmlGetBosDescriptor( - (PUSB_BOS_DESCRIPTOR) (deviceInfo->BosDesc + 1), - deviceInfo->StringDescs - ); - } - } - else - { - hr = E_FAIL; - } - } - return hr; -} - -/***************************************************************************** - - XmlAddRootHub() - - Add a root hub to the parent Host Controller - *****************************************************************************/ -HRESULT XmlAddRootHub(PSTR rhName, PUSBROOTHUBINFO rhInfo) -{ - HRESULT hr = S_OK; - Object ^ parent = gXmlStack->Peek(); - HostControllerType ^ hcParent = nullptr; - PSTR rootHubName = rhInfo->HubName; - - UNREFERENCED_PARAMETER(rhName); - - hcParent = dynamic_cast (parent); - - if (hcParent != nullptr) - { - RootHubType ^ rh = nullptr; - hcParent = (HostControllerType ^) parent; - hcParent->RootHub = gcnew RootHubType(); - - rh = hcParent->RootHub; - rh->HubName = PACHAR_TO_STRING(rootHubName); - - if (NULL != rhInfo->UsbDeviceProperties) - { - rh->HwId = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->HwId); - rh->DeviceId = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceId); - rh->ServiceName = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->Service); - rh->DeviceName = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceDesc); - rh->DeviceClass = PACHAR_TO_STRING(rhInfo->UsbDeviceProperties->DeviceClass); - - // Roothub protocol is same as HC protocol - rh->UsbProtocol = hcParent->UsbProtocol; - } - - rh->HubNodeInformation = gcnew HubNodeInformationType(); - XmlAddHubNodeInformation(rh->HubNodeInformation, rhInfo->HubInfo); - - rh->HubInformationEx = gcnew HubInformationExType(); - XmlAddHubInformationEx(rh->HubInformationEx, rhInfo->HubInfoEx); - - rh->HubCapabilityEx = gcnew HubCapabilitiesExType(); - XmlAddHubCapabilitiesEx(rh->HubCapabilityEx, rhInfo->HubCapabilityEx); - - // Push root hub on to stack - gXmlStack->Push(rh); - } - else - { - // Root hub should be connected to a host controller - hr = E_FAIL; - } - return S_OK; -} - -/***************************************************************************** - - XmlSetVersion() - - Set version information in XML tree - *****************************************************************************/ -VOID XmlSetVersion( - UCHAR uvcMajorVersion, - UCHAR uvcMinorVersion, - UCHAR uvcMajorSpecVersion, - UCHAR uvcMinorSpecVersion - ) -{ - MachineInfoType ^ mInfo; - gXmlView->MachineInfo = gcnew MachineInfoType(); - - mInfo = gXmlView->MachineInfo; - - mInfo->UvcMajorVersion = uvcMajorVersion; - mInfo->UvcMinorVersion = uvcMinorVersion; - mInfo->UvcMajorSpecVersion = uvcMajorSpecVersion; - mInfo->UvcMinorSpecVersion = uvcMinorSpecVersion; - -} - -/***************************************************************************** - - InitXmlHelper() - - Initialize XML helper - *****************************************************************************/ -HRESULT InitXmlHelper() -{ - HRESULT hr = S_OK; - - (XmlGlobal::Instance())->ViewAll = gcnew UvcViewAll(); - (XmlGlobal::Instance())->ViewAll->UvcView = gcnew UvcViewType(); - - // - // Initialize fields to null so we can check against them for allocation - // - (XmlGlobal::Instance())->ViewAll->UvcView->MachineInfo = nullptr; - (XmlGlobal::Instance())->ViewAll->UvcView->UsbTree = nullptr; - - XmlSetVersion( - UVC_SPEC_MAJOR_VERSION, - UVC_SPEC_MINOR_VERSION, - USBVIEW_MAJOR_VERSION, - USBVIEW_MINOR_VERSION - ); - - gXmlStack->Push(gXmlView); - - gXmlViewInitialized = TRUE; - - return hr; -} - -/***************************************************************************** - - SaveXml() - - Saves the inmemory USB view as XML file - *****************************************************************************/ -HRESULT SaveXml(LPTSTR szfileName, DWORD dwCreationDisposition) -{ - HRESULT hr = S_OK; - - if (gXmlViewInitialized) - { - try - { - String ^fileName = PACHAR_TO_STRING(szfileName); - XmlSerializer ^ serializer = gcnew XmlSerializer(UvcViewAll::typeid); - TextWriter ^ writer = nullptr; - - if (dwCreationDisposition != CREATE_ALWAYS) - { - // Check if file exits and return failure if it does - if (File::Exists(fileName)) - { - hr = HRESULT_FROM_WIN32(ERROR_FILE_EXISTS); - } - } - - // Check if file name is NULL - if (String::IsNullOrEmpty(fileName)) - { - hr = E_INVALIDARG; - } - - if (SUCCEEDED(hr)) - { - writer = gcnew StreamWriter(fileName); - serializer->Serialize(writer, (XmlGlobal::Instance())->ViewAll); - writer->Close(); - } - - // Release and reinit XML View for next iteration if requested - ReleaseXmlWriter(); - InitXmlHelper(); - - } - catch(Exception ^ ex) - { - hr = (HRESULT) Marshal::GetHRForException(ex); - } - } - else - { - hr = E_FAIL; - } - - return hr; -} - - -/***************************************************************************** - - ReleaseXmlWriter() - - *****************************************************************************/ -HRESULT ReleaseXmlWriter() -{ - HRESULT hr = S_OK; - - if (gXmlViewInitialized) - { - gXmlViewInitialized = FALSE; - delete XmlGlobal::Instance(); - } - - return hr; -} - diff --git a/tests/projects/winsdk/usbview/xmlhelper.h b/tests/projects/winsdk/usbview/xmlhelper.h deleted file mode 100644 index 1da37d97b..000000000 --- a/tests/projects/winsdk/usbview/xmlhelper.h +++ /dev/null @@ -1,41 +0,0 @@ -/*++ - -Copyright (c) 1997-2011 Microsoft Corporation - -Module Name: - - XMLHELPER.H - -Abstract: - - This helper file declaration for XML helper APIs - -Environment: - - user mode - -Revision History: - - 05-05-11 : created - ---*/ - -#pragma once - -/***************************************************************************** - I N C L U D E S -*****************************************************************************/ -#include "uvcview.h" - -EXTERN_C HRESULT InitXmlHelper(); -EXTERN_C HRESULT ReleaseXmlWriter(); -EXTERN_C HRESULT SaveXml(LPTSTR szfileName, DWORD dwCreationDisposition); -EXTERN_C HRESULT XmlAddHostController( - PSTR hcName, - PUSBHOSTCONTROLLERINFO hcInfo - ); -EXTERN_C HRESULT XmlAddRootHub(PSTR rhName, PUSBROOTHUBINFO rhInfo); -EXTERN_C HRESULT XmlAddExternalHub(PSTR ehName, PUSBEXTERNALHUBINFO ehInfo); -EXTERN_C HRESULT XmlAddUsbDevice(PSTR devName, PUSBDEVICEINFO deviceInfo); -EXTERN_C VOID XmlNotifyEndOfNodeList(PVOID pContext); - diff --git a/tests/projects/winsdk/windemo/main.cpp b/tests/projects/winsdk/windemo/main.cpp deleted file mode 100644 index a8340d936..000000000 --- a/tests/projects/winsdk/windemo/main.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// testw.cpp : Defines the entry point for the application. -// - -#include "stdafx.h" -#include "test.h" - -#define MAX_LOADSTRING 100 - -// Global Variables: -HINSTANCE hInst; // current instance -TCHAR szTitle[MAX_LOADSTRING]; // The title bar text -TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name - -// Forward declarations of functions included in this code module: -ATOM MyRegisterClass(HINSTANCE hInstance); -BOOL InitInstance(HINSTANCE, int); -LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); - -int APIENTRY _tWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, - int nCmdShow) -{ - UNREFERENCED_PARAMETER(hPrevInstance); - UNREFERENCED_PARAMETER(lpCmdLine); - - // TODO: Place code here. - MSG msg; - HACCEL hAccelTable; - - // Initialize global strings - LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); - LoadString(hInstance, IDC_TESTW, szWindowClass, MAX_LOADSTRING); - MyRegisterClass(hInstance); - - // Perform application initialization: - if (!InitInstance (hInstance, nCmdShow)) - { - return FALSE; - } - - hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTW)); - - // Main message loop: - while (GetMessage(&msg, NULL, 0, 0)) - { - if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - return (int) msg.wParam; -} - - - -// -// FUNCTION: MyRegisterClass() -// -// PURPOSE: Registers the window class. -// -// COMMENTS: -// -// This function and its usage are only necessary if you want this code -// to be compatible with Win32 systems prior to the 'RegisterClassEx' -// function that was added to Windows 95. It is important to call this function -// so that the application will get 'well formed' small icons associated -// with it. -// -ATOM MyRegisterClass(HINSTANCE hInstance) -{ - WNDCLASSEX wcex; - - wcex.cbSize = sizeof(WNDCLASSEX); - - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = WndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTW)); - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TESTW); - wcex.lpszClassName = szWindowClass; - wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); - - return RegisterClassEx(&wcex); -} - -// -// FUNCTION: InitInstance(HINSTANCE, int) -// -// PURPOSE: Saves instance handle and creates main window -// -// COMMENTS: -// -// In this function, we save the instance handle in a global variable and -// create and display the main program window. -// -BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) -{ - HWND hWnd; - - hInst = hInstance; // Store instance handle in our global variable - - hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); - - if (!hWnd) - { - return FALSE; - } - - ShowWindow(hWnd, nCmdShow); - UpdateWindow(hWnd); - - return TRUE; -} - -// -// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) -// -// PURPOSE: Processes messages for the main window. -// -// WM_COMMAND - process the application menu -// WM_PAINT - Paint the main window -// WM_DESTROY - post a quit message and return -// -// -LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - int wmId, wmEvent; - PAINTSTRUCT ps; - HDC hdc; - - switch (message) - { - case WM_COMMAND: - wmId = LOWORD(wParam); - wmEvent = HIWORD(wParam); - // Parse the menu selections: - switch (wmId) - { - case IDM_ABOUT: - DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); - break; - case IDM_EXIT: - DestroyWindow(hWnd); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - break; - case WM_PAINT: - hdc = BeginPaint(hWnd, &ps); - // TODO: Add any drawing code here... - EndPaint(hWnd, &ps); - break; - case WM_DESTROY: - PostQuitMessage(0); - break; - default: - return DefWindowProc(hWnd, message, wParam, lParam); - } - return 0; -} - -// Message handler for about box. -INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -{ - UNREFERENCED_PARAMETER(lParam); - switch (message) - { - case WM_INITDIALOG: - return (INT_PTR)TRUE; - - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - { - EndDialog(hDlg, LOWORD(wParam)); - return (INT_PTR)TRUE; - } - break; - } - return (INT_PTR)FALSE; -} diff --git a/tests/projects/winsdk/windemo/resource.h b/tests/projects/winsdk/windemo/resource.h deleted file mode 100644 index 65ba8f31d..000000000 --- a/tests/projects/winsdk/windemo/resource.h +++ /dev/null @@ -1,31 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by test.rc -// - -#define IDS_APP_TITLE 103 - -#define IDR_MAINFRAME 128 -#define IDD_TESTW_DIALOG 102 -#define IDD_ABOUTBOX 103 -#define IDM_ABOUT 104 -#define IDM_EXIT 105 -#define IDI_TESTW 107 -#define IDI_SMALL 108 -#define IDC_TESTW 109 -#define IDC_MYICON 2 -#ifndef IDC_STATIC -#define IDC_STATIC -1 -#endif -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS - -#define _APS_NO_MFC 130 -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 110 -#endif -#endif diff --git a/tests/projects/winsdk/windemo/small.ico b/tests/projects/winsdk/windemo/small.ico deleted file mode 100644 index d551aa3aa..000000000 Binary files a/tests/projects/winsdk/windemo/small.ico and /dev/null differ diff --git a/tests/projects/winsdk/windemo/stdafx.cpp b/tests/projects/winsdk/windemo/stdafx.cpp deleted file mode 100644 index 50daaa27d..000000000 --- a/tests/projects/winsdk/windemo/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// testw.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/tests/projects/winsdk/windemo/stdafx.h b/tests/projects/winsdk/windemo/stdafx.h deleted file mode 100644 index de0dfa3cd..000000000 --- a/tests/projects/winsdk/windemo/stdafx.h +++ /dev/null @@ -1,21 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include - -// C RunTime Header Files -#include -#include -#include -#include - - -// TODO: reference additional headers your program requires here diff --git a/tests/projects/winsdk/windemo/targetver.h b/tests/projects/winsdk/windemo/targetver.h deleted file mode 100644 index f583181df..000000000 --- a/tests/projects/winsdk/windemo/targetver.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -// The following macros define the minimum required platform. The minimum required platform -// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run -// your application. The macros work by enabling all features available on platform versions up to and -// including the version specified. - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. -#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. -#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. -#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. -#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. -#endif diff --git a/tests/projects/winsdk/windemo/test b/tests/projects/winsdk/windemo/test deleted file mode 100644 index 33639f71c..000000000 --- a/tests/projects/winsdk/windemo/test +++ /dev/null @@ -1,150 +0,0 @@ -//Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#ifndef APSTUDIO_INVOKED -#include "targetver.h" -#endif -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 -#pragma code_page(936) - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. - -IDI_TESTW ICON "testw.ico" -IDI_SMALL ICON "small.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDC_TESTW MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "E&xit", IDM_EXIT - END - POPUP "&Help" - BEGIN - MENUITEM "&About ...", IDM_ABOUT - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDC_TESTW ACCELERATORS -BEGIN - "?", IDM_ABOUT, ASCII, ALT - "/", IDM_ABOUT, ASCII, ALT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About testw" -FONT 8, "MS Shell Dlg" -BEGIN - ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20 - LTEXT "testw, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX - LTEXT "Copyright (C) 2020",IDC_STATIC,42,26,114,8 - DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP -END - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_ABOUTBOX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 163 - TOPMARGIN, 7 - BOTTOMMARGIN, 55 - END -END -#endif // APSTUDIO_INVOKED - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#ifndef APSTUDIO_INVOKED\r\n" - "#include ""targetver.h""\r\n" - "#endif\r\n" - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDC_TESTW "TESTW" - IDS_APP_TITLE "testw" -END - -#endif -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/tests/projects/winsdk/windemo/test.h b/tests/projects/winsdk/windemo/test.h deleted file mode 100644 index e60f2eb7e..000000000 --- a/tests/projects/winsdk/windemo/test.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "resource.h" diff --git a/tests/projects/winsdk/windemo/test.ico b/tests/projects/winsdk/windemo/test.ico deleted file mode 100644 index d551aa3aa..000000000 Binary files a/tests/projects/winsdk/windemo/test.ico and /dev/null differ diff --git a/tests/projects/winsdk/windemo/test.rc b/tests/projects/winsdk/windemo/test.rc deleted file mode 100644 index 9ef96ba63..000000000 --- a/tests/projects/winsdk/windemo/test.rc +++ /dev/null @@ -1,150 +0,0 @@ -//Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#ifndef APSTUDIO_INVOKED -#include "targetver.h" -#endif -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE 9, 1 -#pragma code_page(936) - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. - -IDI_TESTW ICON "test.ico" -IDI_SMALL ICON "small.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDC_TESTW MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "E&xit", IDM_EXIT - END - POPUP "&Help" - BEGIN - MENUITEM "&About ...", IDM_ABOUT - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDC_TESTW ACCELERATORS -BEGIN - "?", IDM_ABOUT, ASCII, ALT - "/", IDM_ABOUT, ASCII, ALT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "About testw" -FONT 8, "MS Shell Dlg" -BEGIN - ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20 - LTEXT "testw, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX - LTEXT "Copyright (C) 2020",IDC_STATIC,42,26,114,8 - DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP -END - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_ABOUTBOX, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 163 - TOPMARGIN, 7 - BOTTOMMARGIN, 55 - END -END -#endif // APSTUDIO_INVOKED - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#ifndef APSTUDIO_INVOKED\r\n" - "#include ""targetver.h""\r\n" - "#endif\r\n" - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDC_TESTW "TESTW" - IDS_APP_TITLE "testw" -END - -#endif -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED diff --git a/tests/projects/winsdk/windemo/xmake.lua b/tests/projects/winsdk/windemo/xmake.lua deleted file mode 100644 index 1f492822e..000000000 --- a/tests/projects/winsdk/windemo/xmake.lua +++ /dev/null @@ -1,12 +0,0 @@ --- add rules: debug/release -add_rules("mode.debug", "mode.release") - --- define target -target("test") - - -- set kind - add_rules("win.sdk.application") - - -- add files - add_files("*.rc", "*.cpp") - -- cgit v1.3.1